Skip to main content
Visitor II
March 9, 2022
Solved

Unable to convert PDM data to PCM data using pdm2pcm

  • March 9, 2022
  • 2 replies
  • 2321 views

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.
    Best answer by EEnco.1

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

    2 replies

    EEnco.1Author
    Visitor II
    March 9, 2022

    To be removed

    ST Employee
    March 9, 2022

    Hi @EEnco.1​ ,

    should I remove this post?

    -Eleon

    EEnco.1AuthorAnswer
    Visitor II
    March 10, 2022

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