Teensy 4.0 I2S Support

Status
Not open for further replies.
Oh, did not know that. I left SCL of the DAC unconnected.

From the PCM5102A datasheet, "The serial audio interface typically has 4 connections SCK (system master clock), BCK (bit clock), LRCK (left right word clock) and DIN (data). The device has an internal PLL that is used to take either SCK or BCK and create the higher rate clocks required by the interpolating processor and the DAC clock. This allows the device to operate with or without an external SCK."

When testing with the Convolution object by DerekR I experienced strange crackling noises. Could it be that this is caused by this?

I will try to connect SCL of the DAC to pin23 of the Teensy 4.0.

I'm not sure the clicking noise you heard was this or not. But definitely worth trying.
 
The PCM5102A doesn't have software control, it's a hardware DAC. ...If it's not working with the Master Clock from the Teensy then you are running on the PLL Mode where it runs without the System Clock. Worth noting.
thanks- I got volume working with the 'amp' codeblock. "PLL mode", eh? my crackling was solved by grounding the dac's SCL- could imply something off with teensy4 mclk1? .
ordering up a couple of PCM18.. i2s adc modules to hopefully finally get the full audio processing machine i've been hacking my way towards for 5 years now.
 
Thanks for your input!

When using the DAC alone, it works perfectly both ways: either with SCL connected to GND (PLL mode) or SCL connected to pin 23 (using MCLK from the Teensy 4.0).

But when I additionally connect the ADC and run the PassThroughStereo example, I get horrible crackling noise which is also dependent on me touching various parts of the ADC circuit . . .

However, when I have everything connected exactly the same way (I use the flying wire connectors to connect the headers, not very good for > 40MHz signals . . .), but use only the DAC with the Zelda example (having the ADC wired and under power, but not úsed by the software), audio output is fine/perfect.

So, my conclusion:
* it is not the wiring / EMI that causes the crackling noise, because then I would hear it even when I use the DAC only software example
* could it be related to using the ADC as slave? Should I use it as a master (I have MD0 and MD1 connected to GND)

A little puzzling, what causes this effect.

All the best, Frank DD4WH
 
I'd also allow a question to continue thinking (my current project does NOT use the audio library, working with 24bit audio @96kHz) before my T4 will arrive: On the T3.x there was 1 single I2S with 2 FIFOs, 2 TX lines with common BCLK and LRCLK lines, allowing a synchronous 4 channel audio output.
From what I read in the MX1060 RM, there are now multiple I2S hardware instances, each with a single TX line and separate BCLK and LRCLK lines which appears to me making things more complicated for true quad channel I2S audio out. The reference manual mentions that the different I2S hardware instances might be synced together by configuration, but I didn't yet understand everything. Has anybody had a look onto this and might point me towards an emulation of T3.x's 4 channel I2S on the T4? Thank you in advance!
 
I'd also allow a question to continue thinking (my current project does NOT use the audio library, working with 24bit audio @96kHz) before my T4 will arrive: On the T3.x there was 1 single I2S with 2 FIFOs, 2 TX lines with common BCLK and LRCLK lines, allowing a synchronous 4 channel audio output.
From what I read in the MX1060 RM, there are now multiple I2S hardware instances, each with a single TX line and separate BCLK and LRCLK lines which appears to me making things more complicated for true quad channel I2S audio out. The reference manual mentions that the different I2S hardware instances might be synced together by configuration, but I didn't yet understand everything. Has anybody had a look onto this and might point me towards an emulation of T3.x's 4 channel I2S on the T4? Thank you in advance!

My Teensy4 hasn't arrived yet, but I've been assuming the use of OUT1A, OUT1B, OUT1C and OUT1D together with MCLK1, BCLK1 and LRCLK1 wukk give a standard 4 channel I2S. I wasn't going to use OUT2 or it's MCLK and other pins.
 
From what I read in the MX1060 RM, there are now multiple I2S hardware instances, each with a single TX line and separate BCLK and LRCLK lines which appears to me making things more complicated for true quad channel I2S audio out.

Indeed there are now 3 separate I2S peripherals inside the chip, 2 of which can be accessed on Teensy 4.0 pins.

But they are not created equal. The first one has 5 data pins, which is actually 1 more data pin than Teensy 3.x. So with the right programming, I'm pretty sure Teensy 4.0 can do the quad channel feature we've had for years on Teensy 3.x.

The other I2S peripherals are indeed limited to 1 TX pin and 1 RX pin, so only stereo is possible on those, unless a multi-channel protocol like TDM is used.

The situation with those 5 pins could be called "more flexible" or "more complicated" than Teensy 3.x, depending on your perspective. So far I've not actually used them, so all of this is based only on my reading of the ref manual. On Teensy 3.x, 2 of the data pins always transmit and 2 always receive. Simple. On Teensy 4.0, 3 of the 5 data pins can transmit or receive, depending on how you configure the hardware. I believe NXP's intention was to allow stereo input and 8 channel output, or 8 channel input and stereo output. I'm not sure if 4 and 6 channel configurations also work. It's on my list of stuff to do...

On the pinout reference card, I had to make some compromises for the sake of simplicity and limited space. So the 5 data signals are labeled "IN1, OUT1A, OUT1B, OUT1C, OUT1D", which implies the mode of stereo input and 8 channel output. 1 of these 5 is on a bottom side pad, because again so many difficult trade offs were required in assigning the pinout.

In the absence of software support for actually using more than 2 data pins, probably the easiest way to get quad channel support right now would be to just use the 2nd I2S port.
 
Indeed there are now 3 separate I2S peripherals inside the chip, 2 of which can be accessed on Teensy 4.0 pins.

But they are not created equal. The first one has 5 data pins, which is actually 1 more data pin than Teensy 3.x. So with the right programming, I'm pretty sure Teensy 4.0 can do the quad channel feature we've had for years on Teensy 3.x.

The other I2S peripherals are indeed limited to 1 TX pin and 1 RX pin, so only stereo is possible on those, unless a multi-channel protocol like TDM is used.

The situation with those 5 pins could be called "more flexible" or "more complicated" than Teensy 3.x, depending on your perspective. So far I've not actually used them, so all of this is based only on my reading of the ref manual. On Teensy 3.x, 2 of the data pins always transmit and 2 always receive. Simple. On Teensy 4.0, 3 of the 5 data pins can transmit or receive, depending on how you configure the hardware. I believe NXP's intention was to allow stereo input and 8 channel output, or 8 channel input and stereo output. I'm not sure if 4 and 6 channel configurations also work. It's on my list of stuff to do...

On the pinout reference card, I had to make some compromises for the sake of simplicity and limited space. So the 5 data signals are labeled "IN1, OUT1A, OUT1B, OUT1C, OUT1D", which implies the mode of stereo input and 8 channel output. 1 of these 5 is on a bottom side pad, because again so many difficult trade offs were required in assigning the pinout.
.

I hadn't read the datasheet yet (my Teensy hasn't even arrived) but if you are saying that OUT2/3/4 can be made into inputs that's fantastic news. A small complete digital mixer on a Teensy !
 
Indeed there are now 3 separate I2S peripherals inside the chip, 2 of which can be accessed on Teensy 4.0 pins.

But they are not created equal. The first one has 5 data pins, which is actually 1 more data pin than Teensy 3.x. So with the right programming, I'm pretty sure Teensy 4.0 can do the quad channel feature we've had for years on Teensy 3.x.

The other I2S peripherals are indeed limited to 1 TX pin and 1 RX pin, so only stereo is possible on those, unless a multi-channel protocol like TDM is used.

The situation with those 5 pins could be called "more flexible" or "more complicated" than Teensy 3.x, depending on your perspective. So far I've not actually used them, so all of this is based only on my reading of the ref manual. On Teensy 3.x, 2 of the data pins always transmit and 2 always receive. Simple. On Teensy 4.0, 3 of the 5 data pins can transmit or receive, depending on how you configure the hardware. I believe NXP's intention was to allow stereo input and 8 channel output, or 8 channel input and stereo output. I'm not sure if 4 and 6 channel configurations also work. It's on my list of stuff to do...

On the pinout reference card, I had to make some compromises for the sake of simplicity and limited space. So the 5 data signals are labeled "IN1, OUT1A, OUT1B, OUT1C, OUT1D", which implies the mode of stereo input and 8 channel output. 1 of these 5 is on a bottom side pad, because again so many difficult trade offs were required in assigning the pinout.

In the absence of software support for actually using more than 2 data pins, probably the easiest way to get quad channel support right now would be to just use the 2nd I2S port.

Thank you, Paul! I'll have obviously to dive deeper into the reference manual this weekend. 2 data pins on one I2S for quad channel audio output will be sufficient for my project. Inputs are not needed.
 
On the pinout reference card, I had to make some compromises for the sake of simplicity and limited space. So the 5 data signals are labeled "IN1, OUT1A, OUT1B, OUT1C, OUT1D", which implies the mode of stereo input and 8 channel output. 1 of these 5 is on a bottom side pad, because again so many difficult trade offs were required in assigning the pinout.

Any plans for a larger Teensy4.5/6 later like the 3.5/6 to overcome the pinouts issue ? I suspect a lot of people may prefer that for such a powerful processor.
 
I found the cause for my non- or mis-understanding. The reference manual does mention that SAI1 is multi channel capable but the documentation afterwards does not give any detail beyond the 1 single TX data line mode. Inquiring somewhat further, I found this application note which shows at least that TCR3 has not 1 but 4 bit fields for the up to 4 TX channels and that the (undocumented in the RM) additional transmit registers TDR1 to TDR3 exist besides TDR0. Now I'll still have to find out what their address offsets are...
 
Rev D is coming soon. Here's the first prototype, on my desk right now...

...

Paul - is the Rev D final silkscreen committed? - I should have mentioned this earlier - during the T4 Beta handling the Audio boards I have to work to find which end is the GND/USB end to orient with Teensy. If not too late having a 'GND' end PIN indicator of some sort could help.
 
I updated the audio shield page recently, with this:



When I get some time, will add a photo of the required wiring. A photo should be a lot more visible than just this text.

Hi Paul

Reading the post led me to wonder about something else. I'm not too familiar with how the audio library for the Teensy audio shield is constructed, but it seems to expect certain Teensy pins to be used. I was wondering, how feasible would it be to make the audio library generic such that the user/programmer can choose which Teensy (I2S) pins to assign in the code? Is this possible to do (in theory) given the limitation of assigning the use to digital IO pins of the Teensy? In that way the use of the library would be possible for any kind of pin choice or Teensy 3.x or Teensy4?

Would like to understand this better,

Thanks
Erik
 
Hi Paul

Reading the post led me to wonder about something else. I'm not too familiar with how the audio library for the Teensy audio shield is constructed, but it seems to expect certain Teensy pins to be used. I was wondering, how feasible would it be to make the audio library generic such that the user/programmer can choose which Teensy (I2S) pins to assign in the code? Is this possible to do (in theory) given the limitation of assigning the use to digital IO pins of the Teensy? In that way the use of the library would be possible for any kind of pin choice or Teensy 3.x or Teensy4?

Would like to understand this better,

Thanks
Erik

I suspect this is just impossible, unless you resort to bit-banging (i.e. manually turning the pins on/off and not using the hardware supports, which would be sloooooooooooow). You have to understand that these modern chips have things like SPI, I2S, I2C, in hardware, and there are only so many combinations that are supported.
 
I suspect this is just impossible, unless you resort to bit-banging (i.e. manually turning the pins on/off and not using the hardware supports, which would be sloooooooooooow). You have to understand that these modern chips have things like SPI, I2S, I2C, in hardware, and there are only so many combinations that are supported.

Thanks for the explanation MichaelMeissner
 
Note : The iMX_RT_1060 reference manual has an error in the audio section, the extended memory map and configuration for multi-channel I2S with SAI1 is missing. Please refer to the iMX_RT_1064 reference manual, it has the full and correct description.
 
Note : The iMX_RT_1060 reference manual has an error in the audio section, the extended memory map and configuration for multi-channel I2S with SAI1 is missing. Please refer to the iMX_RT_1064 reference manual, it has the full and correct description.

Can you please post a link to he right datasheet? I'm also not finding the 5 data pins on the first SAI. I did find a note about 4 data pins in the application note but not 5. I wanted to read up about switching the lines from rx/tx. I'm looking for confirmation about how the pins can be either receiving or transmitting.

My use case is a digital mixer. Without using TDM I would get 12 inputs and 2 outputs (nice). One can also get 12 outputs and 2 inputs. When using TDM things get super interesting (feasible? Idk). Using TDM, one can have 48 inputs (6x8) and 8 outputs. One can also have 48 outputs, and 8 inputs. That's a lot of channels, so I don't know if the hardware can handle it. I also know the software isn't ready. But it's interesting to study nonetheless and I'm toying with some designs in kicad to expose the lines along with some buffers to properly send the clocks to the modules using octal buffers... This would expose the 12/2, 2/12, 48/8, 8/48 options I just mentioned to expansion headers so we can hook up modules to the breakout board.

My hope for the breakout board is to make software development easier...
 
Yup, pretty much. It came up during the beta test and was discussed somewhere in the 4000+ message beta test thread.

Fortunately it was discovered long enough ago that we were able to make a revision to add the resistor on the audio shield by the time of Teensy 4.0's release.

Hey Paul or anyone from the Beta who worked on I2C/I2S, question about this resistor. At first, I couldn't get my T4 working with my WM8731. As we already know, the WM8731 is sensitive to overly fast edges. It appears the T4 is using default I/O output pad settings, it doesn't change based on the function they are assigned to. This was causing me issues as the default configuration had too fast a slew rate and too strong a drive strength for I2S and I2C pins which are of course slow and very slow respectively.

I was able to get the codec working flawlessly in the end but had to make a few changes:

#1 In WireIMXRT.cpp there a couple functions with infinite while (1) loops waiting for an event with a note that says // TODO: timeout .... My bus errors were freezing the bus in a busy state and this was hanging the CPU in these infinite loops so I had to add a timeout. This fixed the CPU hanging but of course the bus errors themselves were still a problem.

#2 So, I was still getting very serious bus errors, even retries weren't enough to make the codec work. By reconfiguring the various output pads appropriately for slow interfaces, 100% of the bus errors went away. Specifically setting the slew rate slow, and the drive strength to minimum for all I2C pins and I2S outputs. Furthermore, The I2C didn't appear have open-drain enabled? so I added that as well. The following fixed all the signal reflections causing problems:
Code:
// defaults were all 0x10B0 which is keeper, Medium speed (100 Mhz), drive strength = R0/6 = 150/6 = 25 ohms (the second strongest drive strength available)
// My changes were:
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_00 = 0xF808; // SCL, pullup at 22K, open drain enable, low speed, drive strength at R0 (150 ohm)
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_01 = 0xF808; // SDA
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09 = 0x8; // MCLK, low speed, drive strength at R0 (150 ohm).
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_10 = 0x8; // BCLK
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_11 = 0x8; // LRCLK
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_01 = 0x8; // OUT1A

Shouldn't the output drivers be configured similarly for low speed interfaces to prevent reflections? The drive strength is controlled by the output series resistor in the pad. Specifically for MCLK, the default is 25 ohm, and you've added a 100 ohm resistor to the board effectively making the drive strength 125 ohm. Wouldn't changing the output driver from R0/6 to R0 have accomplished the same thing (sets drive strength to 150 ohm)?
 
Last edited:
Very interesting! It would be nice to know where and how exactly you changed the files (but maybe that will soon be incorporated in the next Teensyduino version?).

I would just like to report my very similar experience with the Teensy audio Board & T4, which I connected with very short soldered wires (max. 2.5cm !, 100 Ohms series resistor to MCLK) to the Teensy 4.0 and additionally the PCM1808 ADC which I tried to connect to the T4. I know this is not state-of-the-art, because of no ground plane, but I thought that this short wire length would be sufficient.

--> Both setups (Teensy audio board & T4; PCM1808 & T4) did not run properly/reliably at the standard sample rate. There was annoying drizzling noise and all sorts of malfunction: I suspect this has the same cause as reported by Blackaddr, because the problem was cured by using sample rates lower than 24ksps . . .

This is just to report that similar problems are present in other ADC/DAC/codecs and to me it seems the post by Blackaddr adresses exactly this problem, although I am far from understanding the underlying details.
 
Can you please post a link to he right datasheet? I'm also not finding the 5 data pins on the first SAI. I did find a note about 4 data pins in the application note but not 5. I wanted to read up about switching the lines from rx/tx. I'm looking for confirmation about how the pins can be either receiving or transmitting.

My use case is a digital mixer. Without using TDM I would get 12 inputs and 2 outputs (nice). One can also get 12 outputs and 2 inputs. When using TDM things get super interesting (feasible? Idk). Using TDM, one can have 48 inputs (6x8) and 8 outputs. One can also have 48 outputs, and 8 inputs. That's a lot of channels, so I don't know if the hardware can handle it. I also know the software isn't ready. But it's interesting to study nonetheless and I'm toying with some designs in kicad to expose the lines along with some buffers to properly send the clocks to the modules using octal buffers... This would expose the 12/2, 2/12, 48/8, 8/48 options I just mentioned to expansion headers so we can hook up modules to the breakout board.

My hope for the breakout board is to make software development easier...

The iMX_RT_1064 reference manual with the missing registers and values for multi-channel SAI1 is here. (You need probably register at NXP to have access. That's free)

The 5 data pins for SAI1 and their multiplexing which can be configured for all variants of TX0 (RX3/TX1) (RX2/TX2) (RX1/TX3) RX0 are correctly documented on page 310 of the iMX_RT_1060 reference manual.
 
Shouldn't the output drivers be configured similarly for low speed interfaces to prevent reflections?

The other interfaces aren't as critical as in this case they are all just allowed to settle and then clocked in by MCLK so it is this line that it is essential there are no reflections. STMicroelectronics MCUs have special circuitry to avoid this problem but NXP seem a little different.

But anyone using ADC or DACs without an MCLK (e.g. PCM5102) it is essential to avoid reflections so you need to get the line matching perfect or there will be jitter in the regenerated clock.
 
The other interfaces aren't as critical as in this case they are all just allowed to settle and then clocked in by MCLK so it is this line that it is essential there are no reflections.

In general this is true. But you also need to consider PCB routing. Tracks with fast edges can couple into adjacent tracks where then run close and parallel. Thus, data lines that run right next to clock lines can have their reflections (caused by fast edges) couple into the clock line where they run parallel.

Fast edges also emit more EMI which can cause interference in nearby analog circuits. Since we're talking about an audio codec here this is very important. My recommendation is that all digital output drivers be configured for the slowest edges and power that still provides high data integrity, not just for the clock output. This is a common design rule at my current employer where EMI and power are tightly constrained.
 
In general this is true. But you also need to consider PCB routing. Tracks with fast edges can couple into adjacent tracks where then run close and parallel. Thus, data lines that run right next to clock lines can have their reflections (caused by fast edges) couple into the clock line where they run parallel.

Fast edges also emit more EMI which can cause interference in nearby analog circuits. Since we're talking about an audio codec here this is very important. My recommendation is that all digital output drivers be configured for the slowest edges and power that still provides high data integrity, not just for the clock output. This is a common design rule at my current employer where EMI and power are tightly constrained.

Yes I was assuming good PCB design. Resistors on all tracks (or configuring the internal ones on STM MCUs) right near the source (which remember is at the other end sometimes !) is always best, but if you don't have the space then the MCLK is a must, the rest are try to dos.
 
@Blackaddr: could you point me in the right direction where I could add your register settings (in which file)?

I tried to add them in my sketch in the setup, but no success, it seems to make no difference.
Code:
// defaults were all 0x10B0 which is keeper, Medium speed (100 Mhz), drive strength = R0/6 = 150/6 = 25 ohms (the second strongest drive strength available) // My changes were:
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_00 = 0xF808; // SCL, pullup at 22K, open drain enable, low speed, drive strength at R0 (150 ohm)
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_01 = 0xF808; // SDA
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09 = 0x8; // MCLK, low speed, drive strength at R0 (150 ohm).
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_10 = 0x8; // BCLK
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_11 = 0x8; // LRCLK
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_01 = 0x8; // OUT1A
 
@DD4WH: The assignments can likely go anywhere after you've called Wire.begin() for I2C, during my testing I had them at the end of setup(). The I2S stuff starts up as soon as the I2S object is created and most people do that with a global variable so it's well before setup().

Note also those pad controls I posted are for very specific pins. (SCL=19, SDA=18, MCLK=23, BCLK=21, LRCLK=20,DIN=8, DOUT=7) in case people have different custom audio boards.

DD4WH: I think you've actually got a different problem than I had.

My particular issue is the WM8731 codec has an SCL line that is very sensitive to noise/reflections on the BCLK line. For the 6 pins I listed above, in my case only one actually matters, BCLK output. If I change the other 5, I still get the problem, because the fast edges on BCLK are the only problem actually manifesting as errors on another bus for me. So my symptom is the I2C bus hangs because the SCL is a victim to the BCLK aggressor. I don't get any audio glitches on the I2S though, it's just the I2C bus having lots of errors and hanging.

In your case, you've found that reducing the sampling fixes things, right? That suggests signal edges are NOT your problem (or not your only problem) because edge reflections are based solely on the edge speeds, not the overall clock/data rate. Even a very slow clock can have fast edges causing reflections so turning down the clock doesn't usually help.

I proposed altering the configuration of all those output pads as I believe it is simply good practice to configure them optimally for the interface they're using, many people have no problems with the defaults.
 
Blackaddr, thanks a lot for your detailed explanation!

OK, I now understood the difference between the I2C and the I2S problems ;-). But I am still struggling with my problems, could not cure them with the code.

However, I have not understood where to change the setting of I2S drive strength . . . can that be changed on-the-fly after initialization of the I2S lines? Probably not. So I searched for the files where the I2S is initialized for T4. Is it here ??? Strange that totally different pins are initialized in configI2S (pin 5: MCLK, pin 4: BCLK, pin 3: TX):

https://github.com/PaulStoffregen/Audio/blob/master/output_i2s2.cpp

I guess I am really missing something here . . . I am travelling at the moment, so my further tests will be continued in a week.
 
Status
Not open for further replies.
Back
Top