I2S/SAI (1) and (2) in T4 cores

floj

Member
Limiting the scope of my statements to the 1062 blocks of code.
I haven't read the KINETISL or KINETISK parts, but if anyone goes to investigate after reading this, be careful because those parts are interleaved in and it's really easy to screw up.

input_i2s.cpp.....uses config_i2s from output_i2s.cpp and ONLY enables the RECEIVER in both master and slave begins
output_i2s.cpp.....enables RECEIVER then TRANSMITTER for both master and slave instances

input_i2s2.cpp.....uses config_i2s from output_i2s2.cpp and enables the RECEIVER then TRANSMITTER for both master and slave instances
output_i2s2.cpp....enables TRANSMITTER only for both master and slave

In the i2s(1) group the transmitter is the one that has the sync bit set in both master and slave configs because the RECEIVER bck and L/R signals are the ones of primary interest and the opposing part (TRANSMITTER) has it's sync bit set to 1.
In the i2s(2) group the receiver is the one that has the sync bit set in both master and slave configs because the TRANSMITTER bck and L/R signals are the ones of primary interest and the opposing part (RECEIVER) has it's sync bit set to 1.

Since these are crisscrossed I'd expect to see the enables in the begin() go in reverse order but they do not.

The imxrt manual is very deliberate about the enable order, except that it has a logical contradiction the way I read it. It says something to the effect of enable the transmitter before you enable the transmitter. So one of these is right and one is not. Just don't know which.

It's actually referred to twice in the same section of the manual and both sections are jibberish.

There is also what I think is a mistake and also a typo at the same time. In the i2s(1) group...the slave config_i2s leaves the unused TX FSD port on....so no real consequences but it's done with a macro (right word?) from the opposite group that happens to be equal...I2S_RCR4_FSD = 0x1....in the tcr4 section.

Code:
// configure transmitter
    I2S1_TMR = 0;
    I2S1_TCR1 = I2S_TCR1_RFW(1);  // watermark at half fifo size
    I2S1_TCR2 = I2S_TCR2_SYNC(1) | I2S_TCR2_BCP;
    I2S1_TCR3 = I2S_TCR3_TCE;
    I2S1_TCR4 = I2S_TCR4_FRSZ(1) | I2S_TCR4_SYWD(31) | I2S_TCR4_MF
        | I2S_TCR4_FSE | I2S_TCR4_FSP | I2S_RCR4_FSD;
    I2S1_TCR5 = I2S_TCR5_WNW(31) | I2S_TCR5_W0W(31) | I2S_TCR5_FBT(31);

    // configure receiver
    I2S1_RMR = 0;
    I2S1_RCR1 = I2S_RCR1_RFW(1);
    I2S1_RCR2 = I2S_RCR2_SYNC(0) | I2S_TCR2_BCP;
    I2S1_RCR3 = I2S_RCR3_RCE;
    I2S1_RCR4 = I2S_RCR4_FRSZ(1) | I2S_RCR4_SYWD(31) | I2S_RCR4_MF
        | I2S_RCR4_FSE | I2S_RCR4_FSP;
    I2S1_RCR5 = I2S_RCR5_WNW(31) | I2S_RCR5_W0W(31) | I2S_RCR5_FBT(31);
 
The files I mentioned are in the Audio library, not the core. If someone could just go ahead and delete this thread, I'd appreciate it. If you can't get the subject correct, it probably doesn't deserve a reply.
 
There is also what I think is a mistake and also a typo at the same time. In the i2s(1) group...the slave config_i2s leaves the unused TX FSD port on....so no real consequences but it's done with a macro (right word?) from the opposite group that happens to be equal...I2S_RCR4_FSD = 0x1....in the tcr4 section.

I personally tested the I2S slave mode input and output with the MICROE board with WM8731 (which runs in master mode). It worked fine, or sure seemed to work fine. Admittedly it was years ago, but the I2S code really hasn't changed since.

If there is an issue, I really need a test case which reproduces the problem.
 
Not a problem as I said. There's just a sorta typo thing and it leaves the Tx frame fsd on..which isn't used unless you change the pin configurations to use it...it's fine. My main concern or point of interest was just trying to figure out the order of enables. Since there's just one direction enacted in the Audio library with the sync going in one way for i2s2 and the other for i2s1 maybe it isn't as important as the manual says it is and the other problems a handful of other people had with sai port sync were just DMA related.
 
there's just one direction enacted in the Audio library with the sync going in one way for i2s2 and the other for i2s1

Oh, it's been years since we talked of this... But as I recall from late 2018 and early 2019 when we were all discussing which pins to bring out on Teensy 4.0 (which started beta testing in December 2018 with the RT1052 chip and switched to RT1062 in Spring 2019) we chose AD_B1_10 and AD_B1_11 to bring out LRCLK and BCLK for I2S1 because those pins have analog and a serial port, which are important features. They have SAI1_RX_SYNC and SAI1_RX_BCLK as ALT3 on their pin muxes.

Later it was decided to also bring out I2S2. The earliest beta test boards didn't bring out I2S2. Ultimately EMC_05 and EMC_06 were chosen, because they give access to PWM and also FlexIO and XBAR. Those have SAI2_TX_SYNC and SAI2_TX_BCLK on ALT2 of their pin muxes.

Had we only cared about digital audio, we would have picked other pins with SAI2_RX_SYNC and SAI2_RX_BCLK, since we brought out the "RX" versions for SAI1. But that would have meant giving up 2 pins with XBAR access. Or in an extreme example of prioritizing digital audio, maybe both RX and TX variants would have been allocated to pins, giving up 2 other pins with other non-audio features. However, it was decided we would only support I2S with RX and TX in sync, since that's the only configuration people really use in practice.

Since bringing out the RX variant on I2S2 gave 2 more pins capable of XBAR access and bringing out the TX variant on I2S1 gave access to analog pins and a serial port, the audio library has code to configure the ports so we sync both RX to TX on one port and TX to RX on the other port. It's not a bug in the code. It's just a consequence of which pins were chosen to route to Teensy 4.0 pins. The rationale was to maximize access to as many features as possible within the limited number of pins able to fit on Teensy 4.0, of course working within the constraints of how Freescale (now NXP) decided to assign the signals to pin muxes inside the chip.
 
Have a HW project up and the enable order doesn't seem to matter. I tried it both ways with DMA requests hanging off of the slave side or the master side. Doesn't seem to matter when they're right next to each other at least. Odd that the manual was so specific. I wish they'd retype whatever they were trying to say there because it's completely unreadable.

If both the transmitter and receiver use the transmitter bit clock and frame sync:
  • Configure the transmitter for asynchronous operation and the receiver for synchronous operation.
  • Enable the receiver in synchronous mode only after both the transmitter and receiver are enabled.
  • Enable the transmitter last and disable the tranmitter first.
If both the transmitter and receiver use the receiver bit clock and frame sync:
  • Configure the receiver for asynchronous operation and the transmitter for synchronous operation.
  • Enable the transmitter in synchronous mode only after both the receiver and transmitter are enabled.
  • Enable the receiver last and disable the receiver first.

Free drinks before 9:30. Doors open at 10.

Thank you Paul and co. for all of your hard work.
 
Floj you wrote: "It's actually referred to twice in the same section of the manual and both sections are jibberish.". I do not know the english word jibbberish, but it is sureley at least that ... This morning, I posted a question on NXP forum about that !
 
Back
Top