To test the code we are going to use the MIMXRT685-EVK board connected to the Jetson AGX Orin and to a PC host both running Linux.
- JP12 jumper must be set:
- 2-3 when connected to the Jetson 40-pin header
- 1-2 when connected to coaster
For our use-case we need that to be in position 2-3.
- JP4 must be closed to be able to use the FC0 UART
For the I2S part we are going to use FLEXCOMM4 and FLEXCOMM6 for the TX, and FLEXCOMM5 and FLEXCOMM7 for RX.
Several signals are shared internally so we are only going to interface externally with FLEXCOMM4 on the header J27 and with FLEXCOMM5 on the header J28.
In particular:
- J28.7 - GND
- J28.6 - CLK [ PIO1_3/FC5_SCK ]
- J28.5 - FSYNC [ PIO1_4/FC5_TXD_SCL_MISO_WS ]
- J28.4 - SDIN [ PIO1_5/FC5_RXD_SDA_MOSI_DATA ]
- J27.1 - SDOUT [ PIO0_30/FC4_RXD_SDA_MOSI_DATA ]
These signals are going to be connected to the Jetson AGX Orin 40-pins header.
Connect TX, RX and GND on the J16 header to (for example) an FTDI receiver to have access to the UART.
Two USB cables are going to be connected to J5 and J7 connectors.
From the 40-pins header we need access to:
- PIN6 - GND
- PIN12 - I2S_CLK
- PIN35 - I2S_FS
- PIN38 - I2S_SDIN
- PIN40 - I2S_SDOUT
For I2S we are going to wire the J27 and J28 headers on the EVK to the 40-pin header on the Jetson Orin, as follows:
- J28.7 -> GND
- J28.6 -> I2S_CLK
- J28.5 -> I2S_FS
- J28.4 -> I2S_SDOUT
- J27.1 -> I2S_SDIN
Using a UART-USB cable, connect the J16 header to a USB port on your PC
Connect J5 and J7 to the PC used for programming the board and acting as USB host.
For the complete documentation please refer to the vscode-for-mcux wiki.
Step-by-step procedure:
-
Download Visual Studio Code for your host / architecture.
-
From the extensions marketplace download the
MCUXpresso for VS Code
extension:

- From the
QUICKSTART PANEL
selectOpen MCUXpresso Installer
:

- From the installer window select everything but the
Zephyr Developer
entry and start the installation:

- In the
INSTALLED REPOSITORIES
window, click onImport Repository
, fill the entries as needed and click theImport
button:

-
Clone the
tdm2usb
repo somewhere accessible. -
In the
PROJECTS
window, click onImport Project
, then select theFolder
containing the project, fill the remaining entries as suggested by the extension and click onImport
:

- To compile the project, right-click on the project name in the
PROJECTS
window and selectPristine Build/Rebuild Selected
:

- To flash the code on the EVK, connect the board and click on the
Debug
button besides the project name in thePROJECTS
window:

Important
There is currently a bug in the extension for which you usually have to flash / debug TWICE (Debug
-> Stop
-> Debug
-> Run
) to be able to correctly run the code.
Refer to your UART-USB converter documentation about how to access the serial console provided by the EVK (this is usually done using minicom
or equivalent).
UART setting is 115200 8N1 with no flow control.
On the Jetson AGX Orin, the I2S controller is configured using the amixer
command as follows:
amixer -c APE cset name="I2S2 Mux" ADMAIF2
amixer -c APE cset name="ADMAIF2 Mux" I2S2
amixer -c APE cset name="I2S2 codec master mode" cbs-cfs
amixer -c APE cset name="I2S2 codec frame mode" dsp-a
amixer -c APE cset name="I2S2 Capture Audio Bit Format" 32
amixer -c APE cset name="I2S2 Playback Audio Bit Format" 32
amixer -c APE cset name="I2S2 Client Bit Format" 32
amixer -c APE cset name="I2S2 Client Channels" 16
amixer -c APE cset name="I2S2 Capture Audio Channels" 16
amixer -c APE cset name="I2S2 Playback Audio Channels" 16
amixer -c APE cset name="I2S2 FSYNC Width" 0
amixer -c APE cset name="I2S2 Sample Rate" 48000
amixer -c APE cset name="I2S2 Loopback" off
amixer -c APE cset name="I2S2 Capture Data Offset" 2
To test both the communication streams (IN and OUT) we use arecord
to record the data stream, and speaker-test
to generate the audio stream, both running on the Jetson ORIN and/or the host PC.
We are testing the following configuration:
<- EP 2 IN (data) [SOURCE]
+--------------+
USB | | I2S
PC <-------+ IN <-------+ Jetson AGX Orin
| | RX
+--------------+
RT685 EVK
with the PC recording over USB the data generated by the Jetson and sent over I2S. In this case we only have on single EP IN that is using implicit feedback to modulate the stream rate.
This configuration can be tested by doing:
[PC] arecord -D hw:TDM2USB,0 -c 16 pc_record.wav -r 48000 -f S32_LE -d 60 -t wav
[Jetson] speaker-test -c 16 -f 1000 -F S32_LE -D hw:APE,1 -t sine
We are doing a 60s WAV recording on the PC and gathering the 1kHz sine wave per channel generated on the Jetson. The data generated and recorded is: 48kHz / 16 channels / 32 bits per channel.
We are testing the following configuration:
<- EP 1 IN (feedback)
-> EP 1 OUT (data) [SINK]
+--------------+
USB | | I2S
PC +-------> OUT +-------> Jetson AGX Orin
| | TX
+--------------+
RT685 EVK
with the Jetson recording over I2S the data generated by the PC and sent over USB. In this case we have an explicit feedback IN endpoint that is modulating the stream rate.
This configuration can be tested by doing:
[Jetson] arecord -D hw:APE,1 -c 16 jetson_record.wav -r 48000 -f S32_LE -d 60 -t wav
[PC] speaker-test -c 16 -f 1000 -F S32_LE -D hw:TDM2USB,0 -t sine
The PC is generating the 1kHz sine wave per channel data sent through USB to the Jetson that is gathering data recording from the I2S interface. The data generated and recorded is: 48kHz / 16 channels / 32 bits per channel.
There are two easy ways to test both the streams at the same time:
- we do what was described in the previous sections at the same time on the PC and on the Jetson
- we use
alsaloop
to create a loop
alsaloop
is (unsurprisingly) creating a loop using ALSA, so we can verify that we can send and receive data at the same time.
If we want to have the loopback on the USB (PC) side so that we can send and record from the I2S (Jetson) side, we can do that by doing in sequence:
[Jetson] speaker-test -c 16 -f 1000 -F S32_LE -D hw:APE,1 -t sine
[PC] alsaloop -P hw:TDM2USB,0 -C hw:TDM2USB,0 -c 16 -f S32_LE -r 48000 -v
[Jetson] arecord -D hw:APE,1 -c 16 jetson_recorded.wav -r 48000 -f S32_LE -d 10 -t wav
In this case we are instructing the PC to send over the playback USB interface, whatever we receive from the capture USB interface. We then send data through I2S on the Jetson side, and we record a 10 seconds wave file from the Jetson itself with whatever we receive from the same interface.
The same can be done by looping the I2S side instead of the USB side:
[PC] speaker-test -c 16 -f 1000 -F S32_LE -D hw:TDM2USB,0 -t sine
[Jetson] alsaloop -P hw:APE,1 -C hw:APE,1 -c 16 -f S32_LE -r 48000 -v
[PC] arecord -D hw:TDM2USB,0 -c 16 pc_recorded.wav -r 48000 -f S32_LE -d 10 -t wav
The scenario is the opposite of what we previously described, by looping this time the I2S playback / capture interface and streaming data and recording on the USB side.