TDM slave to USB async

Discussions about USB Audio on XMOS devices
andreaalbano
Member
Posts: 10
Joined: Tue May 31, 2016 3:00 pm

TDM slave to USB async

Post by andreaalbano »

Hello,
we are trying to setup a XK-AUDIO-316-MC evaluation board to act as a TDM to USB converter.

The configuration it’s a little odd:
  • 16 channel on TDM to USB path (2xTDM8)
  • 4 channel on USB to TDM path (1xTDM8 where just the first 4 channel are used).
To perform this we are using app_usb_aud_xk_evk_xu316 with the following defines.

Code: Select all

                                               
                                                -DCODEC_MASTER=1 \
                                                -DXUA_SYNCMODE=XUA_SYNCMODE_ASYNC \
                                                -DXUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
                                                -DMAX_FREQ=48000 \
                                                -DMIN_FREQ=48000 \
                                                -DI2S_CHANS_ADC=16 \
                                                -DI2S_CHANS_DAC=8 \
                                                -DNUM_USB_CHAN_IN=16 \
                                                -DNUM_USB_CHAN_OUT=4
The system works fine except for one detail: the stream clock used for the USB transactions is not the TDM clock.

We use XUA_SYNCMODE=XUA_SYNCMODE_ASYNC define so we did expect the TDM peripheral clock to be the provider of the media clock.

Looking at the code it seems like that, when using ADAT or SPDIF examples with ASYNC mode, the USB media clock is somehow synchronized with the ADAT/SPDIF RX sync clock.

For TDM slave, instead, this doesn't seem to possible, because the usecase is:
  • the XMOS provide the mclk to the codec
  • the codec that generate a TDM master to the XMOS.
  • In this situation, everything is still synchronized by design even if the TDM is slave.
  • In our case, where the TDM is generated by a third party device we have this mismatch.
User avatar
Ross
Verified
XCore Legend
Posts: 1071
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

The clock communicated to the host will be the master-clock, not the TDM word clock. The system is assuming the DAC/DAC is clocked from this same master-clock.

It sounds like you want the xcore to generate the master clock from the incoming TDM clock, which isn't something the code currently supports (not a common request), but it shouldn't be too hard to add (the S/PDIF handing will provide an excellent reference).
Technical Director @ XMOS. Opinions expressed are my own
andreaalbano
Member
Posts: 10
Joined: Tue May 31, 2016 3:00 pm

Post by andreaalbano »

Well,
actually all data flow on SPDIF or ADAT is managed in a completely different way than TDM, so it's very hard to add the option following those examples.

I've personally tried, but, due to lack of documentation of the code, it's almost impossible for someone who doesn't have a deep understanding of the code.
Just to make you understand, these are all the changes I've made before I had to give up:
Screenshot 2024-07-22 160708.png
I actually don't understand what's the purpose of the TDM slave example where the XMOS clock is used as master to the DAC/ADC: why not to use it in master mode, what's the difference?
A TDM slave example should assume a clock not synchronous with the master, in my opinion.
You do not have the required permissions to view the files attached to this post.
User avatar
Ross
Verified
XCore Legend
Posts: 1071
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

Thanks for your feedback.

As you say, your configuration is somewhat "odd" and it's not something that's come up too much (or ever in my memory) in the past despite the millions of units sold.

Typically we find an MCLK is available for use.

Another issue is the TDM/I2S task is central to the whole design, it cannot support external changes to sample-rate that it doest know about - the host is master in that regard.

We'll bear your suggestion in mind for future releases.
Technical Director @ XMOS. Opinions expressed are my own
User avatar
fabriceo
XCore Addict
Posts: 222
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi, if you allow me a feedback, in the current usb audio stack, the mclk signal has to go on both tile : the one in charge of I2S and the one in charge of USB. on the USB side, it is use only to compute the so called feedback endpoint in format 16:16 and this is done in the SOF interrupt at say 8khz for EAC2. Also the 2 tiles are fully synchronized via the channel interrupt handler in the decouple task.
For a commercial product I wanted to disconnect the 2 clocks domain and this is possible : I m passing the I2S frequency (lrclk based) to the decouple Task in the data exchange process, and decouple compared this value to the USB host frequency. If they are different a global variable is set, and then I choose to force the feedback endpoint to a fixed value equal to the one expected by the host instead of computing it in the SOF. Then an indicator on the product front-panel informs the user of the different sampling rate.
With the same global flag I manage to interact with the USB-fifo in order to avoid issue related to overrun/underun.
Overall this works well and the standard framework could be adjusted to include some global flags like this. Also by passing some lrclk timestamp to the decouple task, the SOF interrupt could be reworked to recompute the feedback endpoint without need Mclk.
for thoughts and fun.