2024-02-19 05:44 AM - edited 2024-02-19 05:56 AM
Hello everyone,
I am currently attempting to convert PDM data (from a MEMS CMM-4030DT-26354) to PCM data using the libPDMFilter_CM7_IAR_wc32 provided by STM32Cube. However, the results I am obtaining are not as expected. I am expecting a 1000 Hz sine wave tone, but instead, I am getting what appears to be noise (refer to the attached image). It is important to note that the PCM data is being sent to a DAC, which is set to a frequency of approximately 16 kHz.
My setup is as follows:
static void MX_SAI1_Init(void)
{
hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
hsai_BlockA1.Init.DataSize = SAI_DATASIZE_16;
hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_LSB;
hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; SEL pin is conected to VDD
hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_DISABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_HF;
hsai_BlockA1.Init.AudioFrequency =AUDIO_PDM_GET_FS_FREQUENCY(AUDIO_FREQUENCY); //16 kHz
hsai_BlockA1.Init.MckOutput = SAI_MCK_OUTPUT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_MONOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.Init.PdmInit.Activation = ENABLE;
hsai_BlockA1.Init.PdmInit.MicPairsNbr = 1;
hsai_BlockA1.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK2_ENABLE;
hsai_BlockA1.FrameInit.FrameLength = 16;
hsai_BlockA1.FrameInit.ActiveFrameLength = 8;
hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;
hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT; //SAI_FS_BEFOREFIRSTBIT
hsai_BlockA1.SlotInit.FirstBitOffset = 0;
hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hsai_BlockA1.SlotInit.SlotNumber = 1;
hsai_BlockA1.SlotInit.SlotActive = SAI_SLOTACTIVE_0;
}
The frequency that the SAI provides to the MIC is 1024 MHz. The microphone was tested using a low-pass filter, and it worked as expected. Therefore, the issue seems to be with the library.
The library is configured as follows:
/**
* @brief Init PDM Filters.
* @PAram AudioFreq: Audio sampling frequency
* @PAram ChannelNumber: Number of audio channels in the PDM buffer.
* @retval None
*/
static void AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChannelNumber) //16 kHz, only one channel
{
uint32_t index = 0;
/* Enable CRC peripheral to unlock the PDM library */
__HAL_RCC_CRC_CLK_ENABLE();
CRC->CR = CRC_CR_RESET;
for(index = 0; index < ChannelNumber; index++)
{
/* Init PDM filters */
PDM_FilterHandler[index].bit_order = PDM_FILTER_BIT_ORDER_LSB;
PDM_FilterHandler[index].endianness = PDM_FILTER_ENDIANNESS_LE;
PDM_FilterHandler[index].high_pass_tap = 2136746229;
PDM_FilterHandler[index].out_ptr_channels = ChannelNumber;
PDM_FilterHandler[index].in_ptr_channels = ChannelNumber;
PDM_Filter_Init((PDM_Filter_Handler_t *)(&PDM_FilterHandler[index]));
/* Configure PDM filters */
PDM_FilterConfig[index].output_samples_number = AudioFreq/1000;
PDM_FilterConfig[index].mic_gain = 49;
PDM_FilterConfig[index].decimation_factor = PDM_FILTER_DEC_FACTOR_64;
PDM_Filter_setConfig((PDM_Filter_Handler_t *)&PDM_FilterHandler[index], &PDM_FilterConfig[index]);
}
}
/**
* @brief Convert audio format from PDM to PCM.
* @PAram PDMBuf: Pointer to PDM buffer data
* @PAram PCMBuf: Pointer to PCM buffer data
* @PAram ChannelNumber: PDM Channels number.
* @retval None
*/
static void AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf, uint32_t ChannelNumber)
{
uint32_t index = 0;
uint32_t u32_ret=0;
for(index = 0; index < ChannelNumber; index++)
{
u32_ret=PDM_Filter(&((uint8_t*)(PDMBuf))[index], (uint16_t*)&(PCMBuf[index]), &PDM_FilterHandler[index]);
}
if(0 != u32_ret)
{
Error_Handler();
}
}
In the main function, I have the following code
initialization code
/* Init PDM Filters */
AUDIO_IN_PDMToPCM_Init(AUDIO_FREQUENCY, AUDIO_CHANNEL_NUMBER); //#define //AUDIO_FREQUENCY SAI_AUDIO_FREQUENCY_16K
//#define AUDIO_CHANNEL_NUMBER 1U
}
The DAC function
void DAC_Ch1_SineConfig(void)
{
DAC_ChannelConfTypeDef sConfig = {0};
/* Set DAC instance */
hdac1.Instance = DAC1;
/* Initialize DAC */
if (HAL_DAC_Init(&hdac1) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Config Channel */
sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_EXTERNAL;
/* DAC Channel configuration */
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
{
/* Channel configuration Error */
Error_Handler();
}
/* DAC calibration */
if (HAL_DACEx_SelfCalibrate(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* Enable DAC selected channel and associated DMA */
if (HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, u32_dataBuff, 16, DAC_ALIGN_12B_R) != HAL_OK)
{
/* Start DMA Error */
Error_Handler();
}
}
I believe the issue lies with the library. It is unusual that a PDM value of 0 would result in a PCM value of 32768. I have the following questions:
I look forward to your reply.
2024-02-24 12:01 PM
Dear @eduarm ,
I’m not sure it will help, but it seems you are using this pre-compiled library “libPDMFilter_CM7_IAR_wc32” which is compiled for Cortex-M7 Core which is present in our STM32F7 and H7 series with IAR compiler.
U5 has Cortex-M33 core , so may be it is incompatible. I would suggest to check with M4.
Ciao
STOne-32
2024-02-26 09:58 PM
Thanks for your answer sir. I will have a look a that.
2024-06-12 01:13 AM
I can not find any library for M33. Is it possible use M4 Lib for that?