Hello is there a way to implement the slave side of TDM stream? Any hint will be appreciated I need this because I am hooking up to XMOS XK-MCU-MC-AB eval boards via wire and doing some experimentation with TDMA, I followed this https://github.com/xmos/fwk_io/ - but it seems to be old/useless cause I can't even build it with cmake - the version doesn't even use interface and message passing between tasks.
Thanks
TDM SLAVE
-
Verified
- XCore Legend
- Posts: 1153
- Joined: Thu May 27, 2010 10:08 am
Hi, yes this should be possible. We have a couple of TDM slave implementations but they are a bit disparate at the moment. We have:
fwk_io TDM slave 16 slots which you have found. This is tested at 16 slots but should be OK for fewer. There is an example of using this in a 16ch PDM mic to TDM slave which could be stripped down https://github.com/xmos/sln_voice/tree/ ... aggregator and docs https://github.com/xmos/sln_voice/blob/ ... egator.rst.
It uses callbacks to you app to tell you when data is needed/available.
We also have a TDM slave in lib_xua which is our core USB Audio library. The task "audio hub" can implement an 8 slot TDM slave. You can see an example of this used in USB Audio https://github.com/xmos/sw_usb_audio/bl ... d.cmake#L8.
What is your overall goal? If you just want the TDM slave and your own app/logic then you can still use the USB Audio version (if it meets your needs) but you need to emulate the channel protocol that audio hub uses on your app side. We have code for this somewhere - let me know if you would like a copy and I'll dig it out.
We don't have any 'interface' enabled TDM slave code however. Both use channels.
Finally, you may have noticed there are various build systems. We are unifying this to one common one called "XCOMMON CMAKE" which USB Audio now uses. Some of the other libs like sln_voice and fwk_voice use a slightly different version - basically CMake with some includes. They should all work but in time everything will use XCOMMON CMAKE. There should instructions how to build these things and they should all work. If not - just shout as we will need to fix it.
fwk_io TDM slave 16 slots which you have found. This is tested at 16 slots but should be OK for fewer. There is an example of using this in a 16ch PDM mic to TDM slave which could be stripped down https://github.com/xmos/sln_voice/tree/ ... aggregator and docs https://github.com/xmos/sln_voice/blob/ ... egator.rst.
It uses callbacks to you app to tell you when data is needed/available.
We also have a TDM slave in lib_xua which is our core USB Audio library. The task "audio hub" can implement an 8 slot TDM slave. You can see an example of this used in USB Audio https://github.com/xmos/sw_usb_audio/bl ... d.cmake#L8.
What is your overall goal? If you just want the TDM slave and your own app/logic then you can still use the USB Audio version (if it meets your needs) but you need to emulate the channel protocol that audio hub uses on your app side. We have code for this somewhere - let me know if you would like a copy and I'll dig it out.
We don't have any 'interface' enabled TDM slave code however. Both use channels.
Finally, you may have noticed there are various build systems. We are unifying this to one common one called "XCOMMON CMAKE" which USB Audio now uses. Some of the other libs like sln_voice and fwk_voice use a slightly different version - basically CMake with some includes. They should all work but in time everything will use XCOMMON CMAKE. There should instructions how to build these things and they should all work. If not - just shout as we will need to fix it.
Engineer at XMOS
-
- Member++
- Posts: 17
- Joined: Fri Nov 15, 2024 2:40 am
Hi infiniteimprobability , Sorry I have not seen your reply earlier. I got the fwk_io to build with however I was expecting a TDM slave appication that I could just dump on the target rather than running some python tests, which doesnt work for me
./test_tdm_slave_tx16_cb.py
D:\xmos\projects\fwk_io\test\lib_i2s>python test_tdm_slave_tx16_cb.py
Traceback (most recent call last):
File "D:\xmos\projects\fwk_io\test\lib_i2s\test_tdm_slave_tx16_cb.py", line 3, in <module>
from tdm_slave_checker import TDMSlaveTX16Checker
File "D:\xmos\projects\fwk_io\test\lib_i2s\tdm_slave_checker.py", line 3, in <module>
import Pyxsim
ModuleNotFoundError: No module named 'Pyxsim'
I found some Pyxsim python module but the spelling seems to be off (small p vs capital p). And I did not get anywhere with that endeavor.
I have a simple goal:
1. Connect two XK-AUDIO-316-MC-AB boards via wire (clocks, data) and set the jumpers to use TDM path only (i.e. X_ADC_D0). Designate one board as master and another as slave. Then use TDM master to send a sample audio clip from the master board to the slave. On the slave board run TDM slave application and allow it to receive the bitstream. I want to verify that the data received is 100% valid bit for bit.
Hope there is a straight forward way to accomplish this.
Thanks
./test_tdm_slave_tx16_cb.py
D:\xmos\projects\fwk_io\test\lib_i2s>python test_tdm_slave_tx16_cb.py
Traceback (most recent call last):
File "D:\xmos\projects\fwk_io\test\lib_i2s\test_tdm_slave_tx16_cb.py", line 3, in <module>
from tdm_slave_checker import TDMSlaveTX16Checker
File "D:\xmos\projects\fwk_io\test\lib_i2s\tdm_slave_checker.py", line 3, in <module>
import Pyxsim
ModuleNotFoundError: No module named 'Pyxsim'
I found some Pyxsim python module but the spelling seems to be off (small p vs capital p). And I did not get anywhere with that endeavor.
I have a simple goal:
1. Connect two XK-AUDIO-316-MC-AB boards via wire (clocks, data) and set the jumpers to use TDM path only (i.e. X_ADC_D0). Designate one board as master and another as slave. Then use TDM master to send a sample audio clip from the master board to the slave. On the slave board run TDM slave application and allow it to receive the bitstream. I want to verify that the data received is 100% valid bit for bit.
Hope there is a straight forward way to accomplish this.
Thanks
-
Verified
- XCore Legend
- Posts: 1153
- Joined: Thu May 27, 2010 10:08 am
Hi, you don't need to worry about the Python stuff unless you are keen to replicate the tests (which you are welcome to do if you wish - you'll need to setup a pyenv with the module deps in requirements.txt in the repo root).
However it sounds like you are more interested in connecting two boards and applying the code. You will need two applications. Is the master a USB Audio device too? You will need some method of getting audio into it and out of it and USB Audio will give you a bit perfect way of doing that.
To get things setup quickly I'd use 2 USB Audio builds (assuming 8 channels per data line is acceptable, which USB Audio is currently fixed at).
If so, the master should be a build of "2SMi10o10xxxxxx_tdm8" from USB Audio. This will just a standard build of the reference design. You could increase the number of channels from 10 to 16 to fully populate slots on 2 data lines. You will need to reduce the max sample rate to 96kHz because USB Audio won't handle 192k at 16 channels. Because it's fixed at 8 channels per data line, you'd need 2 data lines (or reduce channels to 8 for a single data line if that meets your needs)
The slave could be a build of the same config but with "-DCODEC_MASTER=1" so that the xcore becomes slave. HOWEVER You will need to keep the CODECs on the board in reset though (or configure them as slave) because by default this define will cause one of the CODEC chips to become the master and this will contend with the master on the other board.
You'll need to connect MCLK, BCLK, WCLK (LRCLK) and the data line (and ground of course - be careful about ground loops with USB etc. too) and it should all work. MCLK is needed because the slave side USB Audio will need to keep track of it for asynch feedback the host. You wouldn't need MCLK if it wasn't USB Audio. You may want to watch signal integrity on this line as it will be 45.8752MHz by default, unless you change as follows (which should work if you limit sample rate to 96kHz)::
-DMCLK_48=512*48000
-DMCLK_441=512*44100
If you want a custom app without USB Audio then you'll need to consider the links I sent in the first post I made in this thread. As I mentioned before, the TDM IP is not in one consistent place at this time but it does exist.
All of this is certainly feasible and the chip tools can do it, but there will be some work involved in developing the app especially if you move away from USB Audio.
However it sounds like you are more interested in connecting two boards and applying the code. You will need two applications. Is the master a USB Audio device too? You will need some method of getting audio into it and out of it and USB Audio will give you a bit perfect way of doing that.
To get things setup quickly I'd use 2 USB Audio builds (assuming 8 channels per data line is acceptable, which USB Audio is currently fixed at).
If so, the master should be a build of "2SMi10o10xxxxxx_tdm8" from USB Audio. This will just a standard build of the reference design. You could increase the number of channels from 10 to 16 to fully populate slots on 2 data lines. You will need to reduce the max sample rate to 96kHz because USB Audio won't handle 192k at 16 channels. Because it's fixed at 8 channels per data line, you'd need 2 data lines (or reduce channels to 8 for a single data line if that meets your needs)
The slave could be a build of the same config but with "-DCODEC_MASTER=1" so that the xcore becomes slave. HOWEVER You will need to keep the CODECs on the board in reset though (or configure them as slave) because by default this define will cause one of the CODEC chips to become the master and this will contend with the master on the other board.
You'll need to connect MCLK, BCLK, WCLK (LRCLK) and the data line (and ground of course - be careful about ground loops with USB etc. too) and it should all work. MCLK is needed because the slave side USB Audio will need to keep track of it for asynch feedback the host. You wouldn't need MCLK if it wasn't USB Audio. You may want to watch signal integrity on this line as it will be 45.8752MHz by default, unless you change as follows (which should work if you limit sample rate to 96kHz)::
-DMCLK_48=512*48000
-DMCLK_441=512*44100
If you want a custom app without USB Audio then you'll need to consider the links I sent in the first post I made in this thread. As I mentioned before, the TDM IP is not in one consistent place at this time but it does exist.
All of this is certainly feasible and the chip tools can do it, but there will be some work involved in developing the app especially if you move away from USB Audio.
Engineer at XMOS
-
- Member++
- Posts: 17
- Joined: Fri Nov 15, 2024 2:40 am
Hi Infiniteimprobability, Thanks so much for the info. Yes the master could be the USB device to my host PC. Your suggested method seems to be the most straight forward way of accomplishing what I want to do however just slightly confused whether TDM loopback app on the slave is needed and whether or not I should cross-connect DAC D0 from master to ADC D0 of the slave ?
Also how should I configure both boards to use TDM as the data source using jumpers J6.J9.J11.J13 for ADC and J3,J8, J10, J12 for DAC? I am planning on keeping it simple first and only use one input/output.
If I understand the data-path, it is:
Master USB audio data form host ---> Xcore.ai X_DAC_0(bypass codec) -----TDM DATA ----> Slave Xcore.ai X_ADC_0--->loopback to X_DAC_0--->CODEC ---> Analog out to speaker
The inter-connection of my XK-316-MC-AB boards

To keep the DAC/ADC in reset for the slave, I added the following code at the bottom of the function xk_audio_316_mc_ab_AudioHwInit (since I don't know what code I would comment to have them not initialized).
//Ratin - keep DAC/ADC in reset
/* Reset DAC & ADC registers. Just in case we've run another build config */
WriteAllDacRegs(i2c, PCM5122_PAGE, 0x00); // Set Page 0.
WriteAllDacRegs(i2c, PCM5122_STANDBY_PWDN, 0x10); // Request standby mode
delay_milliseconds(1);
WriteAllDacRegs(i2c, PCM5122_RESET, 0x11); // Reset dac modules and registers to defaults. but this sets standby to 0 so chip starts up ... need to put back in standby.
WriteAllDacRegs(i2c, PCM5122_STANDBY_PWDN, 0x10); // Request standby mode
WriteAllAdcRegs(i2c, PCM1865_RESET, 0xFE);
With this code built with the defines that you mentioned running on the slave (app_usb_aud_xk_316_mc_2SMi8o8xxxxxx.xe) and the unmodified version of it running on the master, I am not hearing any audio so far thru the slave's speaker. I am sure I'm doing something wrong..
Thanks
Ratin
Also how should I configure both boards to use TDM as the data source using jumpers J6.J9.J11.J13 for ADC and J3,J8, J10, J12 for DAC? I am planning on keeping it simple first and only use one input/output.
If I understand the data-path, it is:
Master USB audio data form host ---> Xcore.ai X_DAC_0(bypass codec) -----TDM DATA ----> Slave Xcore.ai X_ADC_0--->loopback to X_DAC_0--->CODEC ---> Analog out to speaker
The inter-connection of my XK-316-MC-AB boards

To keep the DAC/ADC in reset for the slave, I added the following code at the bottom of the function xk_audio_316_mc_ab_AudioHwInit (since I don't know what code I would comment to have them not initialized).
//Ratin - keep DAC/ADC in reset
/* Reset DAC & ADC registers. Just in case we've run another build config */
WriteAllDacRegs(i2c, PCM5122_PAGE, 0x00); // Set Page 0.
WriteAllDacRegs(i2c, PCM5122_STANDBY_PWDN, 0x10); // Request standby mode
delay_milliseconds(1);
WriteAllDacRegs(i2c, PCM5122_RESET, 0x11); // Reset dac modules and registers to defaults. but this sets standby to 0 so chip starts up ... need to put back in standby.
WriteAllDacRegs(i2c, PCM5122_STANDBY_PWDN, 0x10); // Request standby mode
WriteAllAdcRegs(i2c, PCM1865_RESET, 0xFE);
With this code built with the defines that you mentioned running on the slave (app_usb_aud_xk_316_mc_2SMi8o8xxxxxx.xe) and the unmodified version of it running on the master, I am not hearing any audio so far thru the slave's speaker. I am sure I'm doing something wrong..
Thanks
Ratin
You do not have the required permissions to view the files attached to this post.