cancel
Showing results for 
Search instead for 
Did you mean: 

What are frames and slots when reading from a PDM microhpone with SAI?

Robert_149494
Associate II

I am trying to configure a single microphone with a pulse-density modulation (PDM) output on my microcontroller (STM32U575ZIT). It's a CMM-4030DT-261280-TR MEMS microphone.

But I can't seem to figure out the basics. The SAI settings mention "Frame Length", "Data Size" and "Slot Size". What even are slots and frames in this context?

 

I think I understand PDM and it makes sense to define a data size: how many bits should be counted together to form a single data point. The other notions however confuse me.

Attached is my SAI config from CubeMX.

cubemx_pdm.jpg

 

I logged the clock and data using a logic analyzer some testing code on the MCU hoping to figure this out. The code:

            HAL_SAI_Init(&hsai_BlockA1);

            std::array<uint8_t, 8> data;
            data.fill(0);

            auto ok = HAL_SAI_Receive(&hsai_BlockA1, data.data(), data.size(), 100);

            HAL_SAI_DeInit(&hsai_BlockA1);

The analyzer output and the content of data after this block:

logic_pdm.jpg screenshot_data.jpg

For one I am surprised to see 37 rising edges, instead of 8 * 8 = 64. How where these bytes composed?

1 ACCEPTED SOLUTION

Accepted Solutions
Robert_149494
Associate II

Figured I'd come back with the full solution. In the end I got a single PDM microphone to work with these settings:
cubemx_settings.jpg

Only the Mckdiv value I couldn't manage to change from CubeMX, so I added that as user code:
cubemx_mckdiv.jpg

 

In the end the "Serial audio interface (SAI)" chapter of the STM32 reference manual was helpful. In particular the section "PDM interface". See also the following figure from the manual:
ref_slots.jpg

So the PDM data is collected by the SAI and written to memory as 'slots'. The memory destination (SAI_ADR register) is always divided in 32 bit words and you can configure how these words should be used.
With the config above, only the smallest 8 bits of each WORD are filled by the single microphone. But the HAL functions neatly take care of this behavior, so as a user you only the see the byte produced by the

View solution in original post

3 REPLIES 3
Saket_Om
ST Employee

Hello @Robert_149494 


A dedicated chapter explains how to configure SAI for this usage is available on reference manual RM0456 Chapter 69.4.10.

Please find below an example of SAI PDM configuration for record on two microphones.
The SAI kernel clock has been configured at 48MHz.
We want a SAI1_CK1 at around 1MHz for digital microphones.
The expected serial clock frequency is 2MHz (SAI1_CK1*2 because on this example we have only one microphone).
So, the master clock divider is set to 24 (Fsai_ker_clk/Fsck_a).
With this configuration, the recorded data after an external decimation of 64 will be at around 16kHz (1Mhz/16).

Here is the configuration with some details:

 

  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_8;
  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_ENABLE;
  hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_DISABLE; /* See SAI chapter 69.4.8 of RM0456, in this case NODIV=1 and Fsck_a = Fsai_ker_clk/MCKDIV)
  hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
  hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV; /* In order to set directly MCKDIV value (not computed by HAL SAI source code) */
  hsai_BlockA1.Init.Mckdiv = 24; /* Probably not generated by CubeMx */
  hsai_BlockA1.Init.MckOutput = SAI_MCK_OUTPUT_DISABLE;
  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 = 2;
  hsai_BlockA1.SlotInit.SlotActive = 0x0000FFFF;
  if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
  {
    Error_Handler();
  }

Could you check with this setting please?

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

Thanks for your reply!

I tried your suggestion, except I left it at the most significant byte first:

 

hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;

 

EDIT: @Saket_Om  why would `OutputDrive` be enabled, if we only have microphones?

And now for the first time I've gotten valid data back, so thank you! 
Or at least, pretty close. Now all even bytes should be ignored, which also makes sense because it's now configured for two microphones.

sai_scope.jpg

I don't understand what's different in this configuration though and what I did wrong before.

What would be the correct way to receive only data from a single microphone?

Robert_149494
Associate II

Figured I'd come back with the full solution. In the end I got a single PDM microphone to work with these settings:
cubemx_settings.jpg

Only the Mckdiv value I couldn't manage to change from CubeMX, so I added that as user code:
cubemx_mckdiv.jpg

 

In the end the "Serial audio interface (SAI)" chapter of the STM32 reference manual was helpful. In particular the section "PDM interface". See also the following figure from the manual:
ref_slots.jpg

So the PDM data is collected by the SAI and written to memory as 'slots'. The memory destination (SAI_ADR register) is always divided in 32 bit words and you can configure how these words should be used.
With the config above, only the smallest 8 bits of each WORD are filled by the single microphone. But the HAL functions neatly take care of this behavior, so as a user you only the see the byte produced by the