Skip to main content
EEnco.1
Associate III
March 9, 2022
Solved

Unable to convert PDM data to PCM data using pdm2pcm

I'm using a stm32wb55RG. I'm trying to get data from a MEMS PDM microphone and convert it into PCM data. I'm using SAI PDM interface and DMA. So far, I think I manage to receive the PDM data (I get some values from the SAI interface) :

0693W00000KbvY4QAJ.pngI don't know if these values make a sense or not. But when I try to convert these data into PCM using PDM_Filter, I can't get any value in the output buffer.

I provide the code :

#include "main.h"
#include "pdm2pcm_glo.h"
#include "stdio.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
 SAI_HandleTypeDef hsai_BlockA1;
DMA_HandleTypeDef hdma_sai1_a;
 
UART_HandleTypeDef huart1;
 
PCD_HandleTypeDef hpcd_USB_FS;
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_DMA_Init(void);
static void MX_USB_PCD_Init(void);
static void MX_SAI1_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t rxstate = 0;
uint8_t PDM_Buffer[1024];
 
 
 
 
/* PDM-PCM conversion configuration */
PDM_Filter_Handler_t PDM_FilterHandler;
PDM_Filter_Config_t PDM_FilterConfig;
 
/* USER CODE END 0 */
 
/**
 * @brief The application entry point.
 * @retval int
 */
int main(void)
{
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* Configure the system clock */
 SystemClock_Config();
 
/* Configure the peripherals common clocks */
 PeriphCommonClock_Config();
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_USART1_UART_Init();
 MX_USB_PCD_Init();
 MX_DMA_Init();
 MX_SAI1_Init();
 
 PDM_FilterHandler.bit_order = PDM_FILTER_BIT_ORDER_MSB;
 PDM_FilterHandler.endianness = PDM_FILTER_ENDIANNESS_BE;
 PDM_FilterHandler.high_pass_tap = 2104533974;
 PDM_FilterHandler.out_ptr_channels = 1;
 PDM_FilterHandler.in_ptr_channels = 1;
 
 PDM_FilterConfig.output_samples_number = 16;
 PDM_FilterConfig.mic_gain = 24;
 
 PDM_FilterConfig.decimation_factor = PDM_FILTER_DEC_FACTOR_64;
 
 PDM_Filter_Init((PDM_Filter_Handler_t *)(&PDM_FilterHandler));
 PDM_Filter_setConfig((PDM_Filter_Handler_t *)&PDM_FilterHandler, &PDM_FilterConfig);
 
 
 uint16_t pcm_data[4096];
 uint16_t mid_Buffer[16];
 
 uint16_t pcm_index = 0;
 
 HAL_SAI_Receive_DMA(&hsai_BlockA1, &PDM_Buffer[0], 64);
 
 while (1)
 {
 if (rxstate==1){
 PDM_Filter(&PDM_Buffer[0], &mid_Buffer[0], &PDM_FilterHandler);
 for(uint8_t i = 0; i < 64 ; i++){
 pcm_data[pcm_index] = mid_Buffer[i];
 pcm_index++;
 }
 rxstate=0;
 }
 
 if (rxstate==2){
 PDM_Filter(&PDM_Buffer[64], &mid_Buffer[0], &PDM_FilterHandler);
 for(uint8_t i = 0; i < 64 ; i++){
 pcm_data[pcm_index] = mid_Buffer[i];
 pcm_index++;
 }
 rxstate=0;
 }
 
 if(pcm_index==4096){
 HAL_SAI_DMAPause(&hsai_BlockA1);
 //pcm_index = 0;
 }
 }
 
}
 
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai_BlockA1){
 rxstate = 1;
 
}
 
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai_BlockA1){
 rxstate = 2;
}
 
void SystemClock_Config(void)
{
 ...
}
 
void PeriphCommonClock_Config(void)
{
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 
 /** Initializes the peripherals clock
 */
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS;
 PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSI;
 PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE0;
 
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN Smps */
 
 /* USER CODE END Smps */
}
 
/**
 * @brief SAI1 Initialization Function
 * @param None
 * @retval None
 */
static void MX_SAI1_Init(void)
{
 
 /* USER CODE BEGIN SAI1_Init 0 */
 
 /* USER CODE END SAI1_Init 0 */
 
 /* USER CODE BEGIN SAI1_Init 1 */
 
 /* USER CODE END SAI1_Init 1 */
 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;
 hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
 hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
 hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_DISABLE;
 hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
 hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
 hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;
 hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
 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_CLOCK1_ENABLE;
 hsai_BlockA1.FrameInit.FrameLength = 16;
 hsai_BlockA1.FrameInit.ActiveFrameLength = 1;
 hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;
 hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
 hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
 hsai_BlockA1.SlotInit.FirstBitOffset = 0;
 hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
 hsai_BlockA1.SlotInit.SlotNumber = 1;
 hsai_BlockA1.SlotInit.SlotActive = 0x0000FFFF;
 if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN SAI1_Init 2 */
 
 /* USER CODE END SAI1_Init 2 */
 
}

TL DR : Using this : PDM_Filter(&PDM_Buffer[0], &mid_Buffer[0], &PDM_FilterHandler); mid_buffer is stuck to 0 and I don't understand where the problem comes from

    This topic has been closed for replies.
    EEnco.1
    EEnco.1Best answer
    Associate III
    March 10, 2022

    Yes, you can remove all the posts in this page as I managed to fix the issue

    3 replies

    EEnco.1
    EEnco.1Author
    Associate III
    March 9, 2022

    To be removed

    Eleon BORLINI
    ST Employee
    March 9, 2022

    Hi @EEnco.1​ ,

    should I remove this post?

    -Eleon

    EEnco.1
    EEnco.1AuthorBest answer
    Associate III
    March 10, 2022

    Yes, you can remove all the posts in this page as I managed to fix the issue