cancel
Showing results for 
Search instead for 
Did you mean: 

Question about frame format of sai

Younjun
Associate II

Hi,

​I'm implementing signal processing code.(cs42l51 audio in --> stm32 --> cs42l51 audio out)

And i'm using STM32H7B3-discovery kit.

I have some question about frame format of sai and cs42l51.

When i send sine wave data from stm32 to cs42l51, the waveform is not sine wave.(like noise)

First question is about frame format.

I'm implementing to send AIN1A to AOUTA and AIN1B to AOUTB.

I set sai setting like below.

  • frame length : 32bit
  • active length : 16bit
  • active slot : 0, 1
  • mode : stereo mode

0693W00000LyqwpQAB.png

​I think I set sai frame like this. Is it right?

0693W00000LyqxnQAB.png

​Second question is about sai callback.

​In audio example, output callbacks are divided into two.(half callback, callback complete)

Does half callback mean that the LRCK is in a low state?

​​

Last question is about slot.

I'm wondering about below part.(STM32H7B3 reference manual P.2172 FS roll)

0693W00000LyqzKQAR.pngI set the slot size to 2 and i'm using one left(AOUTA) / one right(AOUTB).

The right and left channel are each 1, so i can't set it to 0.5.

What does this mean?

Regards,

Youngjun

1 ACCEPTED SOLUTION

Accepted Solutions
Piranha
Chief II

The frame diagram is correct now.

The data order in memory is the same as it is on the wire - frame after frame. Therefore for n+1 slots the order is:

SLOT0, SLOT1, ... SLOTn; SLOT0, SLOT1, ... SLOTn; SLOT0, SLOT1, ... SLOTn; ...

You don't have to access GPIO pins for this and the synchronization will break anyway. The DMA interrupt with it's status flags already tells you which interrupt it is - half or full transfer complete. Use that information to decide on which half of the buffer to process. Alternatively you can use double-buffer mode (RM0455 section "15.3.11 Double-buffer mode"). It has a few advantages, but both approaches are viable.

Your current D-cache management is OK, but still read this topic:

https://community.st.com/s/question/0D53W00000oXSzySAG/different-cache-behavior-between-stm32h7-and-stm32f7

Also, when you're not sure, you can disable D-cache altogether for debugging purposes.

View solution in original post

7 REPLIES 7
Piranha
Chief II

> ​I think I set sai frame like this. Is it right?

Totally no. Read the codec's datasheet section "4.7 Digital Interface Formats". And you have even invented some BOUT channels, which doesn't exist. Even the name AOUT means "Analog OUTput". A standard I2S means a 64-bit frame with two 32-bit slots, which you can fill with up to 24 bits of data.

> Does half callback mean that the LRCK is in a low state?

No, it means half of the buffer, which you assigned to DMA, has been read/written. Those are DMA interrupts - read about those in a DMA section of the reference manual.

> I'm wondering about below part.(STM32H7B3 reference manual P.2172 FS roll)

It's written by people, who are not native English speakers. Sometimes the descriptions are strange, confusing or even wrong. In this case they just mean that from the total number of slots you set up, half will be for the left channel and the other half for the right channel.

Younjun
Associate II

hi Piranha.

Thank you for your answer.

​I drew it wrong.

'For CS42L51 BOUT sample' ​ --> 'For CS42L51 AOUTB sample'

I set the cs42l51 interface to I2S with 24bit.​

Then, should I change the stm32 setting like this?

  • FRL in SAI_xFRCR : 64bit
  • SLOTZ in SAI_xSLOTR : 32bit​
  • SLOTEN in SAI_xSLOTR : enable slot0 and slot1

0693W00000LyrEFQAZ.png0693W00000LyrEKQAZ.pngIs it right?

Regards,

Youngjun

Piranha
Chief II

The register bitfield numbers are OK, just do not forget to set the DS field at SAI_xCR1 to 24-bit for your example.

But the drawing is still wrong. You have drawn a 128-bit frame with four 32-bit slots, just named incorrectly. Forget the Sample1/2 - the frame has only one sample for every channel/slot!

  • SLOT0: FS is low, holds a sample for left channel (AOUTA)
  • SLOT1: FS is high, holds a sample for right channel (AOUTB)

Also you have drawn FS signal as for I2S, but aligned data bits in a right-justified format, which the particular codec supports only for the DAC. Generally an I2S or left-justified format should be preferred, because those work correctly even if the number of used data bits for transmitter and receiver differs. For I2S the frame starts with FS at low level, but for left/right-justified formats the frame starts with FS at high level. And data bits for I2S are like for a left-justified, just delayed by one bit. These parameters are configured by FSPOL and FSOFF bits at SAI_xFRCR register.

Again - read the codec's datasheet section "4.7 Digital Interface Formats" and look carefully at diagrams there!

Younjun
Associate II

Slot0 : 32bit

Slot1 : 32bit

Total : 64bit

0693W00000LyriKQAR.pngAnd MSB aligned left.

Is that right?

I have one question about copy dma data to slot.

This is my tx code.

I declared p_bff(wave data size 256byte) and copy p_bff to BufferoutCtl.bufff(address 0x38000000).

When FS pin(GPIO E4) state is low, is the 128byte of p_bff data transfer to CS42L51?

I understood like this.

  • FS : low
    • p_bff[0] : AOUTA sample 1
    • p_bff[1] : AOUTA sample 2
    • ......
    • p_bff[127] : AOUTA sample 128

Is that right?

if (tx_half_flag) {
			pin_state = HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4);
			if (pin_state == GPIO_PIN_RESET) {
				memcpy(&BufferOutCtl.buff[0], p_bff, HALF_TXRX_SIZE);
				SCB_CleanDCache_by_Addr((uint32_t*) &BufferOutCtl.buff[0], HALF_TXRX_SIZE);
			}else{
			}
			
			tx_half_flag = 0;
		}
		if (tx_full_flag) {
			pin_state = HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4);
			if (pin_state == GPIO_PIN_RESET) {
				memcpy(&BufferOutCtl.buff[HALF_TXRX_SIZE], p_bff + HALF_TXRX_SIZE, HALF_TXRX_SIZE);
				SCB_CleanDCache_by_Addr((uint32_t*) &BufferOutCtl.buff[0], HALF_TXRX_SIZE);
			}else{
			}
			
			tx_full_flag = 0;
		}

I have a lot of questions because it is my first time using sai.

Thank you for your kind reply.

Regards,

Youngjun​

Piranha
Chief II

The frame diagram is correct now.

The data order in memory is the same as it is on the wire - frame after frame. Therefore for n+1 slots the order is:

SLOT0, SLOT1, ... SLOTn; SLOT0, SLOT1, ... SLOTn; SLOT0, SLOT1, ... SLOTn; ...

You don't have to access GPIO pins for this and the synchronization will break anyway. The DMA interrupt with it's status flags already tells you which interrupt it is - half or full transfer complete. Use that information to decide on which half of the buffer to process. Alternatively you can use double-buffer mode (RM0455 section "15.3.11 Double-buffer mode"). It has a few advantages, but both approaches are viable.

Your current D-cache management is OK, but still read this topic:

https://community.st.com/s/question/0D53W00000oXSzySAG/different-cache-behavior-between-stm32h7-and-stm32f7

Also, when you're not sure, you can disable D-cache altogether for debugging purposes.

Younjun
Associate II

Your answer was great helpful for me.​

Thank you.

By the way... In your code the address at line 15 is &BufferOutCtl.buff[0], but should be &BufferOutCtl.buff[HALF_TXRX_SIZE].