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 Codeextension:
- From the
QUICKSTART PANELselectOpen MCUXpresso Installer:
- From the installer window select everything but the
Zephyr Developerentry and start the installation:
- In the
INSTALLED REPOSITORIESwindow, click onImport Repository, fill the entries as needed and click theImportbutton:
-
Clone the
tdm2usbrepo somewhere accessible. -
In the
PROJECTSwindow, click onImport Project, then select theFoldercontaining 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
PROJECTSwindow and selectPristine Build/Rebuild Selected:
- To flash the code on the EVK, connect the board and click on the
Debugbutton besides the project name in thePROJECTSwindow:
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" 2To 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 sineWe 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
alsaloopto 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.