SAI I2S on FRDM K64F (Synchronized Tx with Rx)

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

SAI I2S on FRDM K64F (Synchronized Tx with Rx)

1,651 Views
marcin99
Contributor II

Hello, I am having issues with configuring the SAI in FRDM K64F to the following mode:

SAI_Rx is slave and gets FS and BCK from external audio ADC.

SAI_Rx sends BCK and FS to SAI_Tx

SAI_Tx is a master and sends BCK and FS to the external amplifier.

Both Tx and Rx are in I2S mode

SAI_MCLK - should this be configured as external input and get it from the ADC as well?

I have SDK 2.2 but I'm configuring registers manually to have better understanding.. but it is not working.

To get the above config, the datasheet instructs to set the Rx  to A-sync mode and Tx to Sync mode. I configured the other registers to the best of my knowledge, but I cannot get the Tx BCK to be sourced from the SAI_Rx. The Tx BCK defaults to internal 24MHz clock.

0 Kudos
11 Replies

1,068 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Marcin99.

Sorry, I am not very clear about your hardware connection.

You said the SAI_Rx is slave, which means that bit/frame clock signals SAI_RX_BCLK/SAI_RX_SYNC are input signal from K64 perspective.

You said "SAI_Rx sends BCK and FS to SAI_Tx, SAI_Tx is a master and sends BCK and FS to the external amplifier.", the description is in contradiction with each other, is the SAI_Tx  a master or slave?

The SAI_MCLK can be input or output, in other words, the ADC can generate the SAI_MCLK, the K64 can generate SAI_MCLK also, it is dependent on your requirement.

Pls draw a figure so that we can know the hardware connection. waht is your issue now?

BR

Xiangjun Rong

0 Kudos

1,068 Views
marcin99
Contributor II

Here is the current I2S config section of code:

void init_I2S(void)
{
    // Enable SAI and DMA mux clock
    SIM->SCGC6 |= ( SIM_SCGC6_I2S_MASK | SIM_SCGC6_DMAMUX_MASK );

    // Enable DMA clock
    SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;

    // Clear flags for SAI module
    SAI_TxReset(I2S0);
    SAI_RxReset(I2S0);

    I2S0->RCSR = 0x0;        // Disable the Receiver
    I2S0->RCR3 = 0x0;        // Disable the Receiver Channel
    I2S0->TCSR = 0x0;        // Disable Transmitter
    I2S0->TCR3 = 0x0;        // Disable Transmitter channel

    I2S0->RCR2 |= (I2S_RCR2_BCP_MASK );
    I2S0->RCR3 |= (I2S_RCR3_RCE(0x1));
    I2S0->RCR4 |= (I2S_RCR4_FRSZ(0x1) | I2S_RCR4_SYWD(0x1F) | I2S_RCR4_MF_MASK | I2S_RCR4_FSE_MASK | I2S_RCR4_FSP_MASK | I2S_RCR4_FSD_MASK);
    I2S0->RCR5 |= (I2S_RCR5_WNW(0x1F) | I2S_RCR5_W0W(0x1F) | I2S_RCR5_FBT(0x1F));

    I2S0->TCR2 |= ( I2S_TCR2_SYNC(0x1) | I2S_TCR2_BCS_MASK | I2S_TCR2_BCP_MASK );

    I2S0->TCR4 |= (I2S_TCR4_FRSZ(0x1) | I2S_TCR4_SYWD(0x1F) | I2S_TCR4_MF_MASK | I2S_TCR4_FSE_MASK | I2S_TCR4_FSP_MASK );

    I2S0->TCR5 |= (I2S_TCR5_WNW(0x1F) | I2S_TCR5_W0W(0x1F) | I2S_TCR5_FBT(0x1F));

    I2S0->TCR3 |= I2S_TCR3_TCE(0x1);    // Enable Channel
    I2S0->TCSR |= I2S_TCSR_TE_MASK;        // Enable Tx

    I2S0->RCR3 |= I2S_RCR3_RCE(0x1);    // Enable Channel
    I2S0->RCSR |= I2S_RCSR_RE_MASK;        // Enable Rx

}

0 Kudos

1,068 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Marcin,

sorry for the delay, I just come back from a long Chinese festival.

I do not know if the synchronization is needed, it is dependent on your application.

In asynchronous mode, the SAI_RX and SAI_TX are independent module, for SAI_RX, the ADC is master, bit clock(SAI_RX_BCLK) and frame clock(SAI_RX_SYNC) are from ADC module. For SAI_TX module, it can be master, in other words, bit clock(SAI_TX_BCLK) and frame clock(SAI_TX_SYNC) are from SAI_TX module, which can drive the PWR_AMP.

For synchronous mode, the SAI_TX and SAI_RX share the same bit clock and frame clock, for example, you can connect the ADC bit/frame clock  to the bit/frame clock of both SAI_TX and SAI_RX, it is synchronous mode, although you can set asynchronous mode for both SAI_RX and SAI_TX. As alternative, you can set the SAI_RX in slave/asynchronous mode, while set the SAI_TX is synchronous mode by setting   SYNC bits in I2Sx_TCR2 as 01 in binary, the SAI_TX bit/frame clock are connected to the SAI_RX bit/frame clock internally, SAI_TX bit/frame clcok external pads are not needed.

Hope it can help you

BR

Xiangjun rong

0 Kudos

1,068 Views
marcin99
Contributor II

Does anyone at NXP have any recommendations?

Is this possibly a datasheet issue or am I missing something?

0 Kudos

1,068 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Marcin,

I see your issue, I will test on my TWR-k64F board, give you my result at the end of this week.

BR

Xiangjun Rong

0 Kudos

1,068 Views
marcin99
Contributor II

Hello Xiangjun,

Will you have time to check this before the weekend?

0 Kudos

1,068 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Marcin,

I am sorry, I forgot the case.

I will follow up it.

BR

Xiangjun Rong

0 Kudos

1,068 Views
marcin99
Contributor II

Have you had a chance to look into this?

0 Kudos

1,067 Views
marcin99
Contributor II

I am starting to question whether it is possible to have the SAI Transmitter use Receiver's Bit and Frame Clocks So far I was only able to feed the Frame Clock from the Receiver to Transmitter.

In section 54.1.2 (page 1721) of the K64 reference manual  the SAI block diagram shows direct connection between Frame Sync of the Transmitter and Receiver. However it does not show similar path for the Bit Clock.

The same reference manual states the following in the section 54.4.3.1:

If the receiver bit clock and frame sync are to be used by both the transmitter and
receiver:
• The receiver must be configured for asynchronous operation and the transmitter for
synchronous operation.
• In synchronous mode, the transmitter is enabled only when both the receiver and
transmitter are both enabled.
• It is recommended that the receiver is the last enabled and the first disabled.

I believed that I followed these instructions and was unable to get the BCK through from Rx to Tx.

Any help would be greatly appreciated!

0 Kudos

1,068 Views
marcin99
Contributor II

Thanks and really no problem about the delay!

Back to the question.. I think I setup both SAI_Tx and Rx as you described in the last sentence. I prefer to have the Bit and Frame clocks connected internally and  sourced by the ADC module.

I2S0->RCR2 |= (I2S_RCR2_BCP_MASK );  // SYNC is 00 --> Rx in asynch mode, change clock polarity, BCD=0 --> Slave

I2S0->TCR2 |= ( I2S_TCR2_SYNC(0x1) | I2S_TCR2_BCP_MASK );  // SYNC is 01 --> Tx in sync mode, change to clock polarity

// For BCD = 0 --> there is no BCK and no FS

// For BCD = 1 --> the BCK is a 24MHz clock (not related to the Rx BCK) and FS seems to be sync'ed with Rx_FS.

I tried several combinations and cannot get the Tx_BCK to be directly tied with Rx_BCK.

Could you provide the SAI register configuration for this SAI mode?

0 Kudos

1,068 Views
marcin99
Contributor II

I apologize for not being clear.

SAI_Rx is a slave (receives BCK and FS from ADC)

SAI_Tx is a master (sends BCK and FS to Power Amp)

What I am not sure about is how does the SAI Tx get synchronized with SAI_Rx. The user guide explains that it is possible for SAI_Rx to source BCK and FS internally to the SAI_Tx. You are correct, that there seems to be a contradiction because the SAI Tx would be a slave to SAI_Rx and at the same time master to the Power Amplifier.  I am sure this is misunderstanding on my part and hopefully you could clear this up for me.

ADC_BCK --> SAI_Rx_BCK --??--> SAI_Tx_BCK --> Power_Amp_BCK

ADC_FS --> SAI_Rx_FS --??--> SAI_Tx_FS --> Power_Amp_FS

As far as the MCLK it would seem to me that I do not need MCLK for this to happen, but I think that the SAI would need it to move things internally. In this case would it be OK to use unsynchronized internal MCLK or should I route the MCLK from the ADC to the SAI?

Hopefully this is more clear,

Marcin

0 Kudos