UAC 2 USB to i2s bridge with DSD and i2c DAC configuration

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
BritishCat
Member++
Posts: 20
Joined: Tue Oct 24, 2023 11:16 am

UAC 2 USB to i2s bridge with DSD and i2c DAC configuration

Post by BritishCat »

Hello, I would like to develop a sound card based on an XMOS processor to create a UAC 2 compliant USB input with an asynchronous interface. In this system, the processor should operate in Slave mode on the I2S bus. It will detect the input sampling frequency and select the corresponding MasterClock using a high or low logic level on a GPIO pin. In the future, I would like to enhance the firmware by teaching the processor to handle DSD and configure the DAC in detail via the I2C bus. Additionally, I aim to gain a more comprehensive understanding of libraries and improve my programming skills in your environment.
Can you advise me on where to start? I would like to begin by building a simple application from scratch (without using reference applications) and gradually make it more complex using the audio libraries xua and xud. Thank you.


User avatar
Ross
XCore Expert
Posts: 968
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

My advice would be to start with the usb audio reference design and modify that, you will have to add the sample rate detection and notify the host. USB is host centric - generally it expects to be in charge of the bus.
User avatar
BritishCat
Member++
Posts: 20
Joined: Tue Oct 24, 2023 11:16 am

Post by BritishCat »

While studying the documentation of reference applications and the lib_xua library, I unfortunately couldn't find a method or function for determining the current sampling frequency or a code template that could be useful for switching the frequency grid when changing or starting the device. Can you please guide me to where I can find this information?
User avatar
Ross
XCore Expert
Posts: 968
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

The function AudioHwConfig() will be called when the host sets the sample rate - sample rate is a parameter of this function.

You cannot simply change the SR without informing the host - you will need modify the code for the interrupt/status endpoint to inform the host of a clock change. There has been some similar threads in this forum fairly recently. The code currently only does this for changes to an external digital stream i.e. S/PDIF & ADAT
User avatar
BritishCat
Member++
Posts: 20
Joined: Tue Oct 24, 2023 11:16 am

Post by BritishCat »

I'm sorry for my bad English, it's not my primary language. Did I understand correctly that the current SR can be obtained as the first argument of the AudioHwConfig() function, 'samFreq'? I understand how to build the logic for switching between grids that are multiples of 44.1/48, thanks a lot. Unfortunately I didn’t understand about the host notification. So, during switching the sampling frequency, do I need to call some function to notify the host about the status of the MasterClock switch, to put the host into a waiting mode? Did I understand everything correctly? Unfortunately, using a search engine, I could not find a similar topic on the forum. Thanks a lot for your help
Last edited by BritishCat on Tue Oct 24, 2023 9:17 pm, edited 1 time in total.
User avatar
fabriceo
XCore Addict
Posts: 186
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hello BritishCat
let me step in. If you just have a DAC to drive and if your problem is only to select an external crystal (say 22/24 or 45/49) and you want the Xmos to act as a I2S master but slave on the master clock, then you just have to modify AudioHwConfig() to accommodate you DAC configuration (using i2c) and to control the switch for the crystal (using a port gpio). That's quite easy and the USB Audio software is designed for such a customization.

if on the other end you want an external action (user, buttons...) to change the crystal or the sample rate, THEN you have to inform the host and the host will send all the usb-requests to adjust to this and you ll receive the changes confirmation in the AudioHwConfig().
As said Ross this involves usb-interrupt-enpoint and you can find information in the code related to spdif/adat.
but this topic becomes quite complex to deal with and the usb-audio app is not build for simply configuring this, you will have to do many changes by your own. I would not recommend to start experimenting xmos USB Audio with such a challenge :)

hope this helps
User avatar
BritishCat
Member++
Posts: 20
Joined: Tue Oct 24, 2023 11:16 am

Post by BritishCat »

Yes, Fabriceo, you're right. I'd like to develop an XMOS vs. DAC combo, where XMOS works as the Master with an external MCK (it generates all clocks except the Master clock). So, the DAC will work as a Slave. Now, I'm going to build a simple application based on the lib_xua codless model or the AN00246_xua example. I just want to modify AudioHwConfig() and AudioHwInit() to add the option to switch the sample rate (44.1/48) and add a mute function. If I need to add just some simple logic it should be easy
User avatar
BritishCat
Member++
Posts: 20
Joined: Tue Oct 24, 2023 11:16 am

Post by BritishCat »

I have one more question. What happens to the processor when the input data format changes from 16 bits to 24 or 32 bits? What will be the output of the bus i2s? I have not seen anywhere in the descriptions about support and output of 24-bit format. Is it possible to limit the depth to 16 bits or 24, for example if the DAC does not support higher modes?
#ifndef XUA_I2S_N_BITS
#define XUA_I2S_N_BITS (32)
#endif

#if (XUA_I2S_N_BITS != 16) && (XUA_I2S_N_BITS != 32)
#error Unsupported value for XUA_I2S_N_BITS (only values 16/32 supported)
#endif

/**
 * @brief Max supported sample frequency for device (Hz). Default: 192000
 */
#ifndef MAX_FREQ
#define MAX_FREQ                 (192000)
#endif
This code from xua_conf_default.h I might have misunderstood, but it seems to me that there is no 24-bit output
User avatar
fabriceo
XCore Addict
Posts: 186
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi
the XMOS USB receiver is handling properly data transmitted in 16, 24 or 32 bits, as long as an interface is defined in the descriptor to support a specific bit depth.
the 24 bit is special in a sense that the predefined configuration is to consider it as a 4 bytes chunk, but still the extraction is done on 3 bytes. the relevant bits are always stored in the MSB and the LSBs are filled with 0. so you end up with 32bits words.

to configure the USB interfaces, see in devicedefines.h the section where you find defines containing "STREAM_FORMAT_OUTPUT".

now the USB received data will be transferred by the Decouple task to the I2S tasks as 32bits chunk in all cases.
Also the XMOS buffered port are configured in 32bits and your I2S stream should stay in 32bits. probably your DAC accept 32bits and I don't see reason to change this, as long as the 32bits contains the original 16/24/32 format.

hope this helps
User avatar
BritishCat
Member++
Posts: 20
Joined: Tue Oct 24, 2023 11:16 am

Post by BritishCat »

Thank you fabriceo for your help.I looked at the documentation of different DACs, really 20 and 24 bit DAC's have an input dataWord length 32bit. I didn't pay atantion about it.This is true for most modern 20,24,32 bit DAC's except old and rare ones, such as AD 1865. So I understood that I have nothing to change in these options.