cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5A5: SAI with 24bit PCM samples - why just 16bit or 32bit?

tjaekel
Lead

I want to use STM32U5A5 SAI1 to generate via SAI1 a master I2S, with 24bit sample words.
I need 24bit because sending out afterwards as S/PDIF (via SAI2) needs 24bit sample words (as I understand: SAI2 as S/PDIF Tx is "forced" to send as 24bit samples - only).

I get just 16bit PCM or 32bit PCM, but not 24bit! WHY?

My config:

  hsai_BlockA1.Instance = SAI1_Block_A;
  hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
  hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
  hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
  hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
  hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
  hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;
  hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;	//SAI_SYNCEXT_OUTBLOCKA_ENABLE;	//SAI_SYNCEXT_DISABLE;
  hsai_BlockA1.Init.MckOutput = SAI_MCK_OUTPUT_DISABLE;
  hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
  hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
  hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
  /* S/PDIF is 24bit ! */
  if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_24BIT, 2) != HAL_OK)
  {
    Error_Handler();
  }
}

See, that I use SAI_PROTOCOL_DATASIZE_24BIT.

I have also set DMA  config to use Bytes (instead of words, just being skeptical if 32bit words might affect the behavior).

    NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
    NodeConfig.Init.Request = GPDMA1_REQUEST_SAI1_A;
    NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
    NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
    NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
    NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
    NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
    NodeConfig.Init.DestDataWidth = DMA_SRC_DATAWIDTH_BYTE;
    NodeConfig.Init.SrcBurstLength = 1;
    NodeConfig.Init.DestBurstLength = 1;
    NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
    NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    NodeConfig.Init.Mode = DMA_NORMAL;
    NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
    NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
    if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel4) != HAL_OK)

Just to make sure, 24bit as three bytes can be handled via DMA. But at the end, it should not matter because my buffer is properly aligned (for multiples of 24bit samples, two channels, so that even a Word DMA should work as well).

#define SAI_CHANNELS			2		/* stereo, two MIC channels */
#define SAI_BYTES_PER_SAMPLE	3		/* 24bit, for SPDIF */
#define SAI_AUDIO_FREQ			48		/* 48 KHz */
#define SAI_BUFFER_SIZE			1000	/* as N times 1ms samples - 1 second */
#define SAI_DOUBLE_BUFFER		2		/* 2 for double buffering! */
uint8_t SAIRxBuf[((SAI_CHANNELS * SAI_BYTES_PER_SAMPLE) * SAI_AUDIO_FREQ) * SAI_BUFFER_SIZE * SAI_DOUBLE_BUFFER] __aligned(4);

I get just 16bit per SAI_FS frame or 32bit per SAI_FS, but not 24bit! WHY?

Here the waveform with SAI_PROTOCOL_DATASIZE_24BIT used: see that 32bits are in a channel frame where I expect to see 24bits!

PDM_MIC_MCU_signals_5.png

If I just change to:

if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 2) != HAL_OK)

I see 16bit per SAI FS frame - correct:

PDM_MIC_MCU_signals_6.png

This MCU drives me crazy.

How to use 24bit PCM on SAI for this MCU, with the associated HAL drivers?

1 ACCEPTED SOLUTION

Accepted Solutions
Saket_Om
ST Employee

Hello,

 

The HAL_SAI_InitProtocol function will program frame and slot configurations for the specified protocol according to data size and slot number.

In your case, you want to configure a frame with two slots, and a data size of 24 bits in I2S protocol.

I won’t detail all configurations but, if master clock divider is used (SAI_MASTERDIVIDER_ENABLE), the frame length must equal to a power of 2 to ensure that an audio frame contains an integer number of MCLK pulses per bit clock cycle.

On HAL_SAI_InitProtocol function, we have chosen to always respect it so if you want two slots with 24 bits data size, we configure a frame length of 64 bits (48 is not a power of 2).

You observe two slots of 32 bits (slot size) but each slot has a data size of 24 bits (data size). 

It means that only 24bits are received on each slot (you can observe that the last 8 bits are null).

If you really want a frame length of 48bits, with two slots of 24bits, you can use HAL_SAI_Init function instead of HAL_SAI_InitProtocol.

But you will need before to configure FrameInit and SlotInit structure of SAI handle. Don’t forget also to disable master clock divider.

 

Hope it will be helpful for you.

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

Thanks
Omar

View solution in original post

2 REPLIES 2
Saket_Om
ST Employee

Hello,

 

The HAL_SAI_InitProtocol function will program frame and slot configurations for the specified protocol according to data size and slot number.

In your case, you want to configure a frame with two slots, and a data size of 24 bits in I2S protocol.

I won’t detail all configurations but, if master clock divider is used (SAI_MASTERDIVIDER_ENABLE), the frame length must equal to a power of 2 to ensure that an audio frame contains an integer number of MCLK pulses per bit clock cycle.

On HAL_SAI_InitProtocol function, we have chosen to always respect it so if you want two slots with 24 bits data size, we configure a frame length of 64 bits (48 is not a power of 2).

You observe two slots of 32 bits (slot size) but each slot has a data size of 24 bits (data size). 

It means that only 24bits are received on each slot (you can observe that the last 8 bits are null).

If you really want a frame length of 48bits, with two slots of 24bits, you can use HAL_SAI_Init function instead of HAL_SAI_InitProtocol.

But you will need before to configure FrameInit and SlotInit structure of SAI handle. Don’t forget also to disable master clock divider.

 

Hope it will be helpful for you.

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

Thanks
Omar

Thank you, this makes sense.