Finding I2S Pins on Pinout Diagram

Status
Not open for further replies.
I'm having trouble understanding which pins on a Teensy (or any other micro) are suitable for I2S. On the "Output to I2S" page I see the following:

Pin 09 = BCLK
Pin 11 = MCLK
Pin 22 = TX
Pin 23 = LCRLK

What about these pins makes them usable for I2S and which pins comprise the second I2S output on Teensy 3.2 and up? Can I move these to other pins as long as I use a CS pin for BCLK and a DOUT pin for MCLK? Are Pins 22 and 23 special in some way as well?

Lastly, I gather from my reading that LCRLK is sometimes called LRC and MCLK is not always used - but I'm not sure why that is.

Thanks all!
 
I'm having trouble understanding which pins on a Teensy (or any other micro) are suitable for I2S. On the "Output to I2S" page I see the following:

Pin 09 = BCLK
Pin 11 = MCLK
Pin 22 = TX
Pin 23 = LCRLK

What about these pins makes them usable for I2S and which pins comprise the second I2S output on Teensy 3.2 and up? Can I move these to other pins as long as I use a CS pin for BCLK and a DOUT pin for MCLK? Are Pins 22 and 23 special in some way as well?

Lastly, I gather from my reading that LCRLK is sometimes called LRC and MCLK is not always used - but I'm not sure why that is.

Thanks all!
If you plan to use, Audio library, you cannot easily change these pins. The MCLK pin is fixed and cannot be changed. The use of a MCLK signal depends on the ADC/DAC/Codec used and is required for the SGTL500 in the audio adapter. Other I2S devices (e.g. ICS43432 Mic) do not use MCLK signal, so this pin is free and can be reconfigured.
The use of MCLK requires that BCLK and FS are controlled by output (TX_BCLK and TX_FS) which is legitimate as the RX side is internally slaved to TX.

The output/input bins are defined in the relative .h/.cpp files. In particular, the second input/output data lines are given in the quad version of these files.

If you plan to change the audio library or write your own I2S interface, you should consult the MK22/65/66 documentation you can find on PJRC web site.
 
The short answer is to just use the default pins and work the rest of your project around those I2S pins being consumed for digital audio. Using any other pins for I2S is quite hard to do, and even if you go to all that trouble, it will only buy you a very limited set of not-so-satisfying alternatives.

Now if you don't like the short answer, and from your question I'm imagining you won't, maybe you're ready to dig into the rather difficult work to discover only very limited choices?

You first stop is at the schematic, to translate the Arduino pin numbers to Freescale's native port names.

https://www.pjrc.com/teensy/schematic.html

As an example, LRCLK uses pin 23, which is PTC2 on the chip. Everything in Freescale's documentation will be in terms of PTC2, not pin 23 as used in Arduino.

The next step is the MK20DX256 reference manual.

https://www.pjrc.com/teensy/datasheets.html

The info you seek is in chapter 10, in a huge table which starts on page 207.

As you scroll through the table, you'll find PTC2 near the top of page 209.

Every pin can be configured to do 1 of up to 8 possible things. In this case of PTC2, 7 of the 8 slots are filled. If configured to ALT7 the pin will do nothing. You can see in the table that ALT6 is "I2S0_TX_FS". Again, slightly different names are used, but "FS" and "LRCLK" mean the same thing, at least within the context of the I2S port configured for normal I2S mode. In some of the other modes, particularly TDM mode, "FS" would be a much more appropriate name....

So, if you want to find another choice, you need to scan through this giant table to find another pin which offers "I2S0_TX_FS" on any of its 8 functions. No amount of wishful thinking will let any other pin work. Inside the chip there's a "FS" signal wanting to get out to your I2S chip, but it can only get to the outside world though pins where one of the 8 ALT# configurations actually connects that signal inside the chip to the pin's driver circuitry.

A quick search shows the PTA13 (on page 208) and PTB19 (on page 209) are your only other options, other than the default on PTC2. I2S0_TX_FS doesn't appear anywhere else in the table, so there simply are no other pins on the entire chip with the physical ability to get this particular signal to you.

With this info, you go back to the schematic and find those pins. PTA13 is Arduino pin #3, and PTB19 is Arduino pin #30. Since pin 30 is one of not-as-easily-accessible bottom side pads, maybe you'd be more interested in pin 3.

Now in the last step, you would edit the I2S code. But before I describe this, it's essential you've followed these steps and understand the signal inside the chip can physically only connect to those 3 pins, using the ALT# settings described in that big table. The way the code looks might lead you to falsely believe you could configure other choices. You can indeed write any ALT# setting to any pin... but doing so will result in the signals described in that big table, because that's how Freescale internally wired the signals inside the chip.

In this case, the code happens to be at line 336 in output_i2s.cpp:

https://github.com/PaulStoffregen/Audio/blob/master/output_i2s.cpp#L335

Code:
        // configure pin mux for 3 clock signals
        CORE_PIN23_CONFIG = PORT_PCR_MUX(6); // pin 23, PTC2, I2S0_TX_FS (LRCLK)
        CORE_PIN9_CONFIG  = PORT_PCR_MUX(6); // pin  9, PTC3, I2S0_TX_BCLK
        CORE_PIN11_CONFIG = PORT_PCR_MUX(6); // pin 11, PTC6, I2S0_MCLK

Fortunately the header files define convenient names for the pin config registers, so you don't need to go look those up in chapter 11. Since you know pin 3 supports this signal on ALT3, you could just change the first line to this:

Code:
        CORE_PIN3_CONFIG = PORT_PCR_MUX(6); // pin 3, PTA13, I2S0_TX_FS (LRCLK)

As simple as this code looks, it's easy to get things wrong. You can change any pin to any of its 8 ALT# settings. That could result in very confusing problems if you mistakenly connect some other pin to whatever signal happens to be wired to its ALT setting within the chip.
 
Thank you both, this is great information! Seriously, I really appreciate the thorough responses. I love learning this stuff.

Paul, I think I can manage the changes you're talking about, but you have convinced me to plan around it if possible. I might not have to move I2S for my project - I was interested because I'm trying to get audio out, WiFi, onehorse's Ultimate Sensor Fusion, and file storage added to a single Teensy and I hadn't found the right combination of pins yet. I think I'll give this design another shot and then post in the project guidance forum asking about it, before I worry about I2S.
 
Last edited:
Hi, I found an easy hack on how to change I2S pinout on my project that uses Teensy 3.6 in it.
I used to edit the Audio Library to implement my own pinout, and whenever I update Teensyduino, I have to update it again.
So here, I let my sketch (the .ino file) do the work, without bothering touching the Teensyduino files and libraries.
Code:
void UDA1345TS_setup() {
  // set default I2S pins to INPUT or OUTPUT
  pinMode(13, OUTPUT);       // default I2S0_RXD0           (Built-in LED)
  pinMode(38, INPUT_PULLUP); // default I2S0_RXD1           (connected to ENC2B)
  pinMode(22, INPUT);        // default I2S0_TXD0           (connected to VPOT07)
  pinMode(15, INPUT_PULLUP); // default I2S0_TXD1           (connected to BPMBTN)
  pinMode(23, INPUT);        // default I2S0_TX_FS (LRCLK)  (connected to VPOT08)
  pinMode( 9, OUTPUT);       // default I2S0_TX_BCLK        (connected to LCD RS)
  pinMode(11, OUTPUT);       // default I2S0_MCLK           (connected to LEDCLK)
  // set alternate I2S pinout
  CORE_PIN27_CONFIG = PORT_PCR_MUX(6); // I2S0_RXD0
  CORE_PIN28_CONFIG = PORT_PCR_MUX(7); // I2S0_RXD1
  CORE_PIN3_CONFIG  = PORT_PCR_MUX(6); // I2S0_TXD0
  CORE_PIN26_CONFIG = PORT_PCR_MUX(7); // I2S0_TXD1
  CORE_PIN30_CONFIG = PORT_PCR_MUX(4); // I2S0_TX_FS (LRCLK)
  CORE_PIN29_CONFIG = PORT_PCR_MUX(4); // I2S0_TX_BCLK
  CORE_PIN35_CONFIG = PORT_PCR_MUX(4); // I2S0_MCLK
}
I call this function on top of setup(). Now I can use the old I2S pinout for other purposes, especially the built-in LED. Also, I picked this new pinout to free up the analog input pins occupied by the old pinout, and to have the pins close to each other (except pin 3 and 35 :D). On my project, a 20x4 HD44780-compatible LCD, a rotary encoder, an arcade button, 2 pots, and 2 74HC595 shift registers are connected to the default I2S pins and these pins appear to be standard I/O again after calling the function (by pinMode() calls?). My usage of the I2S module inside the Teensy does not interfere with these devices, at least for me.

Available I2S pinouts for Teensy 3.x
ex. I2S0_RXD0 13(4) means pin13 on Teensy at MUX(4) can be used for RXD0 so you can use "CORE_PIN13_CONFIG = PORT_PCR_MUX(4);"
Code:
Teensy 3.0
I2S0_RXD0             13(4)
I2S0_TXD0             3(6)      22(6)
I2S0_TX_FS (LRCLK)    4(6)      23(6)     25(4)
I2S0_TX_BCLK          9(6)      24(6)     32(4)
I2S0_MCLK             11(6)     28(4)
Code:
Teensy 3.1 / Teensy 3.2
I2S0_RXD0             13(4)
I2S0_RXD1             30(4)
I2S0_TXD0             3(6)      22(6)
I2S0_TXD1             15(6)
I2S0_TX_FS (LRCLK)    4(6)      23(6)     25(4)
I2S0_TX_BCLK          9(6)      24(6)     32(4)
I2S0_MCLK             11(6)     28(4)
Code:
Teensy 3.5 / Teensy 3.6
I2S0_RXD0             13(4)     27(6)
I2S0_RXD1             28(7)     38(4)
I2S0_TXD0             3(6)      22(6)     56(4)
I2S0_TXD1             15(6)     26(7)
I2S0_TX_FS (LRCLK)    4(6)      23(6)     30(4)     57(4)
I2S0_TX_BCLK          9(6)      25(6)     29(4)
I2S0_MCLK             11(6)     35(4)     39(6)
Note: As Paul said, only certain pins are capable of doing I2S because it is hardware-dependent, and the three tables above are the only pin possibilities. Double-check pin configs before testing new pinouts.
 
Last edited:
Hi, I found an easy hack on how to change I2S pinout on my project that uses Teensy 3.6 in it.
I used to edit the Audio Library to implement my own pinout, and whenever I update Teensyduino, I have to update it again.
So here, I let my sketch (the .ino file) do the work, without bothering touching the Teensyduino files and libraries.
Code:
void UDA1345TS_setup() {
  // set default I2S pins to INPUT or OUTPUT
  pinMode(13, OUTPUT);       // default I2S0_RXD0           (Built-in LED)
  pinMode(38, INPUT_PULLUP); // default I2S0_RXD1           (connected to ENC2B)
  pinMode(22, INPUT);        // default I2S0_TXD0           (connected to VPOT07)
  pinMode(15, INPUT_PULLUP); // default I2S0_TXD1           (connected to BPMBTN)
  pinMode(23, INPUT);        // default I2S0_TX_FS (LRCLK)  (connected to VPOT08)
  pinMode( 9, OUTPUT);       // default I2S0_TX_BCLK        (connected to LCD RS)
  pinMode(11, OUTPUT);       // default I2S0_MCLK           (connected to LEDCLK)
  // set alternate I2S pinout
  CORE_PIN27_CONFIG = PORT_PCR_MUX(6); // I2S0_RXD0
  CORE_PIN28_CONFIG = PORT_PCR_MUX(7); // I2S0_RXD1
  CORE_PIN3_CONFIG  = PORT_PCR_MUX(6); // I2S0_TXD0
  CORE_PIN26_CONFIG = PORT_PCR_MUX(7); // I2S0_TXD1
  CORE_PIN30_CONFIG = PORT_PCR_MUX(4); // I2S0_TX_FS (LRCLK)
  CORE_PIN29_CONFIG = PORT_PCR_MUX(4); // I2S0_TX_BCLK
  CORE_PIN35_CONFIG = PORT_PCR_MUX(4); // I2S0_MCLK
}
I call this function on top of setup(). Now I can use the old I2S pinout for other purposes, especially the built-in LED. Also, I picked this new pinout to free up the analog input pins occupied by the old pinout, and to have the pins close to each other (except pin 3 and 35 :D). On my project, a 20x4 HD44780-compatible LCD, a rotary encoder, an arcade button, 2 pots, and 2 74HC595 shift registers are connected to the default I2S pins and these pins appear to be standard I/O again after calling the function (by pinMode() calls?). My usage of the I2S module inside the Teensy does not interfere with these devices, at least for me.

Available I2S pinouts for Teensy 3.x
ex. I2S0_RXD0 13(4) means pin13 on Teensy at MUX(4) can be used for RXD0 so you can use "CORE_PIN13_CONFIG = PORT_PCR_MUX(4);"
Code:
Teensy 3.0
I2S0_RXD0             13(4)
I2S0_TXD0             3(6)      22(6)
I2S0_TX_FS (LRCLK)    4(6)      23(6)     25(4)
I2S0_TX_BCLK          9(6)      24(6)     32(4)
I2S0_MCLK             11(6)     28(4)
Code:
Teensy 3.1 / Teensy 3.2
I2S0_RXD0             13(4)
I2S0_RXD1             30(4)
I2S0_TXD0             3(6)      22(6)
I2S0_TXD1             15(6)
I2S0_TX_FS (LRCLK)    4(6)      23(6)     25(4)
I2S0_TX_BCLK          9(6)      24(6)     32(4)
I2S0_MCLK             11(6)     28(4)
Code:
Teensy 3.5 / Teensy 3.6
I2S0_RXD0             13(4)     27(6)
I2S0_RXD1             28(7)     38(4)
I2S0_TXD0             3(6)      22(6)     56(4)
I2S0_TXD1             15(6)     26(7)
I2S0_TX_FS (LRCLK)    4(6)      23(6)     30(4)     57(4)
I2S0_TX_BCLK          9(6)      25(6)     29(4)
I2S0_MCLK             11(6)     35(4)     39(6)
Note: As Paul said, only certain pins are capable of doing I2S because it is hardware-dependent, and the three tables above are the only pin possibilities. Double-check pin configs before testing new pinouts.

I'm trying to use move the STGL5000 audio board on teensy 3.6 so it doesn't use pins 18 and 19, so I can use them for capacitive sensing.

However, I'm struggling. As I understand it, I need to move I2C0_SCL and I2C0_SDA for pins 19 and 18 respectively.

Could anyone confirm if I've understood it right? For pin 18 (LQFP location 45 for quick table referencing - 19 is LQFP 46 - all on Page 186 of the manual) I think I've got the MUX correct - but it doesn't work. Do I need to change the code somewhere else instead? I'm calling it at start of setup.

Thanks for the help! Much appreciated.

Code:
void UDA1345TS_setup() {
  // set default I2C pins to INPUT or OUTPUT
  pinMode(19, OUTPUT);       // default STGL I2C0_SCL - changing it to something else so can be used for capsensing!
  pinMode(18, OUTPUT);        // default STGL I2C0_SDA
  // set alternate I2C pinout
  CORE_PIN33_CONFIG = PORT_PCR_MUX(5); // replacement I2C0_SCL
  CORE_PIN34_CONFIG = PORT_PCR_MUX(5); // replacement I2C0_SDA
}
 
Reading my card: Available alternate SDA0/SCL0 are pins 34/33 and non-touch - if they can be specified as such with Wire init - would take care of it?

Search forum for example usage?:
Code:
    void setSDA(uint8_t);
    void setSCL(uint8_t);

My current code does this to use the bottom pin alternates for MPU9250 9DOF board on Wire with i2c0:
Code:
#define IMU_SCL       47
#define IMU_SDA       48

  //init imu
  // start communication with IMU 
  Wire.setSCL(IMU_SCL);
  Wire.setSDA(IMU_SDA);
  status = Imu.begin();
  if ( 0 != IMU_SPD ) Wire.setClock(IMU_SPD);

  // Initalize IMU   
  initIMU();
 
Reading my card: Available alternate SDA0/SCL0 are pins 34/33 and non-touch - if they can be specified as such with Wire init - would take care of it?

Search forum for example usage?:
Code:
    void setSDA(uint8_t);
    void setSCL(uint8_t);

My current code does this to use the bottom pin alternates for MPU9250 9DOF board on Wire with i2c0:
Code:
#define IMU_SCL       47
#define IMU_SDA       48

  //init imu
  // start communication with IMU 
  Wire.setSCL(IMU_SCL);
  Wire.setSDA(IMU_SDA);
  status = Imu.begin();
  if ( 0 != IMU_SPD ) Wire.setClock(IMU_SPD);

  // Initalize IMU   
  initIMU();

Yes thanks! Did the trick - my understanding of I2C and I2S was very poor and I didn't realise they were independant libraries.

Code:
Wire.setSDA(34);
Wire.setSCL(33);
 
:cool: - yes I saw the I2S note and was going to say that is very pin limited AFAIK - but saw the i2c was the real problem.
 
is there any way to make the audio shield work with teensy 3.6 without using any portc or portb pins?
I tried resid example and I only get a hissing sound and low volume music in the background.
 
is there any way to make the audio shield work with teensy 3.6 without using any portc or portb pins?

Yes, but only with edits deep in the audio library. All of the I2S signals are possible on port A pins, and 2 are possible on port E pins.

Code:
I2S_MCLK        39/PTA17
I2S_TXD0        3/PTA12         56/PTE10
I2S_TX_FS       4/PTA13         57/PTE11
I2S_TX_BCLK     25/PTA5                         
I2S_RXD0        27/PTA15

To use these alternates, you have to edit the I2S code in the audio library which configures the pin muxes.
 
Thank you @paulstoffregen for the quick reply.
Thats exactly the pinout I used plus
Code:
 Wire.setSDA(34);
Wire.setSCL(33);
for i2c pins.
after reading through the forum I am thinking that i am getting that hissing sound because i am using long cables for the connections (uncut 20cm long jumper wires) on a breadboard
I made a sid chip replacement for the commodore 64 using teensy and I am doing reads on address and data lines on portb and portc pins thats why I cant use any of those pins.
Another question. Are any of the clock signals affected if I am overclocking teensy?
 
Fortunately the header files define convenient names for the pin config registers, so you don't need to go look those up in chapter 11. Since you know pin 3 supports this signal on ALT3, you could just change the first line to this:
Code:
CORE_PIN3_CONFIG = PORT_PCR_MUX(6); // pin 3, PTA13, I2S0_TX_FS (LRCLK)
This last code contradicts what you're saying. It should be:
Code:
        CORE_PIN3_CONFIG = PORT_PCR_MUX(4); // pin 3, PTA13, I2S0_TX_FS (LRCLK)
 
Status
Not open for further replies.
Back
Top