Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ UNRELEASED
same functionality as `xua_conf_cores.h` i.e. to allow insertion of tasks
into the `main()` function (`xua_conf_cores.h` to be deprecated in a future
release)
ADDED: Support for define `USER_MAIN_TASKS` with the same functionalty
* ADDED: Support for define `USER_MAIN_TASKS` with the same functionalty
as `USER_MAIN_CORES` i.e. to allow insertion of tasks into the `main()`
function (`USER_MAIN_CORES` to be deprecated in a future release)
* CHANGED: Supported optional configuration header files
Expand All @@ -25,6 +25,8 @@ UNRELEASED
* FIXED: When software pll is enabled, report external clock as invalid when the USB sampling frequency
doesn't match the digital input sampling frequency, instead of programming a wrong value dco Setting
in the pll sigma delta modulator
* ADDED: Support for core USB Audio task (XUA_WRAPPER) without audio task (I2S) which provides
simple API for projects that need to use USB audio as simple audio source/sink

5.1.0
-----
Expand Down
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ project(lib_xua_examples)
add_subdirectory(AN00246_xua_example)
add_subdirectory(AN00247_xua_example_spdif_tx)
add_subdirectory(AN00248_xua_example_pdm_mics)
add_subdirectory(app_lib_i2s_wrapper)
34 changes: 34 additions & 0 deletions examples/app_lib_i2s_wrapper/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.21)
include($ENV{XMOS_CMAKE_PATH}/xcommon.cmake)
project(app_xua_simple_lib_i2s)

set(APP_HW_TARGET xk-audio-316-mc.xn)

set(APP_INCLUDES src)

set(APP_DEPENDENT_MODULES "lib_xua(develop)"
"lib_i2s(6.0.1)"
"lib_board_support(develop)")

set(COMPILER_FLAGS_COMMON -O3
-report
-g
-Wno-unused-function
-DXUD_CORE_CLOCK=600
-DXUD_TILE=0
-DAUDIO_IO_TILE=1
-fxscope
-DUAC_FORCE_FEEDBACK_EP=0
-DDEBUG_PRINT_ENABLE=1
-DBOARD_SUPPORT_BOARD=XK_AUDIO_316_MC_AB)

set(APP_COMPILER_FLAGS_master ${COMPILER_FLAGS_COMMON}
-DI2S_MASTER=1)

set(APP_COMPILER_FLAGS_slave ${COMPILER_FLAGS_COMMON}
-DI2S_SLAVE=1)


set(XMOS_SANDBOX_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..)

XMOS_REGISTER_APP()
2 changes: 2 additions & 0 deletions examples/app_lib_i2s_wrapper/config.xscope
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<xSCOPEconfig ioMode="basic" enabled="true">
</xSCOPEconfig>
158 changes: 158 additions & 0 deletions examples/app_lib_i2s_wrapper/src/app_xua_simple.xc
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright 2017-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

/* A very simple *example* of a USB audio system using the core USB Audio function except with custom audio task (I2S)
*
* It uses the XUA_WRAPPER API along with either master or slave from lib_i2s
*
* - 4 channels in/out I2S
* - 44.1 -> 192 kHz
*
*/

#include <xs1.h>
#include <platform.h>

#include "xua.h"
#include "xud_device.h"
#include "xk_audio_316_mc_ab/board.h"

#undef I2S_CHANS_PER_FRAME // avoid repeat define warning from I2S (defined in XUA too)
#define I2S_DATA_BITS 32
#include "i2s.h"
#include "debug_print.h"

/* Port declarations. Note, the defines come from the xn file */
buffered out port:32 p_i2s_dac[] = {PORT_I2S_DAC0, PORT_I2S_DAC1}; /* I2S Data-line(s) */
buffered in port:32 p_i2s_adc[] = {PORT_I2S_ADC0, PORT_I2S_ADC1}; /* I2S Data-line(s) */
#if I2S_MASTER
buffered out port:32 p_lrclk = PORT_I2S_LRCLK; /* I2S LR-clock */
out port p_bclk = PORT_I2S_BCLK; /* I2S Bit-clock */
#else
buffered in port:32 p_lrclk = PORT_I2S_LRCLK; /* I2S LR-clock */
in port p_bclk = PORT_I2S_BCLK; /* I2S Bit-clock */
#endif

/* Master clock for the audio IO tile */
in port p_mclk_in = PORT_MCLK_IN;

/* Resources for USB feedback */
in port p_for_mclk_count = on tile[XUD_TILE]: XS1_PORT_16B;
in port p_mclk_in_usb = PORT_MCLK_IN_USB; /* Extra master clock input for the USB tile */

/* Clock-block declarations */
clock clk_audio_bclk = on tile[AUDIO_IO_TILE]: XS1_CLKBLK_2; /* Bit clock */
clock clk_audio_mclk = on tile[AUDIO_IO_TILE]: XS1_CLKBLK_3; /* Master clock */
clock clk_audio_mclk_usb = on tile[XUD_TILE]: XS1_CLKBLK_1; /* Master clock for USB tile */


/* Board configuration from lib_board_support */
static const xk_audio_316_mc_ab_config_t hw_config = {
CLK_FIXED, // clk_mode. Drive a fixed MCLK output
#if I2S_MASTER
0, // 0 = dac_is_clock_slave
#else
1, // 1 = dac_is_clock_master
#endif
DEFAULT_MCLK,
0, // pll_sync_freq (unused when driving fixed clock)
AUD_316_PCM_FORMAT_I2S,
I2S_DATA_BITS, // data bits
I2S_CHANS_PER_FRAME // channels per frame
};


[[distributable]]
void i2s_callback_handler(server i2s_frame_callback_if i_i2s, chanend c_aud, client interface i2c_master_if i_i2c_client) {

int32_t samples_to_host[NUM_USB_CHAN_IN] = {0};
int32_t samples_from_host[NUM_USB_CHAN_OUT] = {0};

unsafe {
while(!(unsigned) i_i2c_client); // Wait for valid interface
xk_audio_316_mc_ab_AudioHwInit(i_i2c_client, hw_config);
}

while (1) {
select {
case i_i2s.init(i2s_config_t &?i2s_config, tdm_config_t &?tdm_config):
unsigned curSamRes_DAC, curSamRes_ADC, mClk, curSamFreq;
XUA_wrapper_get_stream_format(&curSamFreq, &mClk, &curSamRes_DAC, &curSamRes_ADC);
i2s_config.mode = I2S_MODE_I2S;
i2s_config.mclk_bclk_ratio = mClk / (curSamFreq * I2S_CHANS_PER_FRAME * I2S_DATA_BITS);
i2s_config.slave_bclk_polarity == I2S_SLAVE_SAMPLE_ON_BCLK_RISING; // Has no effect for master
unsafe {
xk_audio_316_mc_ab_AudioHwConfig(i_i2c_client, hw_config, curSamFreq, mClk, 0, curSamRes_DAC, curSamRes_ADC);
}
debug_printf("Sample rate: %u mClk: %u\n", curSamFreq, mClk);
break;

case i_i2s.restart_check() -> i2s_restart_t restart:
int format_change = XUA_wrapper_exchange_samples(c_aud, samples_to_host, samples_from_host);
if(format_change){
restart = I2S_RESTART;
} else {
restart = I2S_NO_RESTART;
}
break;

case i_i2s.receive(size_t num_in, int32_t samples[num_in]):
// Handle a received sample from I2S
for(int i = 0; i < num_in; i++){
samples_to_host[i] = samples[i]; // copy to USB inbound buffer
}
break;

case i_i2s.send(size_t num_out, int32_t samples[num_out]):
// Provide a sample to send to I2S output
for(int i = 0; i < num_out; i++){
samples[i] = samples_from_host[i];
}
break;
}
}
}


int main()
{
/* Channel for audio data between buffering cores and AudioHub/IO core */
chan c_aud;

/* Interface for access to I2C for setting up hardware */
interface i2c_master_if i_i2c[1];

par {

/* handles XUD, audio data to/from EP's and gives/gets data to/from the audio I/O core */
/* Note, this spawns four cores. This must be configured using xua_conf.h */
on tile[XUD_TILE]:
{
XUA_wrapper_task(c_aud);
}

/* I2S Audiohub */
on tile[AUDIO_IO_TILE]:
{
i2s_frame_callback_if i_i2s;
par
{
#if I2S_MASTER
i2s_frame_master(i_i2s, p_i2s_dac, NUM_USB_CHAN_OUT / 2, p_i2s_adc, NUM_USB_CHAN_IN / 2, I2S_DATA_BITS, p_bclk, p_lrclk, p_mclk_in, clk_audio_bclk);
#else
i2s_frame_slave(i_i2s, p_i2s_dac, NUM_USB_CHAN_OUT / 2, p_i2s_adc, NUM_USB_CHAN_IN / 2, I2S_DATA_BITS, p_bclk, p_lrclk, clk_audio_bclk);
#endif
[[distribute]]
i2s_callback_handler(i_i2s, c_aud, i_i2c[0]);
}
}

on tile[0]:
{
xk_audio_316_mc_ab_board_setup(hw_config);
xk_audio_316_mc_ab_i2c_master(i_i2c);
}
}

return 0;
}
93 changes: 93 additions & 0 deletions examples/app_lib_i2s_wrapper/src/xk-audio-316-mc.xn
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
<Type>Board</Type>
<Name>xcore.ai MC Audio Board</Name>

<Declarations>
<Declaration>tileref tile[2]</Declaration>
</Declarations>

<Packages>
<Package id="0" Type="XS3-UnA-1024-TQ128">
<Nodes>
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" ReferenceFrequency="100MHz">
<Boot>
<Source Location="bootFlash"/>
</Boot>
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>

<!-- Various ctrl signals -->
<Port Location="XS1_PORT_8D" Name="PORT_CTRL"/>

<!-- I2C -->
<Port Location="XS1_PORT_1L" Name="PORT_I2C_SCL"/>
<Port Location="XS1_PORT_1M" Name="PORT_I2C_SDA"/>

<!-- Clocking -->
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN_USB"/>
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>

<!-- Audio Ports: Digital -->
<Port Location="XS1_PORT_1O" Name="PORT_ADAT_IN"/> <!-- N: Coax O: Optical -->
<Port Location="XS1_PORT_1N" Name="PORT_SPDIF_IN"/> <!-- N: Coax O: Optical -->

</Tile>
<Tile Number="1" Reference="tile[1]">
<!-- Audio Ports: I2S -->
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN"/>
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT_2"/>
<Port Location="XS1_PORT_1B" Name="PORT_I2S_LRCLK"/>
<Port Location="XS1_PORT_1C" Name="PORT_I2S_BCLK"/>
<Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC0"/>
<port Location="XS1_PORT_1O" Name="PORT_I2S_DAC1"/>
<port Location="XS1_PORT_1N" Name="PORT_I2S_DAC2"/>
<port Location="XS1_PORT_1M" Name="PORT_I2S_DAC3"/>
<Port Location="XS1_PORT_1I" Name="PORT_I2S_ADC0"/>
<Port Location="XS1_PORT_1J" Name="PORT_I2S_ADC1"/>
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC2"/>
<Port Location="XS1_PORT_1L" Name="PORT_I2S_ADC3"/>

<!-- Audio Ports: Digital -->
<Port Location="XS1_PORT_1G" Name="PORT_ADAT_OUT"/> <!-- A: Coax G: Optical -->
<Port Location="XS1_PORT_1A" Name="PORT_SPDIF_OUT"/> <!-- A: Coax G: Optical -->

<!-- MIDI -->
<Port Location="XS1_PORT_1F" Name="PORT_MIDI_IN"/>
<Port Location="XS1_PORT_4C" Name="PORT_MIDI_OUT"/> <!-- bit[0] -->

</Tile>
</Node>
</Nodes>
</Package>
</Packages>
<Nodes>
<Node Id="2" Type="device:" RoutingId="0x8000">
<Service Id="0" Proto="xscope_host_data(chanend c);">
<Chanend Identifier="c" end="3"/>
</Service>
</Node>
</Nodes>
<Links>
<Link Encoding="2wire" Delays="5clk" Flags="XSCOPE">
<LinkEndpoint NodeId="0" Link="XL0"/>
<LinkEndpoint NodeId="2" Chanend="1"/>
</Link>
</Links>
<ExternalDevices>
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" PageSize="256" SectorSize="4096" NumPages="16384">
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
</Device>
</ExternalDevices>
<JTAGChain>
<JTAGDevice NodeId="0"/>
</JTAGChain>

</Network>
25 changes: 25 additions & 0 deletions examples/app_lib_i2s_wrapper/src/xua_conf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2017-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#ifndef _XUA_CONF_H_
#define _XUA_CONF_H_

#define NUM_USB_CHAN_OUT 4 /* Number of channels from host to device */
#define NUM_USB_CHAN_IN 4 /* Number of channels from device to host */
#define MCLK_441 (512 * 44100) /* 44.1kHz family master clock frequency */
#define MCLK_48 (512 * 48000) /* 48kHz family master clock frequency */
#define MIN_FREQ 44100 /* Minimum sample rate */
#define MAX_FREQ 192000 /* Maximum sample rate */

#define EXCLUDE_USB_AUDIO_MAIN /* Use our own main function */
#define XUA_WRAPPER 1 /* Just use the USB host side tasks, use own audio function */

#define VENDOR_STR "XMOS"
#define VENDOR_ID 0x20B1
#define PRODUCT_STR_A2 "XUA Wrapper Example"
#define PRODUCT_STR_A1 "XUA Wrapper Example"
#define PID_AUDIO_1 1
#define PID_AUDIO_2 2
#define XUA_DFU_EN 0 /* Disable DFU (for simplicity of example */

#endif
1 change: 1 addition & 0 deletions lib_xua/api/xua.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "xua_endpoint0.h"
#include "xua_buffer.h"
#include "xua_mixer.h"
#include "xua_wrapper.h"
#endif

#ifdef __XC__
Expand Down
17 changes: 17 additions & 0 deletions lib_xua/api/xua_conf_default.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/*
* @brief Defines relating to device configuration and customisation of lib_xua
*/

#ifndef _XUA_CONF_DEFAULT_H_
#define _XUA_CONF_DEFAULT_H_

Expand Down Expand Up @@ -85,6 +86,22 @@
#define XUA_NUM_PDM_MICS (0)
#endif

/**
* @brief Enable API for wrapping the USB host and buffering (without audio)
*
* When enabled, an API in xua_wrapper.h is enabled
*/

#ifndef XUA_WRAPPER
#define XUA_WRAPPER 0
#endif

#if XUA_WRAPPER
#define I2S_CHANS_DAC 0 /* We are not using audiohub */
#define I2S_CHANS_ADC 0
#endif /* XUA_WRAPPER */


/**
* @brief Number of DSD output channels.
*
Expand Down
Loading