Using SAI1 to drive 3 audio outputs with 2 TX_Data

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using SAI1 to drive 3 audio outputs with 2 TX_Data

Jump to solution
1,097 Views
DigitalBrain
Contributor I

Hello, I'm running RT1024 on a custom board.
SAI1 is configured as an I2S master to control 1 PCM4104. This DAC is capable of driving 4 output channels, it drives 2 channels per logic state of LRCK:

DigitalBrain_0-1733853392160.png

when LRCK is high, CH1 reproduces whatever comes to DATA0 and CH3 reproduces whatever comes to DATA1.

I'm trying to play sounds taking the "evkmimxrt1024_sai_interrupt_transfer" example and changing SAI3 to SAI1 with the next configuration:

DigitalBrain_1-1733853467091.png


The routine is as follows:
-Initialize clocks
-Initialize SAI1
-Create SAI_TransferTxCreateHandle

 

STATE_EMITTING_RIGHT
-Turn on LED1
-Configure SAI as left justified, monoright and channel 1 (I leave this channel 1 as the example but don't fully understand why is this value), asynchronous mode, master.
-Configure the SAI_TransferTxSetConfig
-Set the BCK with SAI_TxSetBitClockRate
-Reproduces sound with SAI_TransferSendNonBlocking
-Turn off LED1

STATE_EMITTING_LEFT
-Turn on LED2 and LED3
-Configure SAI as left justified, monoleft and channel 1 (I leave this channel 1 as the example but don't fully understand why is this value), asynchronous mode, master.
-Configure the SAI_TransferTxSetConfig
-Set the BCK with SAI_TxSetBitClockRate
-Reproduces sound with SAI_TransferSendNonBlocking
-Turn off LED2 and LED3

Then repeats alternating playing sound between left and right.


Results:
So far, debugging with MCUxpresso I've been able to reproduce sounds through channel 1 (left) and channel 2 (right).

Issues:
1)This doesn't work all the time, if I try to toggle both LED2 and LED3, the program reproduces 10 times the sound on the left and 9 times on the right and then completely freezes. If I remove writing1&writing0 to LED2 or LED3, the program has no freezing, it alternates reproducing sounds left&right without problem.
1.1) In order to reproduce sounds, I need to run the program through MCUXpresso debugging mode. If I run the program without it, volume goes very low and it only reproduces sound through monoLeft. This doesn't make any sense to me. I'm using the same code I tested on another custom board with the same RT1024 and the same audio DAC, but using SAI3 instead of SAI1


2)I see the audio data coming out from TX_DATA0 but not from TX_DATA1. How could I get data to come out from TX_DATA1 pin too?

I've attached the main programming code files for further detail.

Please, any help would be appreciated!!
Thanks!!



0 Kudos
Reply
1 Solution
906 Views
mayliu1
NXP Employee
NXP Employee

Hi @DigitalBrain 

 

I think DEMO_SAI_CHANNEL depend on your needs, what I show you is just a demo.

You can also set saiChannelMask, this param can also set multiple SAI channel.

mayliu1_1-1735296067458.png

function -> SAI_TransferTxSetConfig will call SAI_TxSetConfig

mayliu1_2-1735296153019.png

In SAI_TxSetConfig function , saiChannelMask  set TCR3 register.

 

BR

mayliu

View solution in original post

0 Kudos
Reply
13 Replies
1,063 Views
mayliu1
NXP Employee
NXP Employee

Hi @DigitalBrain ,

Thank you for your interest in the NXP MIMXRT product, I would  like to provide service for you.

Question:
1)This doesn't work all the time, if I try to toggle both LED2 and LED3, the program reproduces 10 times the sound on the left and 9 times on the right and then completely freezes. If I remove writing1&writing0 to LED2 or LED3, the program has no freezing, it alternates reproducing sounds left&right without problem.

Answer: 

I have download your code, but there are no LED1,LED2,LED3 definition.

when the project freezing, Please check Register, Fault, Peripherals->SAI status.

mayliu1_1-1733971150320.png

You can also read SAI status in your code project.

mayliu1_2-1733971457550.png

Question:

1.1) In order to reproduce sounds, I need to run the program through MCUXpresso debugging mode. If I run the program without it, volume goes very low and it only reproduces sound through monoLeft. This doesn't make any sense to me. I'm using the same code I tested on another custom board with the same RT1024 and the same audio DAC, but using SAI3 instead of SAI1
Answer: 

If the volume changed, I suggest you double check Audio format.

Question:

2)I see the audio data coming out from TX_DATA0 but not from TX_DATA1. How could I get data to come out from TX_DATA1 pin too?

Answer: If you want to use TX_DATA0 and TX_DATA1 of SAI1 , please refer to the content of Section 34.5.1.7 "Transmit Configuration 3 (TCR3)" in the MIMXRT1024RM. You should set the Transmit Enable (TCE) bit in Transmit Configuration 3 (TCR3) when initializing the SAI1.

mayliu1_4-1733972318070.png

 

Wish it helps you.
If you still have question about it, please kindly let me know.

 

BR

mayliu

 

0 Kudos
Reply
1,023 Views
DigitalBrain
Contributor I

Hello @mayliu1 

initialization is as follows:

SAI_Init(DEMO_SAI);
SAI_TransferTxCreateHandle(DEMO_SAI, &txHandle, callback, NULL);
SAI_TxSetChannelFIFOMask(DEMO_SAI,3);

I thought that adding the last line would be enough to transmit through TX_DATA1 but it wasn't. What am I missing?


Thanks!!

0 Kudos
Reply
1,009 Views
mayliu1
NXP Employee
NXP Employee

Hi @DigitalBrain ,

Thanks for your reply.

Could you check your SAI1 TCR3 register value.

You can check MCUXpresso IDE -> Peripherals -> SAI1 -> TCR3->TCE

mayliu1_1-1735011387354.png

Wish it helps you.
If you still have question about it, please kindly let me know.

BR

mayliu

0 Kudos
Reply
982 Views
DigitalBrain
Contributor I

Hello, @mayliu1 

Thanks for your reply. These are the values:

DigitalBrain_0-1735208746335.png

TCE is set to 0x1. 

Maybe I need to use a different function to transmit through TX_DATA1?
Currently I'm using:

sai_handle_t txHandle = {0};
sai_transfer_t xfer;
SAI_TransferSendNonBlocking(SAI1, &txHandle, &xfer);

I understood this function would send the same data at the same time through all the enabled TX_DATA channels. Is it correct?


Thanks!!

0 Kudos
Reply
970 Views
mayliu1
NXP Employee
NXP Employee

Hi, @DigitalBrain 

 

Thanks for your update information.

I notice that your TCE is 1,  I don't think it is a right value.

TCE should be 0x03(0b0011) if you want both channel1 and channel 2  working.

mayliu1_0-1735211471634.png

 

Please double check your config function.

 

BR

mayliu

0 Kudos
Reply
968 Views
DigitalBrain
Contributor I

Hello, @mayliu1 

That's true. I've set it to 3:
SAI_TxSetChannelFIFOMask(SAI1,3);


DigitalBrain_0-1735213166427.png

but after executing the function, the register gets set to 0x1 instead of 0x3.

For some reason, I'm not being able to set it to 0x3

0 Kudos
Reply
964 Views
DigitalBrain
Contributor I

Furthermore, even placing the value directly to 0x3 gets 0x1 as result

void SAI_TxSetChannelFIFOMask(I2S_Type *base, uint8_t mask)
{
base->TCR3 &= ~I2S_TCR3_TCE_MASK;
base->TCR3 |= I2S_TCR3_TCE(0x3);
}

0 Kudos
Reply
946 Views
mayliu1
NXP Employee
NXP Employee

Hi @DigitalBrain 

Thanks for your update information.

I did a validation on my side, I can set TCE as 0x03, Please refer to what I did.

mayliu1_0-1735265076973.png

1: First , I think you should set your SAI  TX DATA1 .

Please note that the GPIO TX DATA1  is not real connect, your code should be based on your customed board. The modified configurations I made are just for giving you a demonstration. Please develop your code strictly base on your customed board.

mayliu1_1-1735265147286.png

 

2: Second, you need call SAI_TxSetChannelFIFOMask(DEMO_SAI, 0x03) in your project

I import SDK demo "evkmimxrt1020_sai_interrupt_transfer" , and use MIMXRT1020-EVK board .

mayliu1_2-1735265253628.png

 

Wish it helps you.
If you still have question about it, please kindly let me know.

If you have other question, Please create a new case, Thanks.

 

BR

mayliu

0 Kudos
Reply
921 Views
DigitalBrain
Contributor I

Hello, @mayliu1 

Thanks for your input!

Could you please  show me the value you set for DEMO_SAI_CHANNEL?

If I do the following:

#define DEMO_SAI_CHANNEL (0) //Now it doesn't matter as 3 is being hardcoded
SAI_TxSetChannelFIFOMask(DEMO_SAI,5);
SAI_GetLeftJustifiedConfig(&saiConfig, DEMO_AUDIO_BIT_WIDTH, kSAI_MonoRight,3);

The register sets to 3, seems like the value that matters is the sent on SAI_GetLeftJustifiedConfig

Also, how is it possible to select the data to transfer through TX_DATA0 and TX_DATA1 ?

Thanks!

0 Kudos
Reply
907 Views
mayliu1
NXP Employee
NXP Employee

Hi @DigitalBrain 

 

I think DEMO_SAI_CHANNEL depend on your needs, what I show you is just a demo.

You can also set saiChannelMask, this param can also set multiple SAI channel.

mayliu1_1-1735296067458.png

function -> SAI_TransferTxSetConfig will call SAI_TxSetConfig

mayliu1_2-1735296153019.png

In SAI_TxSetConfig function , saiChannelMask  set TCR3 register.

 

BR

mayliu

0 Kudos
Reply
796 Views
DigitalBrain
Contributor I

Hello @mayliu1 

Thanks for your reply!!

Utilizing kSAI_Channel#Mask got me to transmit data through TX_DATA1, however I'm wondering how is it possible to control which data is sent to each of the TX_DATAX.

For example, is it necessary to reconfigure all each time I want to transmit through audio jack1, audiojack2 audiojack3?


Right now, I need to run all of this routine each time I want to transmit through a jack:

SAI_GetLeftJustifiedConfig(&saiConfig, AUDIO_BIT_WIDTH, kSAI_MonoRight,kSAI_Channel0Mask);
saiConfig.syncMode    = SAI_TX_SYNC_MODE;
saiConfig.masterSlave = SAI_MASTER_SLAVE;
SAI_TransferTxSetConfig(SAI_MODULE, &txHandle, &saiConfig);
 
/* set bit clock divider */
SAI_TxSetBitClockRate(SAI_MODULE, AUDIO_MASTER_CLOCK, AUDIO_SAMPLE_RATE, AUDIO_BIT_WIDTH,
  AUDIO_DATA_CHANNEL);
 
GPIO_PinWrite(BOARD_INITPINS_LED_IZDA_GPIO, BOARD_INITPINS_LED_IZDA_PIN, 1);
/*  xfer structure */
temp          = (uint32_t)music;
xfer.data     = (uint8_t *)temp;
xfer.dataSize = MUSIC_LEN;
isFinished = false;
 
status_t result_IZDA = SAI_TransferSendNonBlocking(SAI_MODULE, &txHandle, &xfer);
/* Wait until finished */
while (isFinished != true)
{
}
 
GPIO_PinWrite(BOARD_INITPINS_LED_IZDA_GPIO, BOARD_INITPINS_LED_IZDA_PIN, 0);
 
delay_msec(800);


Then, if I want to transmit through audiojack 2 I do all the same just changing kSAI_MonoRight to kSAI_MonoLeft.

And finally, if I want to transmit through audiojack3 (this is the one connected to TX_DATA1) I do all the same changing to kSAI_MonoLeft, kSAI_Channel1Mask . This time kSAI_Channel1Mask because (as far as I understand) will transmit through TX_DATA1


Thanks!!
0 Kudos
Reply
772 Views
mayliu1
NXP Employee
NXP Employee

Hi @DigitalBrain ,

 

Thanks for your update information.

Sorry I don't know the corresponding relationship between audio jack1, audiojack2 ,jack3  with your SAI interface.

But I can tell you that SAI_GetClassicI2SConfig, SAI_GetLeftJustifiedConfig, SAI_GetRightJustifiedConfig all can support 2 slot.

Please modify your code, set sai_mono_stereo_t as kSAI_Stereo. 

mayliu1_0-1736504277923.png

I also suggest you can refer to this link.

https://www.nxp.com/docs/en/application-note/AN12090.pdf

If you still have question, Please create a new case, I will do my best to help you.

BR

mayliu

0 Kudos
Reply
727 Views
DigitalBrain
Contributor I

Thanks @mayliu1 !!

I've checked your previous answer as the solution as now data comes out through TX_DATA1. Also, I'll create a new case to troubleshoot the actual control of the data as suggested

Thanks again!!

0 Kudos
Reply