TDM Master Xcore-200 using version 7.0.0

Discussions about USB Audio on XMOS devices
User avatar
Ross
Verified
XCore Legend
Posts: 1117
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

Im not aware of any issue or good reason to balance them over multiple tiles in a single device. I guess it would be nice to balance processing evenly for future development maybe?
Technical Director @ XMOS. Opinions expressed are my own
xmos_user123
Member++
Posts: 19
Joined: Tue Oct 01, 2024 1:43 am

Post by xmos_user123 »

Ross wrote: Thu Oct 10, 2024 10:59 am This will be more involved, you'll need to instantiate lib_i2s on the other tile - running as i2s slave.

You'll also need to wire up the clocks to this tile (LR and Bit)

These is an example app showing this done here:

https://github.com/xmos/sw_usb_audio/tr ... 6_extrai2s
Circling back to this, I noticed in extra_i2s.xc the example code has 2 extra inputs but no extra outputs. I was wondering how we can modify it to have some outputs instead? Specifically I want to output on 2 new ports, but I don't see anywhere tat I can define the dout ports like you did here:

Code: Select all

 on tile[1]: in buffered port:32 p_i2s_din[1] = {XS1_PORT_1M}; // X1D36
on tile[1]: in port p_i2s_bclk = XS1_PORT_1O;                 // X1D38
on tile[1]: in buffered port:32 p_i2s_lrclk = XS1_PORT_1P;    // X1D39
(also FYI the 700MHz solved our LRCLK frequency issue. We are now able to output 40 DAC channels across 5 ports on tile 0)
User avatar
Ross
Verified
XCore Legend
Posts: 1117
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

xmos_user123 wrote: Fri Oct 25, 2024 1:26 am Circling back to this, I noticed in extra_i2s.xc the example code has 2 extra inputs but no extra outputs. I was wondering how we can modify it to have some outputs instead? Specifically I want to output on 2 new ports, but I don't see anywhere tat I can define the dout ports like you did here:

Code: Select all

on tile[1]: in buffered port:32 p_i2s_din[1] = {XS1_PORT_1M}; // X1D36
on tile[1]: in port p_i2s_bclk = XS1_PORT_1O;                 // X1D38
on tile[1]: in buffered port:32 p_i2s_lrclk = XS1_PORT_1P;    // X1D39
Just declare an in output port array e.g.

Code: Select all

on tile[1]: out buffered port:32 p_i2s_dout[1] = {XS1_PORT_1A, XS1_PORT_1B};
pass to i2s_frame_slave (instead of null and 0

Code: Select all

i2s_frame_slave(i_i2s, p_i2s_dout, 2, p_i2s_din, 1, DATA_BITS, p_i2s_bclk, p_i2s_lrclk, clk_bclk);
The data transfer looks to already be implemented by setting EXTRA_I2S_CHAN_COUNT_OUT to 2
xmos_user123 wrote: Fri Oct 25, 2024 1:26 am (also FYI the 700MHz solved our LRCLK frequency issue. We are now able to output 40 DAC channels across 5 ports on tile 0)
Nice!
Technical Director @ XMOS. Opinions expressed are my own
xmos_user123
Member++
Posts: 19
Joined: Tue Oct 01, 2024 1:43 am

Post by xmos_user123 »

Thanks for these code snippets, I've added them to extra_i2s.xc and placed it in the extensions folder of our project. When I try to compile I get a bunch of errors, do I need to link his file somehow for it to be recognized in the project

Code: Select all

../src/extensions/extra_i2s.xc:3:10: fatal error: 'i2s.h' file not found
#include "i2s.h"
         ^
../src/extensions/extra_i2s.xc:56:44: error: parse error before "i_i2s"
void i2s_data(server i2s_frame_callback_if i_i2s, chanend c)
                                           ^
../src/extensions/extra_i2s.xc:66:31: error: use of undeclared identifer `c'
            case inuint_byref(c, x):
                              ^
/Applications/XMOS_XTC_15.3.0/target/include/xs1.h:1035:70: note: expanded from macro 'inuint_byref'
#define inuint_byref(c, val)                 __builtin_in_uint_byref(c, val)
                                                                     ^
../src/extensions/extra_i2s.xc:83:18: error: use of undeclared identifer `i_i2s'
            case i_i2s.init(i2s_config_t &?i2s_config, tdm_config_t &?tdm_config):
                 ^
../src/extensions/extra_i2s.xc:83:29: error: use of undeclared identifer `i2s_config_t'
            case i_i2s.init(i2s_config_t &?i2s_config, tdm_config_t &?tdm_config):
                            ^
../src/extensions/extra_i2s.xc:83:42: error: parse error before '?' token
            case i_i2s.init(i2s_config_t &?i2s_config, tdm_config_t &?tdm_config):
                                         ^
../src/extensions/extra_i2s.xc:100:13: error: parse error before "case"
            case i_i2s.send(size_t num_out, int32_t samples[num_out]):
            ^
../src/extensions/extra_i2s.xc:102:35: error: use of undeclared identifer `i'
                for(size_t i = 0; i < EXTRA_I2S_CHAN_COUNT_OUT; i++)
                                  ^
../src/extensions/extra_i2s.xc:102:68: error: parse error before ')' token
                for(size_t i = 0; i < EXTRA_I2S_CHAN_COUNT_OUT; i++)
                                                                   ^
../src/extensions/extra_i2s.xc:104:21: error: use of undeclared identifer `samples'
                    samples[i] = samplesOut[i];
                    ^
../src/extensions/extra_i2s.xc:109:1: error: parse error before '}' token
}
^
../src/extensions/extra_i2s.xc:112:21: error: local variable `p_i2s_bclk' has type port
on tile[1]: in port p_i2s_bclk = XS1_PORT_1A;                
                    ^~~~~~~~~~
../src/extensions/extra_i2s.xc:113:33: error: local variable `p_i2s_lrclk' has type port
on tile[1]: in buffered port:32 p_i2s_lrclk = XS1_PORT_1B;    
                                ^~~~~~~~~~~
../src/extensions/extra_i2s.xc:114:34: error: local variable `p_i2s_dout' has type that contains a port
on tile[1]: out buffered port:32 p_i2s_dout[1] = {XS1_PORT_1E};
                                 ^~~~~~~~~~~~~
../src/extensions/extra_i2s.xc:116:19: error: local variable `clk_bclk' has type clock
on tile[1]: clock clk_bclk = XS1_CLKBLK_1;
                  ^~~~~~~~
../src/extensions/extra_i2s.xc:120:37: error: storage size of 'i_i2s' isn't known
    interface i2s_frame_callback_if i_i2s;
                                    ^~~~~
../src/extensions/extra_i2s.xc:124:47: error: use of undeclared identifer `p_i2s_din'
        i2s_frame_slave(i_i2s, p_i2s_dout, 1, p_i2s_din, 1, DATA_BITS, p_i2s_bclk, p_i2s_lrclk, clk_bclk);
                                              ^
../src/extensions/extra_i2s.xc:124:9: error: unknown function identifier `i2s_frame_slave' (possibly missing prototype?)
        i2s_frame_slave(i_i2s, p_i2s_dout, 1, p_i2s_din, 1, DATA_BITS, p_i2s_bclk, p_i2s_lrclk, clk_bclk);
        ^
../src/extensions/extra_i2s.xc:125:18: error: too many arguments to function `i2s_data'
        i2s_data(i_i2s, c);
                 ^~~~~
Also how can we modify the our original UseBufferManagement function to now fanout to both tiles?

Code: Select all

void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
{
	/*
	[0] -> [0]
	[1] -> [1]
	...
	[0] -> [24]
	[1] -> [25]
	...
	*/
	for(int i = 24; i > 7; i-=8)
    		for(int j = 7; j >= 0; j--)
    		{
        		sampsFromUsbToAudio[j+i] = sampsFromUsbToAudio[j];
    		}

}
User avatar
Ross
Verified
XCore Legend
Posts: 1117
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

You're missing the I2S library, lib_i2s.

Based on previous posts I *think* you're using an old software version that uses the, now legacy, xcommon build system, in which case clone https://github.com/xmos/lib_i2s and add lib_i2s to USED_MODULES in Makefile

If you're using the new cmake based system, xcommon-cmake, (recommended) simply add lib_i2s to APP_DEPENDENT_MODULES in cmakelists.txt

i.e.

Code: Select all

set(APP_DEPENDENT_MODULES "lib_i2s")


All the fetching will be handled automatically in the cmake step.
Technical Director @ XMOS. Opinions expressed are my own
xmos_user123
Member++
Posts: 19
Joined: Tue Oct 01, 2024 1:43 am

Post by xmos_user123 »

Thanks for the reply. Also just following up on this question... how can we modify our original UseBufferManagement function to now fanout to both tiles?

Code: Select all

void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
{
	/*
	[0] -> [0]
	[1] -> [1]
	...
	[0] -> [24]
	[1] -> [25]
	...
	*/
	for(int i = 24; i > 7; i-=8)
    		for(int j = 7; j >= 0; j--)
    		{
        		sampsFromUsbToAudio[j+i] = sampsFromUsbToAudio[j];
    		}

}
User avatar
Ross
Verified
XCore Legend
Posts: 1117
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

The app_usb_aud_xk_evk_xu316_extrai2s gives an example of this

It shows saving off a channel end as a global:

https://github.com/xmos/sw_usb_audio/bl ... main.h#L11

Running the extra task:

https://github.com/xmos/sw_usb_audio/bl ... main.h#L20

Send the audio data over the channel in AudioBufferManagement()

https://github.com/xmos/sw_usb_audio/bl ... i2s.xc#L35

Receive the data over channel and pass data to I2S (TDM in your case I guess)

https://github.com/xmos/sw_usb_audio/bl ... i2s.xc#L57
Technical Director @ XMOS. Opinions expressed are my own