USB to TDM

Discussions about USB Audio on XMOS devices
sonaben
Junior Member
Posts: 7
Joined: Fri Nov 10, 2023 11:21 am

USB to TDM

Post by sonaben »

Hi everyone,

I'm a newbie with Xmos looking for some advice as I dug my head in the libraries and got a bit confused!

I'm using the latest Xcore multichannel evaluation board. I want to set up a usb audio interface for 8 channels and output it to a TDM single data line (so 8 samples per frame).
I've got the usb_sw_audio app working for usb 8 channels outputting to the 4 dacs, and I thought I could easily modify the configuration to output to TDM (with XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM and I2S_CHANS_DAC=8).

However to my understanding the USB audio app only handles stereo TDM, and the main loop in xua_audiohub.xc (lib xua): AudioHub_MainLoop loops over the number of DACs (4 for this board) and outputs the samples to each DAC, left then right, e.g for left:

Code: Select all

/* Output "even" channel to DAC (i.e. left) */
for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME)
                {
                    if(XUA_I2S_N_BITS == 32)
                        p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]);
                    else
                        partout(p_i2s_dac[index++], XUA_I2S_N_BITS, bitrev(samplesOut[frameCount +i]));
                }
So this is not what I need to output to a TDM dac with BCLK, FSYNC and DOUT.

Now I've spotted the TDM example: app_simple_tdm_master and wonder what's the best way to connect it.
What implementation would you recommend?

Should I instantiate a tdm_master task, and update AudioHub_MainLoop to send to it via tdm_send instead of the code quoted above?
And how would I deal with generating the FSYNC signal?

Also I couldn't find the source code for src_us3_voice_get_next_sample which is used I guess to sample the USB audio, is that right?:

Code: Select all

samplesOut[frameCount+i] = src_us3_voice_get_next_sample(i2sOutUs3.delayLine[i], src_ff3v_fir_coefs[2-audioToUsbRatioCounter]);
Pardon my ignorance, and thanks for your help!

Ben
User avatar
fabriceo
XCore Addict
Posts: 222
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi

the standard TDM implementation is supporting 8 output, this is mentioned in chapter 5.6 of the lib_xua pdf file.
I think you have to set I2S_CHANS_DAC=2 in this case.
no need for extra tasks.

regarding src_us3_voice_get_next_sample, you can find the source code in lib_src on xmos GitHub.
may be this configuration has not been tested and requires some modification in the makefile or importing lib_src.

good luck for your integration, let us know
sonaben
Junior Member
Posts: 7
Joined: Fri Nov 10, 2023 11:21 am

Post by sonaben »

Thanks Fabriceo,

I'm still not quite sure how the TDM signals (FSYNC and BCLK) are handled, but I'm going to have a look at your suggestions over the weekend and let you know, cheers.
User avatar
fabriceo
XCore Addict
Posts: 222
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi
I m sorry, I ve made a mistake.

looking in details in the file lib_xua/api/xua_conf_default.h
what is important is the value of DAC channels per frame and by default it is set to 8 when in TDM mode (line 117) unless you define I2S_CHANS_PER_FRAME in your conf file.
Also depending on your DAC you set the number of channels in I2S_CHANS_DAC
and the number of I2S wires is computed automatically line 133 by the ratio of these value.
sonaben
Junior Member
Posts: 7
Joined: Fri Nov 10, 2023 11:21 am

Post by sonaben »

Hi Fabriceo,

I made some progress but I'm stuck with an issue to do with the i2s clock initialisation I believe.

I did some debugging and the Main Audio I/O loop (xua_audiohub.xc) gets stuck when calling InitPorts_master.

It seems to fail in audiohub_initport.xc with line:

Code: Select all

p_lrclk <: 0 @ tmp;
So I guess it may be an issue with the FSYNC clock...

My ports declaration in the xn file is:

Code: Select all

<Tile Number="0" Reference="tile[0]">
            <Port Location="XS1_PORT_8D"  Name="PORT_CTRL"/>

            <!-- I2C -->
            <Port Location="XS1_PORT_1N"  Name="PORT_I2C_SCL"/>
            <Port Location="XS1_PORT_1O"  Name="PORT_I2C_SDA"/>

            <!-- Clocking --> 
            <Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
            <Port Location="XS1_PORT_1A"  Name="PORT_MCLK_IN_USB"/>
          </Tile>
          <Tile Number="1" Reference="tile[1]">
            <!-- TDM -->
            <Port Location="XS1_PORT_1B"  Name="PORT_I2S_LRCLK"/><!-- FSYNC X1D01 --> 
            <Port Location="XS1_PORT_1C"  Name="PORT_I2S_DAC0"/>
            <Port Location="XS1_PORT_1D"  Name="PORT_I2S_BCLK"/><!-- X1D11 BCLK --> 
            <Port Location="XS1_PORT_1K"  Name="PORT_MCLK_IN"/>
          </Tile>
The XS1_PORT_1B port is connected correctly on my pcb to X1D01.

Not so sure about PORT_MCLK_IN_USB if I should need it, and for my application the DAC only requires FSYNC, DATA and BCLK.

Thank you, and apologies again for my lack of experience!
User avatar
fabriceo
XCore Addict
Posts: 222
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi
I have not used the TDM myself so will not help much, but, from what you describe, writing to p_lrclk is "blocking" which means that the serialization register and fifo register are full, most likely because the clockblock used for this port is either not started or not fed with any bit clock signal.

the Multichannel board is always providing the master clock, and in master mode, the bclk and lrclk (fsync) signal are provided by the xmos.

the port PORT_MCLK_IN_USB is used on the Multichannel board as a copy of the audio master clock, so that both Tile 0 get visibility of the mclk used by the audio tile 1. you need it in the .xn file and a wire exist on the PCB. this is used to compare the audio clock with the usb sof frame (8khz) to inform the host of the packet speed.

hope this helps
sonaben
Junior Member
Posts: 7
Joined: Fri Nov 10, 2023 11:21 am

Post by sonaben »

Hi Fabriceo,

I'm porting the eval board on my own PCB with the XU316-1024-QF60B-xcore_ai chip.

I don't think I've got it right with the clocks set up indeed, probably getting confused with all the settings and I don't know enough about clocking...

I haven't got a CS2100 or SI5351A-B-GT connected so I was thinking of using the "xcore.ai secondary (application) PLL" for now.
But then I believe I can only use USB in synchronous mode, and the default mode is asynchronous, is that right?

Would you know what I need to do in order to configure this?

And then it's just a question of connecting PORT_MCLK_IN_USB and PORT_MCLK_IN together?

Thanks again for helping a beginner :)
User avatar
fabriceo
XCore Addict
Posts: 222
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi
if you design your own board then yes you can use the "application PLL" to generate your Master clock for your DAC and/or ADC.
You will have all audio signals on tile 1 including mclk from PLL on x1d11 which will correspond to port called PORT_MCLK_IN (but it is an output here) and you have to create a physical connection on tile0 , for example on x0d11, and name this PORT_MCLK_IN_USB.

I have not used yet the PLL but you can for sure configure the application in a mode where it generates the master clock and no worry your application stay full asynchronous vs the USB host (which alway sends packets at 8khz with its own clock reference).

you certainly find more info on using the device PLL in the swusbaudio user guide 7.3.1 pdf or in the lib_xua.pdf files.

feel free to share your findings on how to best implement or use this pll
sonaben
Junior Member
Posts: 7
Joined: Fri Nov 10, 2023 11:21 am

Post by sonaben »

Great I'll give it a try and share my findings, thanks again!
User avatar
Ross
Verified
XCore Legend
Posts: 1070
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

ignore references to src_us3_voice_get_next_sample

These were added to provide sample rate conversion from microphones to the usb device sample rate. You won't need this for your TDM application.
Technical Director @ XMOS. Opinions expressed are my own