2021-03-15 07:26 AM
I'm having problems with the PDM2PCM lib and am getting desperate.
I have a STM32L151 with an external clock source of 8.192 MHz. The SYSCLK runs with 16.384 MHz. The APB2 (SPI1) runs with 4.096 MHz.
I'm sampling a PDM mic with an 8-bit SPI at 2.048 MHz. The prescaler is on 2, CPOL is low and CPHA is on the 2nd edge.
I'm using the DMA in circular mode, byte-oriented and with memory increment to fill the PDM buffer. I transfer 512 bytes.
My PDM buffer has 2 x 256 bytes for pseudo double buffering and as PCM buffer I have 32 x 16-bit unsigned (uint16_t).
On each half-transfer and full-transfer (every 1ms each), I execute the PDM_Filter function with half of the PDM buffer to fill the PCM buffer. Thus I should get 32 samples per 1ms. I have 64 as decimation factor.
Unfortunately, all I get is junk. Where could the reasoning error be or what did I not understand correctly? Thank you very very much for the help!
Here are some more excerpts from my code:
//buffers
#define PDMBUFFERSIZE 256*2
#define PCMBUFFERSIZE 32
uint16_t pcmbuffer[PCMBUFFERSIZE];
uint8_t pdmbuffer[PDMBUFFERSIZE];
...
/**
* @brief SPI1 Initialization Function
* @param None
* @retval None
*/
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
...
/*Enables and resets CRC-32 from STM32 HW */
__HAL_RCC_CRC_CLK_ENABLE();
CRC->CR = CRC_CR_RESET;
//Initialize PDM Filter structure
FilterHandler.bit_order = PDM_FILTER_BIT_ORDER_MSB;
FilterHandler.endianness = PDM_FILTER_ENDIANNESS_LE;
FilterHandler.high_pass_tap = 2122358088; // Coff = 0.988 -> get this number as 0.988*(2^31-1)
FilterHandler.out_ptr_channels = 1;
FilterHandler.in_ptr_channels = 1;
PDM_Filter_Init(&FilterHandler);
FilterConfig.output_samples_number = PCMBUFFERSIZE;
FilterConfig.mic_gain = 1;
FilterConfig.decimation_factor = PDM_FILTER_DEC_FACTOR_64;
PDM_Filter_setConfig((PDM_Filter_Handler_t *)&FilterHandler, &FilterConfig);
...
//start mic-recording
MicWokeUp = FALSE;
HAL_SPI_Receive_DMA(&hspi1, pdmbuffer, PDMBUFFERSIZE);
HAL_Delay(200);
MicWokeUp = TRUE;
...
/**
* @brief This function handles DMA Half Transfer interrupt.
*/
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
{
//1. half buffer
if (MicWokeUp == TRUE){
HAL_GPIO_WritePin(H3_GPIO_Port, H3_Pin, GPIO_PIN_SET);
PDM_Filter(&pdmtestbuffer[0], &pcmbuffer[0], &FilterHandler);
PCMBufferReady = TRUE;
HAL_GPIO_WritePin(H3_GPIO_Port, H3_Pin, GPIO_PIN_RESET);
}
}
/**
* @brief This function handles DMA Full Transfer interrupt.
*/
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
//2. half buffer
if (MicWokeUp == TRUE){
HAL_GPIO_WritePin(H4_GPIO_Port, H4_Pin, GPIO_PIN_SET);
PDM_Filter(&pdmtestbuffer[PDMBUFFERSIZE/2], &pcmbuffer[0], &FilterHandler);
PCMBufferReady = TRUE;
HAL_GPIO_WritePin(H4_GPIO_Port, H4_Pin, GPIO_PIN_RESET);
}
}
...
//pcm data ready?
if (PCMBufferReady == TRUE){
PCMBufferReady = FALSE;
//copy pcmbuffer to flashbuffer
HAL_GPIO_WritePin(H5_GPIO_Port, H5_Pin, GPIO_PIN_SET);
for (PCMBufferIndex = 0 ; PCMBufferIndex < PCMBUFFERSIZE; PCMBufferIndex++){
FlashPageBuffer[FlashPageBufferIndex] = ((pcmbuffer[PCMBufferIndex]&0xff00)>>8);
FlashPageBufferIndex++;
}
HAL_GPIO_WritePin(H5_GPIO_Port, H5_Pin, GPIO_PIN_RESET);
}