cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5 PDMtoPCM filter not working

eduarm
Associate

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:

  • I am using the SAI in PDM mode. The configuration of the SAI 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

  • while(1){
  • /* Wait Rx transfer complete event */
    while(bufferStatus != BUFFER_OFFSET_FULL);
    /* Convert PDM data to PCM */
    AUDIO_IN_PDMToPCM(&u16_audioPdmBuf[0], &audioPcmBuf[0], AUDIO_CHANNEL_NUMBER);

    /* Initialize Rx buffer status */
    bufferStatus &= BUFFER_OFFSET_NONE;
    /* Get tick */
    s_ret=HAL_SAI_Receive_IT(&hsai_BlockA1, (uint8_t*)u16_audioPdmBuf, AUDIO_BUFFER_SIZE);
    if(HAL_OK != s_ret)
    {
    Error_Handler();
    }

    for (int i = 0; i < DACSIZE/2; ++i) { //DACSIZE 32
    u32_dataBuff[i] = (uint32_t)audioPcmBuf[i]; // We use this to send to the DAC
    }
    HAL_Delay(1);

}

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:

  1. Why does AUDIO_IN_PDMToPCM only fill 16 values in audioPcmBuf? Shouldn't it fill the entire array?
  2. Why am I seeing a lot of noise? Isn't the library supposed to act as a low-pass filter?
  3. Am I setting something incorrectly, or is the library not compatible with U5?

I look forward to your reply.

2 REPLIES 2
STOne-32
ST Employee

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

Thanks for your answer sir. I will have a look a that.