The XMOS USB Audio solution provides USB Audio Class compliant devices over USB 2.0 (high-speed or full-speed). Based on the XMOS xcore-200 (XS2) and xcore.ai (XS3) architectures, it supports USB Audio Class 2.0 and USB Audio Class 1.0, asynchronous mode (synchronous as an option) and sample rates up to 384kHz.
The complete source code, together with the free XMOS XTC development tools and xcore multi-core micro-controller devices, allow the developer to select the exact mix of interfaces and processing required.
The XMOS USB Audio solution is deployed as a framework (see lib_xua) with reference design applications extending and customising this framework. These reference designs have particular qualified feature sets and an accompanying reference hardware platform.
This software user guide assumes the reader is familiar with the XC language and xcore devices. For more information see XMOS Programming Guide.
The reader should also familiarise themselves with the XMOS USB device library (lib_xud) and the XMOS USB audio library (lib_xua)
Note
The reader should always refer to the supplied CHANGELOG and README files for known issues relating to a specific release
Functionality |
|
Provides USB interface to audio I/O. |
|
Supported Standards |
|
USB |
USB 2.0 (Full-speed and High-speed) |
Audio |
I²S/TDM |
S/PDIF (receive may be limited to 96kHz depending on external hardware) |
|
ADAT |
|
Direct Stream Digital (DSD) |
|
PDM Microphones |
|
MIDI |
|
Supported sample frequencies |
|
16kHz to 384kHz [1] |
|
Supported devices |
|
XMOS Devices |
xcore-200 Series |
xcore.ai Series |
|
Requirements |
|
Development Tools |
XTC Development Tools (see readme for required version) |
USB |
xcore device with integrated USB phy |
Audio |
External audio DAC/ADC/CODECs (and required supporting componentry) supporting I²S/TDM |
Boot/Storage |
Compatible SPI/QSPI Flash device (or xcore device with internal flash) |
Licensing |
|
Reference code provided without charge under license from XMOS. |
Footnotes
This section describes the hardware development platforms supported by the XMOS USB Audio reference design software.
Board |
xcore device |
Analog channels |
Digital Rx/Tx & MIDI |
---|---|---|---|
XK_EVK_XU316 |
xcore.ai |
2 in + 2 out |
N/A |
XK_AUDIO_316_MC_AB |
xcore.ai |
8 in + 8 out |
Supported |
XK_AUDIO_216_MC_AB |
xcore-200 |
8 in + 8 out |
Supported |
Each of the platforms supported has a Board Support Package (BSP), the code for which can be be
found in lib_board_support.
The code in lib_board_support
abstracts away all of the hardware setup including enabling
external hardware blocks and DAC and ADC configuration and provides a translation
layer from the common API supported by lib_xua for
initialising and configuring hardware on a sample rate or stream format change.
Detailed feature sets for the each of the supported boards can be found in the documentation for lib_board_support.
The XMOS USB Audio Reference design includes support for USB Audio Class (UAC) versions 1.0 and 2.0. UAC 2.0 includes support for audio over high-speed USB (UAC 1.0 supports full-speed only) and other feature additions.
Support for USB Audio Class 1.0 has been included in macOS and Windows for a number of years. Most Linux distributions also include support.
Support for USB Audio Class 2.0 is only included in more modern versions of macOS and Windows:
Since version 10.6.4 macOS natively supports USB Audio Class 2.0
Since version 10, release 1809, Windows natively supports USB Audio Class 2.0
For some products it may be desirable to use a third-party driver for Windows. A number of reasons exist as to why this may be desirable:
In order to support UAC 2.0 on Windows versions earlier than 10
The built-in Windows support is typically designed for consumer audio devices, not for professional audio devices
The built in drivers support sound APIs such as WASAPI, DirectSound, MME, but not ASIO.
The XMOS USB Audio Reference design is tested against Thesycon USB Audio Driver for Windows. This includes the following feature-set/benefits:
Available for Windows 10 and Windows 11 operating systems
Designed for professional audio devices and consumer-style devices
Supports ASIO for transparent and low-latency audio streaming
Supports Windows sound APIs such as WASAPI, DirectSound, MME
Supports high-end audio features such as bit-perfect PCM up to 768 kHz sampling rate, native DSD format (through ASIO) up to DSD1024
Supports multiple clock sources such as S/PDIF, ADAT or WCLK inputs
Supports MIDI 1.0 class, including MIDI port sharing
Supports DFU (Device Firmware Upgrade) and comes with a GUI utility for firmware update
Provides a private API for driver control and direct device communication (SDK available)
Comes with a control panel application for driver status/control
Optionally supports virtual channels (channels available at ASIO and Windows APIs but not implemented in the device)
Optionally supports mixing and/or signal processing plugin in the kernel-mode driver
Fully supports driver signing, branding and customization including driver installer (Customization will be done by Thesycon)
Technical support and maintenance provided by Thesycon
Custom features available on request
Note
Many of the benefits listed above apply to both UAC1.0 and UAC2.0 and the Thesycon Driver supports both class versions.
Warning
XMOS development boards are typically supplied with no firmware pre-programmed.
The following steps explain how to programmed the latest firmware on the board and use it. Each step is explained in detail in the following sections.
Download the latest USB Audio 2.0 Device software release from the XMOS website USB & Multichannel Audio page, using the DOWNLOAD SOFTWARE link.
Before downloading the software, review the licence and click Accept to initiate the download.
(Section USB Audio 2.0 reference software.)
If using a Windows host computer, download the USB Audio Class 2.0 Evaluation Driver for Windows.
On the XMOS website USB & Multichannel Audio page, follow the DRIVER SUPPORT link, and click on Download. Once downloaded, run the executable and install the driver.
(Section USB Audio Class 2.0 evaluation driver for Windows.)
Download and install the the XMOS XTC Tools
The minimum required XTC Tools version for compiling USB Audio applications can be found in the README. Make sure to download the correct version of the tools.
(Section XMOS XTC development tools)
Compile the firmware relavant to the available reference hardware platform .
(Section: Building the firmware)
Connect the board to the development system using (using the supplied xTAG if required), and program the firmware onto the board.
(Section Running the firmware)
Connect audio input and output devices, and play audio.
(Section Playing audio)
The latest USB Audio 2.0 Reference Design software is available free of charge from XMOS.
When downloading the software for the first time, the user needs to register at http://www.xmos.com/.
To download the firmware:
On the XMOS website USB & Multichannel Audio page, follow the DOWNLOAD SOFTWARE link
Review the licence agreement and click Accept.
Download and save the software when prompted.
The software is distributed as a zip archive containing pre-compiled binaries and source code that can be built using the XMOS XTC Tools.
Alternatively, contact a local sales representative for further details:
Note
Since version 10.6.4, macOS natively supports USB Audio Class 2.0 – no driver install is required.
Note
Since version 10, release 1703, Windows natively supports USB Audio Class 2.0 – no driver install is required.
Earlier Window versions only provides support for USB Audio Class 1.0. To use a USB Audio Class 2.0 device under these Windows versions requires a third party driver.
Developers may also wish to use a third party driver for reasons including:
ASIO support
Advanced clocking options and controls
Improved latency
Native DSD (via ASIO)
Branding customisation and custom control panels
Large channel count devices
Etc
XMOS therefore provides a free Windows USB Audio driver for evaluation and prototyping and a path to a more feature-rich multichannel production driver from our partner Thesycon.
The evaluation driver is available from the XMOS website:
Further information about the evaluation and production drivers is available in the USB Audio Class 2.0 Windows Driver Overview document available on the website:
The XMOS XTC tools provide everything required to develop applications for xcore multicore microcontrollers and can be downloaded, free of charge, from XMOS XTC tools. Installation instructions can be found here. Be sure to pay attention to the section Installation of required third-party tools.
The XMOS XTC tools make it easy to define real-time tasks as a parallel system. They come with standards compliant C and C++ compilers, language libraries, simulator, symbolic debugger, and runtime instrumentation and trace libraries. Multicore support offers features for task based parallelism and communication, accurate timing and I/O, and safe memory management. All components work off the real-time multicore functionality, giving a fully integrated approach.
The XTC tools are required by anyone developing or deploying applications on an xcore processor. The tools include:
“Tile-level” toolchain (Compiler, assembler, etc)
System libraries
“Network-level” tools (Multi-tile mapper etc)
XSIM simulator
XGDB debugger
Deployment tools
The tools as delivered are to be used within a command line environment, though may also be integrated with VS Code graphical code editor.
Warning
USB Audio applications are compiled using the XCommon CMake build system. The minimum XTC tools version that supports XCommon CMake can be found in the README file. Ensure that the firmware is compiled using the correct XTC Tools version.
Note
For convenience the release zips provided from XMOS contain precompiled binary (xe) files.
From a command prompt with the XMOS tools available, follow these steps:
Unzip the package zip to a known location
From the relevant application directory (e.g.
app_usb_aud_xk_audio_316_mc
), execute the commands:cmake -G "Unix Makefiles" -B build xmake -C build
The above steps will configure and build all of the available and supported build configurations for the application.
The applications are compiled using XCommon CMake which is a CMake
based build system.
The primary configuration file for the application is the CMakeLists.txt. It is present in the application directory (e.g. app_usb_aud_xk_audio_316_mc
).
This file specifies build configs, sources, build options and dependencies.
Note
See Build system for more details.
Typically during development the developer wishes to program the device’s internal RAM with the application binary directly via JTAG and then execute this application.
To run one of the compiled binaries complete the following steps:
Connect the USB Audio board to the host computer.
- Connect the xTAG to the USB Audio board and connect it to the host machine on which the application binary is present via a separate USB cable.
note, some boards have integrated xTAGs.
Ensure any required external power jacks are connected
Finally, to run the binary on the target, execute a command similar to the following:
xrun path/to/binary.xe
The device should now present itself as a USB Audio Device on the connected host computer. It will continue to operate as a USB Audio Device until the target board is power cycled.
Optionally a binary can be programmed into the boot flash. To do this:
Connect the USB Audio board to the host computer.
Connect the xTAG to the USB Audio board and connect the it to the host machine on which the application binary is present via a separate USB cable
Ensure any required external power jacks are connected
From a command prompt with the XMOS tools available, run the following command:
xflash path/to/binary.xe
Once flashed the target device will reboot and execute the binary. Power cycling the target board will cause the device to reboot the flashed binary.
Connect the board to any power supply provided (note, some boards will be USB bus powered)
Connect the board to a host with driver support for USB Audio Class using a USB cable
Install the Windows USB Audio 2.0 demonstration driver, if required.
Connect audio input/output devices to the connectors on the board e.g powered speakers
In the audio application, select the XMOS USB Audio device.
Start playing and recording.
The following sections provide a guide on how to program the USB Audio applications including information on project structure, build configurations and creating custom USB audio applications.
The XMOS USB Audio Reference Design software and associated libraries employ the XCommon CMake build system.
The XCommon CMake build system uses CMake to configure and generate the build environment which can then be built using
xmake.
As part of configuring the build environment, if there are any missing dependencies, XCommon CMake fetches them using git
.
Note
All required dependencies are included in the sw_usb_audio zip download.
The sw_usb_audio GIT repository includes multiple application directories.
Each application directory contains a CMakeLists.txt
file which describes the build configs for that application.
The format of the CMakeLists.txt
is described here
XCommon CMake uses the CMakeLists.txt
to generate Makefiles that can be compiled using xmake
into executables.
Typically, there’s one application directory per hardware platform.
Applications and their respective hardware platforms are listed in Table 1.
Application |
Hardware platform |
---|---|
app_usb_aud_xk_316_mc |
xcore.ai USB Audio 2.0 Multi-channel Audio Board |
app_usb_aud_xk_216_mc |
xcore-200 USB Audio 2.0 Multi-channel Audio Board |
app_usb_aud_xk_evk_xu316 |
xcore.ai Evaluation Kit |
The applications depend on several modules (or libraries), each of which have their own GIT repository. The immediate
dependency libraries for the applications are specified by setting the APP_DEPENDENT_MODULES
variable in the
deps.cmake file. deps.cmake
lists the common dependencies for
all the applications and is included in each application’s CMakeLists.txt
.
The dependency list specified in the deps.cmake
can be extended to add new dependencies.
Refer to the XCommon CMake Dependency Format documentation for more information about adding dependencies.
A shared file containing common dependencies ensures a consistent set of dependencies between all of the applications.
Each library has a lib_build_info.cmake
which lists the library source, compile flags and dependencies.
The library dependencies are specified in the LIB_DEPENDENT_MODULES
variable in the lib_build_info.cmake
.
This allows dependency trees and nesting. XCommon CMake builds up a tree which is traversed depth-first,
and populates the sandbox, fetching any missing dependencies by cloning them from github.
Most of the core code is contained in the XMOS USB Audio Library (lib_xua). A full list of core dependencies is shown in Table 2.
Library |
Description |
---|---|
lib_xua |
Common code for USB audio applications |
lib_xud |
Low level USB device library |
lib_spdif |
S/PDIF transmit and receive code |
lib_adat |
ADAT transmit and receive code |
lib_mic_array |
PDM microphone interface and decimator |
lib_xassert |
Lightweight assertions library |
Note
Some of these core dependencies will have their own dependencies, for example lib_mic_array
depnds on lib_xassert
(see above), lib_logging
(a lightweight print library) and lib_xcore_math
(a DSP library).
Due to the flexibility of the reference design software there are a large number of build options. For example input and output channel counts, Audio Class version, interface types etc. A “build configuration” is a set of build options that combine to produce a binary with a certain feature set.
The build configurations are listed in the application CMakeLists.txt
file.
The build config names are appended to the APP_COMPILER_FLAGS
variable to list
the options for the compiler to use when compiling all source files for the given build configuration (APP_COMPILER_FLAGS_<build config>).
For example:
set(APP_COMPILER_FLAGS_2AMi10o10xssxxx ${SW_USB_AUDIO_FLAGS}
-DXUA_SPDIF_TX_EN=1
-DXUA_SPDIF_RX_EN=1)
specifies that the compiler flags used when compiling the 2AMi10o10xssxxx
build config are everything defined in the
SW_USB_AUDIO_FLAGS
variable plus two extra compiler options for enabling S/PDIF transmit and receive.
To configure the build configurations, run the cmake
command from the application (e.g. app_usb_aud_xk_audio_316_mc
) directory:
cmake -G "Unix Makefiles" -B build
This will create a directory called build
within the application directory.
The output displayed on stdout for the cmake
command will contain the list of all the build configurations for that application. For example,
-- Configuring application: app_usb_aud_xk_evk_xu316
-- Found build configs:
-- 1AMi2o2xxxxxx
-- 2AMi2o2xxxxxx
The cmake
command generates the Makefile for compiling the different build configurations.
The Makefile is created in the build
directory.
The next step is to run the xmake
command which executes the commands in the Makefile to build the executables corresponding to
the build configs. To build all supported configurations for a given application, from the application directory (e.g. app_usb_aud_xk_audio_316_mc
),
run:
xmake -C build
This will run the xmake
command in the build
directory.
The built executables are stored in the <app name>/bin/<config name>
directories. For example, the app_usb_aud_xk_316_mc/bin/2AMi8o8xxxxxx
directory contains the app_usb_aud_xk_316_mc_2ASi8o8xxxxxx.xe
executable. Note how the name of the executable is set to <app_name>_<config_name>.xe:
<app name>/bin/<config name>/<app_name>_<config_name>.xe
To build a specific build configuration, after running the cmake
command, run xmake
with the build config specified:
xmake -C build <build config>
For example:
xmake -C build 2AMi10o10xssxxx
A naming scheme is employed in each application to link features to a build configuration/binary. Depending on the hardware interfaces available variations of the same basic scheme are used.
Each relevant build option is assigned a position in the configuration name, with a character denoting the options value (normally ‘x’ is used to denote “off” or “disabled”)
Some example build options are listed in Table 3.
Build Option Name |
Options |
Denoted by |
---|---|---|
Audio Class Version |
1 or 2 |
1 or 2 |
USB synchronisation type |
Asynchronous or Synchronous |
A or S |
Device I2S role |
Master or Slave |
M or S |
USB IN channels |
i<number> |
|
USB OUT channels |
i<number> |
|
MIDI |
on or off |
m or x |
S/PDIF Output |
on or off |
s or x |
S/PDIF Input |
on or off |
s or x |
ADAT Input |
on or off |
a or x |
ADAT Output |
on or off |
a or x |
DSD |
on or off |
d or x |
For example, in this scheme, a configuration named 2AMi8o8msxxax
would indicate Audio Class 2.0,
USB asynchronous mode, xcore is I²S master, 8 USB IN channels, 8 USB OUT channels, MIDI enabled,
S/PDIF input enabled, S/PDIF output disabled, ADAT input disabled, ADAT output enabled and DSD
disabled.
See comments in the application CMakeLists.txt for details.
It is not practical for all build option permutations to be exhaustively tested. The XMOS USB Audio Reference Design software therefore defines three levels of quality:
Fully Tested - the configuration is fully supported. A product based on it can be immediately put into to a production environment with high confidence. Quality assurance (QA) should cover any customised code/functionality.
Partially Tested - the configuration is partially tested. A product based on it can be put into a production environment with medium confidence. Some additional QA is recommended.
Build Tested - the configuration is guaranteed to build but has not been tested. Full QA is required.
Note
Typically disabling a function should have no effect on QA. For example, disabling S/PDIF on a fully-tested configuration with it enabled should not affect its quality.
XMOS aims to provide fully tested configurations for popular device configurations and common customer requirements and use cases.
Note
It is advised that full QA is applied to any product regardless of the quality level of the configuration it is based on.
Fully tested configurations can be found in the application CMakeLists.txt. Partially and build tested configurations can be
found in the configs_partial.cmake
and configs_build.cmake
files respectively.
Running cmake -G "Unix Makefiles" -B build
will only configure the fully tested configurations and following this
up with the xmake -C build
command will build only these.
To configure and build the partially tested configs in addition to the fully tested ones, run cmake with the PARTIAL_TESTED_CONFIGS
variable set to 1:
cmake -G "Unix Makefiles" -B build -DPARTIAL_TESTED_CONFIGS=1
Following this with the xmake -C build
command will build both fully and partially tested configs.
Similarly to also build the build tested configs along with the fully tested ones, run cmake with BUILD_TESTED_CONFIGS
set to 1, followed by the xmake
command:
cmake -G "Unix Makefiles" -B build -DBUILD_TESTED_CONFIGS=1
Note that setting BUILD_TESTED_CONFIGS
to 1 internally also set the PARTIAL_TESTED_CONFIGS
to 1. So running cmake
with BUILD_TESTED_CONFIGS
set to 1 will configure the fully tested, partially tested and build-only configs and following this up with an xmake -C build
will build all the 3 types
of configs.
Note
Pre-release (i.e. alpha, beta or RC) firmware should not be used as basis for a production device and may not be
representative of the final release firmware. Additionally, some releases may include features of lesser quality level.
For example a beta release may contain a feature still at alpha level quality. See application README
for details of any such features.
Note
Due to the similarities between the xcore-200 and xcore.ai series feature sets, it is fully expected that all listed xcore-200 series configurations will operate as expected on the xcore.ai series and vice versa. It is therefore expected that a quality level of a configuration will migrate between XMOS device series.
This section provides a walk through of a typical USB Audio application. Where specific examples are required,
code is used from the application for XK-AUDIO-316-MC (app_usb_aud_xk_316_mc
).
Note
The applications in sw_usb_audio
use the “Codeless Programming Model” as documented in lib_xua
.
Briefly, the main()
function is used from lib_xua
with build-time defines in the application configuring
the framework provided by lib_xua
. Various functions from lib_xua
are then overridden to provide
customisation. See lib_xua
for full details.
Each application directory contains:
A
CMakeLists.txt
A
src
directory
The src
directory is arranged into two directories:
A
core
directory containing source items that must be made available to the USB Audio framework i.e.lib_xua
.An
extensions
directory that includes extensions to the framework such as external device configuration etc
The core
folder for each application contains:
A
.xn
file to describe the hardware platform the application will run onAn optional header file to customise the framework provided by
lib_xua
namedxua_conf.h
The xua_conf.h
file contains all the build-time #defines
required to tailor the framework
provided by lib_xua
to the particular application at hand.
Typically these override default values in xua_conf_default.h
in lib_xua/api
.
Firstly in app_usb_aud_xk_316_mc
the xua_conf.h
file sets defines to determine overall capability. For this application
most of the optional interfaces are disabled by default. This is because the applications provide a large number build configurations
in the CMakeLists.txt
enabling various interfaces. For a product with a fixed specification this almost certainly would not be the case and setting
in this file may be the preferred option.
Note that ifndef
is used to check that the option is not already defined in the CMakeLists.txt
.
/* Enable/Disable MIDI - Default is MIDI off */
#ifndef MIDI
#define MIDI (0)
#endif
/* Enable/Disable S/PDIF output - Default is S/PDIF off */
#ifndef XUA_SPDIF_TX_EN
#define XUA_SPDIF_TX_EN (0)
#endif
/* Enable/Disable S/PDIF input - Default is S/PDIF off */
#ifndef XUA_SPDIF_RX_EN
#define XUA_SPDIF_RX_EN (0)
#endif
/* Enable/Disable ADAT output - Default is ADAT off */
#ifndef XUA_ADAT_TX_EN
#define XUA_ADAT_TX_EN (0)
#endif
/* Enable/Disable ADAT input - Default is ADAT off */
#ifndef XUA_ADAT_RX_EN
#define XUA_ADAT_RX_EN (0)
#endif
/* Enable/Disable Mixing core(s) - Default is on */
#ifndef MIXER
#define MIXER (1)
#endif
/* Set the number of mixes to perform - Default is 0 i.e mixing disabled */
#ifndef MAX_MIX_COUNT
#define MAX_MIX_COUNT (0)
#endif
/* Audio Class version - Default is 2.0 */
#ifndef AUDIO_CLASS
#define AUDIO_CLASS (2)
#endif
Next, the file defines properties of the audio channels including counts and arrangements. By default the application provides 8 analogue channels for input and output.
The total number of channels exposed to the USB host (set via NUM_USB_CHAN_OUT
and NUM_USB_CHAN_IN
) are calculated
based on the audio interfaces enabled. Again, this is due to the multiple build configurations in the application CMakeLists.txt
and likely to be hard-coded for a product.
/* Number of I2S channels to DACs*/
#ifndef I2S_CHANS_DAC
#define I2S_CHANS_DAC (8)
#endif
/* Number of I2S channels from ADCs */
#ifndef I2S_CHANS_ADC
#define I2S_CHANS_ADC (8)
#endif
/* Number of USB streaming channels - by default calculate by counting audio interfaces */
#ifndef NUM_USB_CHAN_IN
#define NUM_USB_CHAN_IN (I2S_CHANS_ADC + 2*XUA_SPDIF_RX_EN + 8*XUA_ADAT_RX_EN) /* Device to Host */
#endif
#ifndef NUM_USB_CHAN_OUT
#define NUM_USB_CHAN_OUT (I2S_CHANS_DAC + 2*XUA_SPDIF_TX_EN + 8*XUA_ADAT_TX_EN) /* Host to Device */
#endif
/*** Defines relating to channel arrangement/indices ***/
Channel indices/offsets are set based on the audio interfaces enabled. Channels are indexed from 0. Setting SPDIF_TX_INDEX
to 0
would cause the S/PDIF channels to duplicate analogue channels 0 and 1. Note, the offset for analogue channels is always 0.
/* Channel index of S/PDIF Tx channels: separate channels after analogue channels (if they fit) */
#ifndef SPDIF_TX_INDEX
#if (I2S_CHANS_DAC + 2*XUA_SPDIF_TX_EN) <= NUM_USB_CHAN_OUT
#define SPDIF_TX_INDEX (I2S_CHANS_DAC)
#else
#define SPDIF_TX_INDEX (0)
#endif
#endif
/* Channel index of S/PDIF Rx channels: separate channels after analogue channels */
#ifndef SPDIF_RX_INDEX
#define SPDIF_RX_INDEX (I2S_CHANS_ADC)
#endif
/* Channel index of ADAT Tx channels: separate channels after S/PDIF channels (if they fit) */
#ifndef ADAT_TX_INDEX
#define ADAT_TX_INDEX (I2S_CHANS_DAC + 2*XUA_SPDIF_TX_EN)
#endif
/* Channel index of ADAT Rx channels: separate channels after S/PDIF channels */
#ifndef ADAT_RX_INDEX
#define ADAT_RX_INDEX (I2S_CHANS_ADC + 2*XUA_SPDIF_RX_EN)
#endif
The file then sets some frequency related defines for the audio master clocks and the maximum sample-rate for the device.
/* Master clock defines (in Hz) */
#ifndef MCLK_441
#define MCLK_441 (512*44100) /* 44.1, 88.2 etc */
#endif
#ifndef MCLK_48
#define MCLK_48 (512*48000) /* 48, 96 etc */
#endif
/* Minumum sample frequency device runs at */
#ifndef MIN_FREQ
#define MIN_FREQ (44100)
#endif
/* Maximum sample frequency device runs at */
#ifndef MAX_FREQ
#define MAX_FREQ (192000)
#endif
Due to the multi-tile nature of the xcore architecture the framework needs to be informed as to which tile various interfaces should be placed on, for example USB, S/PDIF etc.
#define XUD_TILE (0)
#define PLL_REF_TILE (0)
#define AUDIO_IO_TILE (1)
#define MIDI_TILE (1)
The file also sets some defines for general USB IDs and strings. These are set for the XMOS reference design but vary per manufacturer:
#define VENDOR_ID (0x20B1) /* XMOS VID */
#ifndef PID_AUDIO_2
#define PID_AUDIO_2 (0x0016)
#endif
#ifndef PID_AUDIO_1
#define PID_AUDIO_1 (0x0017)
#endif
#ifndef DFU_PID
#if (AUDIO_CLASS == 1)
#define DFU_PID (0xD000 + PID_AUDIO_1)
#else
#define DFU_PID (0xD000 + PID_AUDIO_2)
#endif
#endif
#define PRODUCT_STR_A2 "XMOS xCORE.ai MC (UAC2.0)"
#define PRODUCT_STR_A1 "XMOS xCORE.ai MC (UAC1.0)"
For a full description of all the defines that can be set in xua_conf.h
see Configuration defines.
In addition to the xua_conf.h
file, the application needs to provide implementations of some overridable user
functions in lib_xua
to provide custom functionality.
For app_usb_aud_xk_316_mc
the implementations can be found in src/extensions/audiohw.xc
and src/extensions/audiostream.xc
The two functions it overrides in audiohw.xc
are AudioHwInit()
and AudioHwConfig()
.
These are run from lib_xua
on startup and sample-rate change respectively.
Note, the default implementations in lib_xua
are empty.
These functions have parameters for sample frequency, sample depth, etc.
In the case of app_usb_aud_xk_316_mc
these functions configure the external DACs and ADCs via an I²C bus and configure
the xcore secondary PLL to generate the required master clock frequencies.
Due to the complexity of the hardware on the XK-AUDIO-316-MC the source code is not included here.
The application also overrides UserAudioStreamStart()
and UserAudioStreamStop()
.
These are called from lib_xua
when the audio
stream to the device is started or stopped respectively.
The application uses these functions to enable/disable the on board LEDs based on whether an audio
stream is active (input or output).
// Copyright 2022-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <platform.h>
on tile[0]: out port p_leds = XS1_PORT_4F;
void UserAudioStreamStart(void)
{
/* Turn all LEDs on */
p_leds <: 0xF;
}
void UserAudioStreamStop(void)
{
/* Turn all LEDs off */
p_leds <: 0x0;
}
Note
A media player application may choose to keep an audio stream open and active and simply send zero data when paused.
The main()
function is the entry point to an application. In the XMOS USB Audio Reference Design
software it is shared by all applications and is therefore part of the framework.
This section is largely informational as most developers should not need to modify the main()
function.
main()
is located in main.xc
in lib_xua
, this file contains:
A declaration of all the ports used in the framework. These clearly vary depending on the hardware platform the application is running on.
A
main()
function which declares some channels and then has apar
statement which runs the required cores in parallel.
Full documentation can be found in lib_xua.
The first items in the par
include running tasks for the Endpoint 0 implementaton and buffering
tasks for audio and endpoint buffering:
{
unsigned x;
thread_speed();
/* Attach mclk count port to mclk clock-block (for feedback) */
//set_port_clock(p_for_mclk_count, clk_audio_mclk);
#if(AUDIO_IO_TILE != XUD_TILE)
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb);
set_port_clock(p_for_mclk_count, clk_audio_mclk_usb);
start_clock(clk_audio_mclk_usb);
#else
/* Clock port from same clock-block as I2S */
/* TODO remove asm() */
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count), "r"(x));
#endif
/* Endpoint & audio buffering cores - buffers all EP's other than 0 */
XUA_Buffer(
#if (NUM_USB_CHAN_OUT > 0)
c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO], /* Audio Out*/
#endif
#if (NUM_USB_CHAN_IN > 0)
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Audio Interrupt - only used for interrupts on external clock change */
c_xud_in[ENDPOINT_NUMBER_IN_INTERRUPT],
c_clk_int,
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#if (XUA_HID_ENABLED)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
, c_mix_out
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#if (!XUA_USE_SW_PLL)
, i_pll_ref
#else
, c_sw_pll
#endif
#endif
);
//:
}
#endif
/* Endpoint 0 Core */
{
thread_speed();
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
}
It also runs a task for the USB interfacing thread (XUD_Main()
):
XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN,
The specification of the channel arrays connecting to this driver are described in the documentation for lib_xud.
The channels connected to XUD_Main()
are passed to the XUA_Buffer()
function which implements audio buffering and also
buffering for other Endpoints.
XUA_Buffer(
#if (NUM_USB_CHAN_OUT > 0)
c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO], /* Audio Out*/
#endif
#if (NUM_USB_CHAN_IN > 0)
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Audio Interrupt - only used for interrupts on external clock change */
c_xud_in[ENDPOINT_NUMBER_IN_INTERRUPT],
c_clk_int,
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#if (XUA_HID_ENABLED)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
, c_mix_out
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#if (!XUA_USE_SW_PLL)
, i_pll_ref
#else
, c_sw_pll
#endif
#endif
);
A channel connects this buffering task to the audio driver which controls the I²S output. It also forwards and receives audio samples from other interfaces e.g. S/PDIF, ADAT, as required:
usb_audio_io(
#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0)
/* Connect audio system to XUA_Buffer(); */
c_mix_out
#else
/* Connect to XUA_Endpoint0() */
c_aud_ctl
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
#if (MIXER)
, c_mix_ctl
#endif
, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, c_pdm_pcm
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, i_pll_ref
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#endif
#if ((XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
, p_for_mclk_count_audio
, c_sw_pll
#endif
);
}
Finally, other tasks are created for various interfaces, for example, if MIDI is enabled a core is required to drive the MIDI input and output.
on tile[MIDI_TILE]:
{
thread_speed();
usb_midi(p_midi_rx, p_midi_tx, clk_midi, c_midi, 0);
}
The flexibility of the XMOS USB Audio Reference Design software is such that the reference applications can be modified to change the feature set or add extra functionality. Any part of the software can be altered since full source code is supplied.
Note
The reference designs have been verified against a variety of host operating systems at different samples rates. Modifications to the code may invalidate the results of this verification and fully retesting the resulting software is strongly recommended.
Note
Developers are encouraged to use a version control system, i.e. GIT, to track changes to the codebase, however, this is beyond the scope of this document.
The general steps to producing a custom codebase are as follows:
Make a copy of the reference application directory (e.g. app_usb_aud_xk_316_mc
or app_usb_aud_xk_216_mc
)
to a separate directory with a different name. Modify the new application to suit the custom requirements. For example:
Provide the .xn
file for the target hardware platform by setting the APP_HW_TARGET
in the application’s CMakeLists.txt
.
Update xua_conf.h
with specific defines for the custom application.
Add any other custom code in the files as needed.
Update the main.xc
to add any custom tasks.
Make a copy of any dependencies that require modification (in most cases, this step is unnecessary).
Update the custom application’s CMakeLists.txt
to use these new modules.
After making appropriate changes to the code, rebuild and re-flash the device for testing.
Note
Whilst a developer may directly change the code in main.xc
to add custom tasks this may not always
be desirable. Doing this may make taking updates from XMOS non-trivial (the same can be said for any
custom modifications to any core libraries). Since adding tasks is considered reasonably common, customisation
defines USER_MAIN_CORES
and USER_MAIN_DECLARATIONS
are made available.
An example usage is shown in app_usb_aud_xk_316_mc/src/extensions/user_main.h
In reality the developer must weigh up the inconvenience of using these defines versus the
inconvenience of merging updates from XMOS into a modified codebase.
The following sections show some example changes with a high level overview of how to change the code.
Customising the digital output format may be required, for example, to support a CODEC that expects sample data right-justified with respect to the word clock.
To achieve this, alter the main audio driver loop in xua_audiohub.xc
. After making the alteration, re-test the functionality to ensure proper operation.
Hint, a naive approach would simply include right-shifting the audio data by 7 bits before it is output to the port. This would of course lose LSB data depending on the sample-depth.
To add some DSP requires an extra thread of computation. Depending on the xcore device being used, some existing functionality might need to be disabled to free up a thread (e.g. disable S/PDIF). There are many ways that DSP processing can be added, the steps below outline one approach:
Remove some functionality using the defines in Configuration defines to free up a thread as required.
Add another thread to do the DSP. This core will probably have a single XC channel. This channel can be used to send
and receive audio samples from the XUA_AudioHub()
task. A benefit of modifying samples here is that samples from
all inputs are collected into one place at this point. Optionally, a second channel could be used to accept control
messages that affect the DSP. This could be from Endpoint 0 or some other task with user input - a thread handling
button presses, for example.
Implement the DSP in this thread. This needs to be synchronous (i.e. for every sample received from the XUA_AudioHub()
,
a sample needs to be output back).
The reference applications supplied in sw_usb_audio
use the framework provided in lib_xua
and
provide qualified configurations of the framework which support, and are validated, on an accompanying
reference hardware platform.
These reference design applications customise and extend this framework to provide the required functionality. This document will now examine in detail how each of the provided applications customise and extend the framework.
The applications contained in this repo use lib_xua
in a “code-less” manner. That is, they use
the main()
function from lib_xua
and customise the code-base as required using build time defines and by
providing implementations to the various required functions in order to support their hardware.
Refer to lib_xua <https://www.xmos.com/file/lib_xua>`_ documentation for full details.
An application of the USB audio framework is provided specifically for the XK_AUDIO_316_MC
hardware described in USB Audio hardware platforms and is implemented on an xcore.ai
series dual tile device. The related code can be found in app_usb_aud_xk_316_mc
.
The design supports upto 8 channels of analogue audio input/output at sample-rates up to 192 kHz
(assuming the use of I²S). This can be further increased by utilising TDM. It also supports S/PDIF,
ADAT and MIDI input and output as well as the mixing functionalty of lib_xua
.
The design uses the following tasks:
XMOS USB Device Driver (XUD)
Endpoint 0
Endpoint Buffer
Decoupler
AudioHub Driver
Mixer
S/PDIF Transmitter
S/PDIF Receiver
ADAT Transmitter
ADAT Receiver
Clockgen
MIDI
The software layout of the USB Audio 2.0 Reference Design running on the xcore.ai device is shown in Fig. 1.
Each circle depicts a task running in a single core concurrently with the other tasks. The lines show the communication between each task.
xcore.ai multichannel audio system/task diagram
As well as the secondary (application) PLL of the xcore.ai device the board includes two options for master clock generation:
A Cirrus Logic CS2100 fractional-N clock multiplier allowing the master clock to be generated from a xcore derived reference clock.
A Skyworks Si5351A-B-GT CMOS clock generator.
The master clock source is chosen by driving two control signals as shown below:
Control Signal |
Master Clock Source |
|
---|---|---|
EXT_PLL_SEL |
MCLK_DIR |
|
0 |
0 |
Cirrus CS2100 |
1 |
0 |
Skyworks SI5351A-B-GT |
X |
1 |
xcore.ai secondary (application) PLL |
Each of the sources have potential benefits, some of which are discussed below:
The Cirrus CS2100 simplifies generating a master clock locked to an external clock (such as S/PDIF in or word clock in).
It multiplies up the PLL_SYNC signal which is generated by the xcore.ai device based on the desired external source (so S/PDIF in frame signal or word clock in).
The Si5351A-B-GT offers very low jitter performance at a relatively lower cost than the CS2100. Locking to an external source is more difficult.
The xcore.ai secondary PLL is obviously the lowest cost and significantly lowest power solution, however its jitter performance can not match the Si5351A which may be important in demanding applications. Locking to an external clock is possible but involves more complicated firmware and more MIPS.
The master clock source is controlled by a mux which, in turn, is controlled by bit 5 of PORT 8C:
Value |
Source |
---|---|
0 |
Master clock is sourced from PhaseLink PLL |
1 |
Master clock is source from Cirrus Clock Multiplier |
The clock-select from the phaselink part is controlled via bit 7 of PORT 8C:
Value |
Frequency |
---|---|
0 |
24.576MHz |
1 |
22.579MHz |
The board is equipped with four PCM5122 stereo DACs from Texas instruments and two quad-channel PCM1865 ADCs from Texas Instruments, giving 8 channels of analogue output and 8 channels of analogue input. Configuration of both the DAC and the ADC takes place over I²C.
All of the external audio hardware is configured using lib_board_support.
Note
lib_board_support
has the I²C library (lib_i2c) in its dependency list.
The hardware targeted is the XMOS XU316 Multichannel Audio board (XK-AUDIO-316-MC).
The lib_board_support functions xk_audio_316_mc_ab_board_setup()
, xk_audio_316_mc_ab_i2c_master()
,
xk_audio_316_mc_ab_AudioHwInit()
and xk_audio_316_mc_ab_AudioHwConfig()
are called at various points during initialisation and
runtime to start the I²C master, initialise and configure the audio hardware.
The audio hardware configuration is set in the config
structure of type xk_audio_316_mc_ab_config_t
which is passed to the xk_audio_316_mc_ab_board_setup()
,
xk_audio_316_mc_ab_AudioHwInit()
and xk_audio_316_mc_ab_AudioHwConfig()
functions.
static xk_audio_316_mc_ab_config_t config =
{
// clk_mode
(XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
? ( XUA_USE_SW_PLL
? CLK_PLL : CLK_CS2100 )
: CLK_FIXED,
// dac_is_clk_master
CODEC_MASTER,
// default_mclk
(DEFAULT_FREQ % 22050 == 0) ? MCLK_441 : MCLK_48,
// pll_sync_freq
PLL_SYNC_FREQ,
// pcm_format
XUA_PCM_FORMAT,
// i2s_n_bits
XUA_I2S_N_BITS,
// i2s_chans_per_frame
I2S_CHANS_PER_FRAME
};
xk_audio_316_mc_ab_board_setup()
function is called from the wrapper function
board_setup()
as part of the application’s initialisation process.
It performs the required port operations to enable the audio hardware on the platform.
xk_audio_316_mc_ab_i2c_master()
function is called after board_setup()
during
initialisation and it starts the I²C master task. This is required to allow the audio hardware to
be configured over I²C, remotely from the other tile, due to the IO arrangement of the
XK-AUDIO-316-MC board.
#define USER_MAIN_CORES on tile[0]: {\
board_setup();\
xk_audio_316_mc_ab_i2c_master(i2c);\
The AudioHwInit()
function is implemented to make a call to the lib_board_support
function xk_audio_316_mc_ab_AudioHwInit()
to power up and initialise the audio hardware
ready for a configuration.
The AudioHwConfig()
function configures the audio hardware post initialisation.
It is typically called each time a sample rate or stream format change occurs.
It is implmented to make a call to the lib_board_support
function xk_audio_316_mc_ab_AudioHwConfig()
.
For further details on the hardware platform and the functions available for configuring it refer to lib_board_support documentation.
The reference design can be built in several ways by changing the build options. These are described in Configuration defines.
The design has only been fully validated against the build options as set in the application as distributed in the CMakeLists.txt. See Build configurations for details and general information on build configuration naming scheme.
These fully validated build configurations are enumerated in the supplied CMakeLists.txt.
The build configuration naming scheme employed in the CMakeLists.txt is shown in Table 6.
Feature |
Option 1 |
Option 2 |
---|---|---|
Audio Class |
1 |
2 |
USB Sync Mode |
async: A |
sync: S |
I²S Role |
slave: S |
master: M |
Input |
enabled: i (channel count) |
disabled: x |
Output |
enabled: i (channel count) |
disabled: x |
MIDI |
enabled: m |
disabled: x |
S/PDIF input |
enabled: s |
disabled: x |
S/PDIF input |
enabled: s |
disabled: x |
ADAT input |
enabled: a |
disabled: x |
ADAT output |
enabled: a |
disabled: x |
DSD output |
enabled: d |
disabled: x |
e.g. A build configuration named 2AMi10o10xsxxxx would signify: Audio Class 2.0 running in asynchronous mode. The xcore is I²S master. Input and output enabled (10 channels each), no MIDI, S/PDIF input, no S/PDIF output, no ADAT or DSD.
In addition to this some terms may be appended onto a build configuration name to signify additional options. For example, tdm may be appended to the build configuration name to indicate the I²S mode employed.
An application of the USB audio framework is provided specifically for the XK_AUDIO_216_MC_AB
hardware described in USB Audio hardware platforms and is implemented on an xcore-200
series dual tile device. The related code can be found in app_usb_aud_xk_216_mc
.
The design supports upto 8 channels of analogue audio input/output at sample-rates up to 192kHz
(assuming the use of I²S). This can be further increased by utilising TDM. It also supports S/PDIF,
ADAT and MIDI input and output as well as the mixing functionalty of lib_xua
.
The design uses the following tasks:
XMOS USB Device Driver (XUD)
Endpoint 0
Endpoint Buffer
Decoupler
AudioHub Driver
Mixer
S/PDIF Transmitter
S/PDIF Receiver
ADAT Receiver
Clockgen
MIDI
The software layout of the USB Audio 2.0 Reference Design running on the xcore.ai device is shown in Fig. 2.
Each circle depicts a task running in a single core concurrently with the other tasks. The lines show the communication between each task.
xcore-200 Multichannel Audio system/task diagram
The app_usb_aud_xk_216_mc
application uses the functions provided in lib_board_support
for master clock generation and audio hardware configuration.
The functions xk_audio_216_mc_ab_AudioHwInit()
and
xk_audio_216_mc_ab_AudioHwConfig()
are called at various points during initialisation and
runtime to initialise and configure the audio hardware.
For further details on the hardware platform and the functions available for configuring it refer to lib_board_support documentation.
The board includes two options for master clock generation:
A single oscillator with a Phaselink PLL to generate fixed 24.576MHz and 22.5792MHz master-clocks.
A Cirrus Logic CS2100 clock multiplier allowing the master clock to be generated from a xcore derived reference clock.
The master clock source is controlled by a mux which, in turn, is controlled by bit 5 of PORT 8C:
Value |
Source |
---|---|
0 |
Master clock is sourced from PhaseLink PLL |
1 |
Master clock is source from Cirrus Clock Multiplier |
The clock-select from the phaselink part is controlled via bit 7 of PORT 8C:
Value |
Frequency |
---|---|
0 |
24.576MHz |
1 |
22.579MHz |
The board is equipped with a single multi-channel audio DAC (Cirrus Logic CS4384) and a single multi-channel ADC (Cirrus Logic CS5368) giving 8 channels of analogue output and 8 channels of analogue input. Configuration of both the DAC and the ADC takes place over I²C.
All of the external audio hardware is configured using lib_board_support
.
Note
lib_board_support
has the I²C library (lib_i2c) in its dependency list.
The hardware targeted is the XMOS XU216 Multichannel Audio board (XK-AUDIO-216-MC).
The functions xk_audio_216_mc_ab_AudioHwInit()
and
xk_audio_216_mc_ab_AudioHwConfig()
are called at various points during initialisation and
runtime to initialise and configure the audio hardware.
The audio hardware configuration is set in the config
structure of type
xk_audio_216_mc_ab_config_t
which is passed to the
xk_audio_216_mc_ab_AudioHwInit()
and xk_audio_216_mc_ab_AudioHwConfig()
functions.
static const xk_audio_216_mc_ab_config_t config = {
// clk_mode
CLK_MODE,
// codec_is_clk_master
CODEC_MASTER,
// usb_sel
(USB_SEL_A ? AUD_216_USB_A : AUD_216_USB_B),
// pcm_format
XUA_PCM_FORMAT,
// pll_sync_freq
PLL_SYNC_FREQ
};
The AudioHwInit()
function is implemented to make a call to the lib_board_support
function xk_audio_216_mc_ab_AudioHwInit()
to power up and initialise the audio hardware
ready for a configuration.
The AudioHwConfig()
function configures the audio hardware post initialisation.
It is called each time a sample rate or stream format change occurs.
It is implemented to make a call to the lib_board_support
function
xk_audio_216_mc_ab_AudioHwConfig()
.
For further details on the hardware platform and the functions available for configuring it refer to lib_board_support documentation.
The reference design can be built in several ways by changing the build options. These are described in Configuration defines.
The design has only been fully validated against the build options as set in the application as distributed in the CMakeLists.txt. See Build configurations for details and general information on build configuation naming scheme.
These fully validated build configurations are enumerated in the supplied CMakeLists.txt.
In practise, due to the similarities between the xcore-200 and xcore.ai series feature set, it is fully expected that all listed xcore-200 series configurations will operate as expected on the xcore.ai series and vice versa.
The build configuration naming scheme employed in the CMakeLists.txt is shown in Table 9.
Feature |
Option 1 |
Option 2 |
---|---|---|
Audio Class |
1 |
2 |
USB Sync Mode |
async: A |
sync: S |
I²S Role |
slave: S |
master: M |
Input |
enabled: i (channel count) |
disabled: x |
Output |
enabled: i (channel count) |
disabled: x |
MIDI |
enabled: m |
disabled: x |
S/PDIF input |
enabled: s |
disabled: x |
S/PDIF input |
enabled: s |
disabled: x |
ADAT input |
enabled: a |
disabled: x |
ADAT output |
enabled: a |
disabled: x |
DSD output |
enabled: d |
disabled: x |
e.g. A build configuration named 2AMi10o10xsxxxx would signify: Audio class 2.0 running in asynchronous mode. The xcore is I²S master. Input and output enabled (10 channels each), no MIDI, S/PDIF input, no S/PDIF output, no ADAT or DSD.
In addition to this some terms may be appended onto a build configuration name to signify additional options. For example, tdm may be appended to the build configuration name to indicate the I²S mode employed.
An application using the USB audio framework provided by lib_xua
needs to be configured via
defines. Defaults for these defines are found in lib_xua
in xua_conf_default.h
.
An application should override these defines in an optional xua_conf.h
file or in the
CMakeLists.txt
for the relevant build configuration.
This section documents commonly used defines, for full listings and documentation see the lib_xua
.
Location (tile) of audio I/O. Default: 0.
Location (tile) of audio I/O. Default: 0.
Location (tile) of MIDI I/O. Default: AUDIO_IO_TILE.
Location (tile) of reference signal to CS2100. Default: AUDIO_IO_TILE.
Location (tile) of SPDIF Tx. Default: AUDIO_IO_TILE.
Number of output channels (host to device). Default: NONE (Must be defined by app)
Number of input channels (device to host). Default: NONE (Must be defined by app)
Number of I2S channesl to DAC/CODEC. Must be a multiple of 2.
Default: NONE (Must be defined by app)
Number of I2S channels from ADC/CODEC. Must be a multiple of 2.
Default: NONE (Must be defined by app)
Number of DSD output channels.
Default: 0 (disabled)
Max supported sample frequency for device (Hz).
Default: 192000Hz
Min supported sample frequency for device (Hz).
Default: 44100Hz
Master clock defines for 44100 rates (in Hz).
Default: NONE (Must be defined by app)
Master clock defines for 48000 rates (in Hz).
Default: NONE (Must be defined by app)
USB Audio Class Version.
Default: 2 (Audio Class version 2.0)
Enable MIDI functionality including buffering, descriptors etc. Default: DISABLED.
MIDI Rx port width (1 or 4bit). Default: 1.
Enables SPDIF Tx. Default: 0 (Disabled)
Defines which output channels (stereo) should be output on S/PDIF. Note, Output channels indexed from 0.
Default: 0 (i.e. channels 0 & 1)
Enables SPDIF Rx. Default: 0 (Disabled)
S/PDIF Rx first channel index, defines which channels S/PDIF will be input on. Note, indexed from 0.
Default: NONE (Must be defined by app when SPDIF_RX enabled)
Enables ADAT Tx. Default: 0 (Disabled)
Defines which output channels (8) should be output on ADAT. Note, Output channels indexed from 0.
Default: 0 (i.e. channels [0:7])
Enables ADAT Rx. Default: 0 (Disabled)
ADAT Rx first channel index. defines which channels ADAT will be input on. Note, indexed from 0.
Default: NONE (Must be defined by app when XUA_ADAT_RX_EN is true)
Number of PDM microphones in the design.
Default: 0
Enable DFU functionality.
Default: 1 (Enabled)
Enable HID playback controls functionality.
1 for enabled, 0 for disabled.
Default 0 (Disabled)
Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
0: XMOS is I2S master. 1: CODEC is I2s master.
Default: 0 (XMOS is master)
Vendor String used by the device. This is also pre-pended to various strings used by the design.
Default: “XMOS”
USB Vendor ID (or VID) as assigned by the USB-IF.
Default: 0x20B1 (XMOS)
USB Product String for the device. If defined will be used for both PRODUCT_STR_A2 and PRODUCT_STR_A1.
Default: Undefined
Product string for Audio Class 2.0 mode.
Default: “XMOS xCORE (UAC2.0)”
Product string for Audio Class 1.0 mode.
Default: “XMOS xCORE (UAC1.0)”
USB Product ID (PID) for Audio Class 1.0 mode. Only required if AUDIO_CLASS == 1 or AUDIO_CLASS_FALLBACK is enabled.
Default: 0x0003
USB Product ID (PID) for Audio Class 2.0 mode.
Default: 0x0002
Device firmware version number in Binary Coded Decimal format: 0xJJMN where JJ: major, M: minor, N: sub-minor version number.
NOTE: User code should not modify this but should modify BCD_DEVICE_J, BCD_DEVICE_M, BCD_DEVICE_N instead
Default: XMOS USB Audio Release version (e.g. 0x0651 for 6.5.1).
Enable/disable output volume control including all processing and descriptor support.
Default: 1 (Enabled)
Enable/disable input volume control including all processing and descriptor support.
Default: 1 (Enabled)
Enable “mixer” core.
Default: 0 (Disabled)
Number of seperate mixes to perform.
Default: 8 if MIXER enabled, else 0
Number of channels input into the mixer.
Note, total number of mixer nodes is MIX_INPUTS * MAX_MIX_COUNT
Default: 18
Report as self or bus powered device. This affects descriptors and XUD usage and is important for USB compliance.
Default: XUA_POWERMODE_BUS
The following functions can be optionally defined by an application to override default (empty)
implementations in lib_xua
.
The functions listed below should be implemented to configure external audio hardware.
User audio hardware initialisation code.
This function is called when the device starts up and should contain user code to perform any required audio hardware initialisation
User audio hardware configuration code.
This function is called when on sample rate change and should contain user code to configure audio hardware (clocking, CODECs etc) for a specific mClk/Sample frequency
samFreq – The new sample frequency (in Hz)
mClk – The new master clock frequency (in Hz)
dsdMode – DSD mode, DSD_MODE_NATIVE, DSD_MODE_DOP or DSD_MODE_OFF
sampRes_DAC – Playback sample resolution (in bits)
sampRes_ADC – Record sample resolution (in bits)
User code mute audio hardware.
This function is called before AudioHwConfig() and should contain user code to mute audio hardware before a sample rate change in order to reduced audible pops/clicks
Note, if using the application PLL of a xcore.ai device this function will be called before the master-clock is changed
User code to un-mute audio hardware.
This function is called after AudioHwConfig() and should contain user code to un-mute audio hardware after a sample rate change
The functions listed below can be useful for mute lines, indication LEDs etc.
User stream start code.
User code to perform any actions required at every stream start - either input or output
User stream stop code.
User code to perform any actions required on every stream stop - either input or output
User input stream stop code.
User code to perform any actions required on input stream start i.e. device to host
User input stream stop code.
User code to perform any actions required on input stream stop i.e. device to host
User output stream start code.
User code to perform any actions required on output stream start i.e. host to device
User output stream stop code.
User code to perfrom any actions required on output stream stop i.e. host to device
The following function is called when the device wishes to read physical user input (buttons etc). The function should write relevant HID bits into this array. The bit ordering and functionality is defined by the HID report descriptor used.
Get the data for the next HID Report.
id – [in] The HID Report ID (see 5.6, 6.2.2.7, 8.1 and 8.2 of the USB Device Class Definition for HID 1.11) Set to zero if the application provides only one HID Report which does not include a Report ID
hidData – [out] The HID data If using Report IDs, this function places the Report ID in the first element; otherwise the first element holds the first byte of HID event data.
Zero – means no new HID event data has been recorded for the given id
The length of the HID Report in the hidData argument
Why does the USBView tool from Microsoft show errors in the devices descriptors?
The USBView tool supports USB Audio Class 1.0 only
How do I set the maximum sample rate of the device?
See MAX_FREQ define in Configuration defines
What is the maximum channel count the device can support?
The maximum channel count of a device is a function of sample-rate and sample-depth. A standard high-speed USB Isochronous endpoint can handle a 1024 byte packet every microframe (125uS).
It follows then that at 192 kHz the device/hosts expects 24 samples per frame (192000/8000). When using Asynchronous mode we must allow for +/- one sample, so 25 samples per microframe in this case.
Assuming 4 byte (32 bit) sample size, the bus expects ((192000/8000)+1) * 4 = 100 bytes per channel per microframe. Dividing the maximum packet size by this value yields the theoretical maximum channel count at the given frequency, that is 1024/100 = 10.24. Clearly this must be rounded down to 10 whole channels.