From 17944ad908866aaaf5c4e599fc902c1e1b071273 Mon Sep 17 00:00:00 2001 From: Brennan Magee Date: Tue, 30 May 2023 17:08:32 +0100 Subject: [PATCH 01/12] Use bat not sh for windows builds on Jenkins This was causing an issue where the windows workspaces could not be cleared. --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d37e570e..138f9ffd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -153,8 +153,8 @@ pipeline { withVS() { bat 'msbuild host_usb_mixer_control.vcxproj /property:Configuration=Release /property:Platform=x64' } - sh 'mkdir Win/x64' - sh 'mv bin/Release/x64/host_usb_mixer_control.exe Win/x64/xmos_mixer.exe' + bat 'mkdir Win\\x64' + bat 'mv bin/Release/x64/host_usb_mixer_control.exe Win/x64/xmos_mixer.exe' archiveArtifacts artifacts: "Win/x64/xmos_mixer.exe", fingerprint: true } } From 1ef5129fdeef0c71fa747c6877d09a838e328c47 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 8 Jun 2023 15:31:12 +0100 Subject: [PATCH 02/12] Variable i2s bit width (#331) - Add support for variable width I2S (via XUA_I2S_N_BITS) - Add support for variable width TDM (again via XUD_I2S_N_BITS when XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM) - Includes support for xcore as I2S/TDM master and slave - Add testing of the the above to test_i2s_loopback - Rationalised test config building in test_i2s_loopback - Documentation updated --- CHANGELOG.rst | 3 +- lib_xua/api/xua_conf_default.h | 19 ++- lib_xua/doc/rst/api_defines.rst | 9 ++ lib_xua/doc/rst/opt_i2s.rst | 19 ++- lib_xua/doc/rst/opt_location.rst | 2 +- lib_xua/doc/rst/overview.rst | 2 +- lib_xua/doc/rst/using_adv_i2s.rst | 4 +- lib_xua/module_build_info | 2 +- .../src/core/audiohub/audiohub_initport.xc | 46 ++++-- lib_xua/src/core/audiohub/xua_audiohub.xc | 120 ++++++++++----- lib_xua/src/core/ports/audioports.xc | 2 +- lib_xua/src/core/warnings.xc | 4 +- tests/test_i2s_loopback.py | 25 +-- tests/test_i2s_loopback/Makefile | 144 ++++-------------- tests/test_i2s_loopback/main.xc | 11 +- tests/test_i2s_loopback/simulation.xc | 5 +- 16 files changed, 221 insertions(+), 196 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d95b28c8..65af1b55 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,9 +4,10 @@ lib_xua Change Log UNRELEASED ---------- + * ADDED: Configurable word-length for I2S/TDM via XUA_I2S_N_BITS * FIXED: Memory corruption due to erroneous initialisation of mixer weights when not in use (#152) * FIXED: UserHostActive() not being called as expected (#326) - * FIXED: Exception when entering DSD mode + * FIXED: Exception when entering DSD mode (#327) 3.4.0 ----- diff --git a/lib_xua/api/xua_conf_default.h b/lib_xua/api/xua_conf_default.h index 8b6242cd..ee3bc85f 100644 --- a/lib_xua/api/xua_conf_default.h +++ b/lib_xua/api/xua_conf_default.h @@ -93,7 +93,11 @@ #define XUA_PCM_FORMAT_I2S (0) #define XUA_PCM_FORMAT_TDM (1) - +/** + * @brief Format of PCM audio interface. Should be set to XUA_PCM_FORMAT_I2S or XUA_PCM_FORMAT_TDM + * + * Default: XUA_PCM_FORMAT_I2S + */ #ifdef XUA_PCM_FORMAT #if (XUA_PCM_FORMAT != XUA_PCM_FORMAT_I2S) && (XUA_PCM_FORMAT != XUA_PCM_FORMAT_TDM) #error Bad value for XUA_PCM_FORMAT @@ -193,6 +197,19 @@ #define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC #endif +/** + * @brief Number of bits per channel for I2S/TDM. Supported values: 16/32-bit. + * + * Default: 32 bits + */ +#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 */ diff --git a/lib_xua/doc/rst/api_defines.rst b/lib_xua/doc/rst/api_defines.rst index 76904020..a67b08fd 100644 --- a/lib_xua/doc/rst/api_defines.rst +++ b/lib_xua/doc/rst/api_defines.rst @@ -50,6 +50,15 @@ Audio Class Feature Configuration --------------------- +I2S/TDM +^^^^^^^ + +.. doxygendefine:: I2S_CHANS_DAC +.. doxygendefine:: I2S_CHANS_ADC +.. doxygendefine:: CODEC_MASTER +.. doxygendefine:: XUA_I2S_N_BITS +.. doxygendefine:: XUA_PCM_FORMAT + MIDI ^^^^ diff --git a/lib_xua/doc/rst/opt_i2s.rst b/lib_xua/doc/rst/opt_i2s.rst index 681626d9..005030b0 100644 --- a/lib_xua/doc/rst/opt_i2s.rst +++ b/lib_xua/doc/rst/opt_i2s.rst @@ -23,11 +23,14 @@ The defines in :ref:`opt_i2s_defines` effect the I2S implementation. - The desired number of input channels via I2S (0 for disabled) - N/A (Must be defined) * - ``XUA_PCM_FORMAT`` - - Enabled either TDM or I2S mode + - Enables either TDM or I2S mode - ``XUA_PCM_FORMAT_I2S`` * - ``CODEC_MASTER`` - - Sets is xCORE is I2S master or slave + - Sets if xCORE is I2S master or slave - ``0`` (xCORE is master) + * - ``XUA_I2S_N_BITS`` + - I2S/TDM word length (16, 32-bit supported) + - ``32`` The I2S code expects that the ports required for I2S (master clock, LR-clock, bit-clock and data lines) are be defined in the application XN file in the relevant `Tile``. For example:: @@ -42,8 +45,16 @@ For example:: -All of the I2S related ports must be 1-bit ports. +All of the I2S/TDM related ports must be 1-bit ports. .. note:: - TDM mode allows 8 channels (rather than 2) to be supplied on each dataline. + TDM mode allows 8 channels (rather than 2) to be supplied on each data-line. + +.. note:: + + Data output/input is in "I2S" format, rather than, say "left-justified" or "right-justified" formats. + I2S format specifies a single bit-clock delay after the LR-clock transition before sample-data is driven/received. + This also applies to TDM mode. TDM support in ADC/DAC hardware is quite varied, an "offset" value may need to be programmed into + the external device for compatible operation. + diff --git a/lib_xua/doc/rst/opt_location.rst b/lib_xua/doc/rst/opt_location.rst index 45a5d1ee..0f3b210b 100644 --- a/lib_xua/doc/rst/opt_location.rst +++ b/lib_xua/doc/rst/opt_location.rst @@ -21,7 +21,7 @@ full listing of these ``TILE`` defines. - Description - Default * - ``AUDIO_IO_TILE`` - - Tile on which I2S, ADAT Rx, S/PDIF Rx & mixer resides + - Tile on which I2S/TDM, ADAT Rx, S/PDIF Rx & mixer resides - ``0`` * - ``XUD_TILE`` - Tile on which USB resides, including buffering for all USB interfaces/endppoints diff --git a/lib_xua/doc/rst/overview.rst b/lib_xua/doc/rst/overview.rst index 8be7bae7..c52db86a 100644 --- a/lib_xua/doc/rst/overview.rst +++ b/lib_xua/doc/rst/overview.rst @@ -25,7 +25,7 @@ Overview | +---------------------------------------------------------------------------------------------+ | | `USB Midi Device Class 1.0 `_ | +---------------------------------+---------------------------------------------------------------------------------------------+ - | Audio | I2S/TDM | + | Audio | I2S/TDM (16/32-bit) | | +---------------------------------------------------------------------------------------------+ | | S/PDIF | | +---------------------------------------------------------------------------------------------+ diff --git a/lib_xua/doc/rst/using_adv_i2s.rst b/lib_xua/doc/rst/using_adv_i2s.rst index 12d5029c..89dd025c 100644 --- a/lib_xua/doc/rst/using_adv_i2s.rst +++ b/lib_xua/doc/rst/using_adv_i2s.rst @@ -5,7 +5,7 @@ I2S/TDM I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core. -In order to enable I2S on must declare an array of ports for the data-lines (one for each direction):: +In order to enable I2S/TDM on must declare an array of ports for the data-lines (one for each direction):: /* Port declarations. Note, the defines come from the XN file */ buffered out port:32 p_i2s_dac[] = {PORT_I2S_DAC0}; /* I2S Data-line(s) */ @@ -22,7 +22,7 @@ Ports for the sample and bit clocks are also required:: These ports must then be passed to the ``XUA_AudioHub()`` task appropriately. -I2S functionality also requires two clock-blocks, one for bit and sample clock e.g.:: +I2S/TDM functionality also requires two clock-blocks, one for bit-clock and another for the master clock e.g.:: /* Clock-block declarations */ clock clk_audio_bclk = on tile[0]: XS1_CLKBLK_4; /* Bit clock */ diff --git a/lib_xua/module_build_info b/lib_xua/module_build_info index b95b65f6..7c50052b 100644 --- a/lib_xua/module_build_info +++ b/lib_xua/module_build_info @@ -11,7 +11,7 @@ endif DEPENDENT_MODULES = lib_locks(>=2.1.0) \ lib_logging(>=3.1.1) \ lib_mic_array(>=4.5.0) \ - lib_spdif(>=4.2.1) \ + lib_spdif(>=5.0.0) \ lib_xassert(>=4.1.0) \ lib_xud(>=2.2.3) \ lib_adat(>=1.0.0) diff --git a/lib_xua/src/core/audiohub/audiohub_initport.xc b/lib_xua/src/core/audiohub/audiohub_initport.xc index cb3e7d2b..61ab6324 100644 --- a/lib_xua/src/core/audiohub/audiohub_initport.xc +++ b/lib_xua/src/core/audiohub/audiohub_initport.xc @@ -1,7 +1,6 @@ -// Copyright 2018-2022 XMOS LIMITED. +// Copyright 2018-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include "xua.h" - #include "dsd_support.h" #if (DSD_CHANS_DAC != 0) @@ -12,7 +11,7 @@ extern buffered out port:32 p_dsd_clk; extern unsigned dsdMode; #if !CODEC_MASTER -void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]) +void InitPorts_master(buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]) { #if (DSD_CHANS_DAC > 0) if(dsdMode == DSD_MODE_OFF) @@ -39,7 +38,12 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu #endif unsigned tmp; - p_lrclk <: 0 @ tmp; + + if(XUA_I2S_N_BITS == 32) + p_lrclk <: 0 @ tmp; + else + tmp = partout_timestamped(p_lrclk, XUA_I2S_N_BITS, 0); + tmp += 100; /* Since BCLK is free-running, setup outputs/inputs at a known point in the future */ @@ -47,19 +51,30 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu #pragma loop unroll for(int i = 0; i < I2S_WIRES_DAC; i++) { - p_i2s_dac[i] @ tmp <: 0; + if(XUA_I2S_N_BITS == 32) + p_i2s_dac[i] @ tmp <: 0; + else + partout_timed(p_i2s_dac[i], XUA_I2S_N_BITS, 0, tmp); } #endif - + unsigned lrClkVal = 0x7FFFFFFF; if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM) - p_lrclk @ tmp <: 0x80000000; + { + lrClkVal = 0x80000000; + } + + if(XUA_I2S_N_BITS == 32) + p_lrclk @ tmp <: lrClkVal; else - p_lrclk @ tmp <: 0x7FFFFFFF; + partout_timed(p_lrclk, XUA_I2S_N_BITS, lrClkVal, tmp); #if (I2S_CHANS_ADC != 0) for(int i = 0; i < I2S_WIRES_ADC; i++) { asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1)); + + if(XUA_I2S_N_BITS != 32) + set_port_shift_count(p_i2s_adc[i], XUA_I2S_N_BITS); } #endif #endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */ @@ -75,7 +90,7 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu #endif } #else -void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]) +void InitPorts_slave(buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]) { #if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) unsigned tmp; @@ -92,7 +107,7 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf p_lrclk when pinseq(0) :> void @ tmp; #endif - tmp += (I2S_CHANS_PER_FRAME * 32) - 32 + 1 ; + tmp += ((I2S_CHANS_PER_FRAME * XUA_I2S_N_BITS) - XUA_I2S_N_BITS + 1) ; /* E.g. 2 * 32 - 32 + 1 = 33 for stereo */ /* E.g. 8 * 32 - 32 + 1 = 225 for 8 chan TDM */ @@ -100,7 +115,10 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf #pragma loop unroll for(int i = 0; i < I2S_WIRES_DAC; i++) { - p_i2s_dac[i] @ tmp <: 0; + if(XUA_I2S_N_BITS == 32) + p_i2s_dac[i] @ tmp <: 0; + else + partout_timed(p_i2s_dac[i], XUA_I2S_N_BITS, 0, tmp); } #endif @@ -108,11 +126,15 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf #pragma loop unroll for(int i = 0; i < I2S_WIRES_ADC; i++) { - asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1)); + asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1)); + if(XUA_I2S_N_BITS != 32) + set_port_shift_count(p_i2s_adc[i], XUA_I2S_N_BITS); } #endif asm("setpt res[%0], %1"::"r"(p_lrclk),"r"(tmp-1)); + if(XUA_I2S_N_BITS != 32) + set_port_shift_count(p_lrclk, XUA_I2S_N_BITS); #endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */ } #endif diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 76229899..e50cee24 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -15,6 +15,8 @@ #include #include #include +#include + #include "xua.h" @@ -50,19 +52,6 @@ unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)]; unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)]; -#ifdef XTA_TIMING_AUDIO -#pragma xta command "add exclusion received_command" -#pragma xta command "analyse path i2s_output_l i2s_output_r" -#pragma xta command "set required - 2000 ns" - -#pragma xta command "add exclusion received_command" -#pragma xta command "add exclusion received_underflow" -#pragma xta command "add exclusion divide_1" -#pragma xta command "add exclusion deliver_return" -#pragma xta command "analyse path i2s_output_r i2s_output_l" -#pragma xta command "set required - 2000 ns" -#endif - #if (XUA_ADAT_TX_EN) extern buffered out port:32 p_adat_tx; #endif @@ -76,7 +65,7 @@ void InitPorts_slave #else void InitPorts_master #endif -(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], +(buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]); @@ -96,7 +85,17 @@ static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:3 #if CODEC_MASTER unsigned syncError = 0; unsigned lrval = 0; - p_lrclk :> lrval; + const unsigned lrval_mask = (0xffffffff << (32 - XUA_I2S_N_BITS)); + + if(XUA_I2S_N_BITS != 32) + { + asm volatile("in %0, res[%1]":"=r"(lrval):"r"(p_lrclk):"memory"); + set_port_shift_count(p_lrclk, XUA_I2S_N_BITS); + } + else + { + p_lrclk :> lrval; + } if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM) { @@ -114,30 +113,46 @@ static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:3 } else { - if(frameCount == 0) - syncError += (lrval != 0x80000000); + if(XUA_I2S_N_BITS == 32) + { + if(frameCount == 0) + syncError = (lrval != 0x80000000); + else + syncError = (lrval != 0x7FFFFFFF); + } else - syncError += (lrval != 0x7FFFFFFF); + { + if(frameCount == 0) + syncError = ((lrval & lrval_mask) != 0x80000000); + else + syncError = ((lrval | (~lrval_mask)) != 0x7FFFFFFF); + } } return syncError; #else + unsigned clkVal; if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM) { if(frameCount == (I2S_CHANS_PER_FRAME-1)) - p_lrclk <: 0x80000000; + clkVal = 0x80000000; else - p_lrclk <: 0x00000000; + clkVal = 0x00000000; } else { if(frameCount == 0) - p_lrclk <: 0x80000000; + clkVal = 0x80000000; else - p_lrclk <: 0x7fffffff; + clkVal = 0x7fffffff; } + if(XUA_I2S_N_BITS == 32) + p_lrclk <: clkVal; + else + partout(p_lrclk, XUA_I2S_N_BITS, clkVal >> (32 - XUA_I2S_N_BITS)); + return 0; #endif @@ -254,9 +269,9 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out if ((I2S_CHANS_DAC > 0 || I2S_CHANS_ADC > 0)) { #if CODEC_MASTER - InitPorts_slave(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); + InitPorts_slave(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); #else - InitPorts_master(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); + InitPorts_master(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); #endif } @@ -290,9 +305,17 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out // p_i2s_adc[index++] :> sample; // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) unsigned sample; - asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index])); + sample = bitrev(sample); - int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line. + if(XUA_I2S_N_BITS != 32) + { + set_port_shift_count(p_i2s_adc[index], XUA_I2S_N_BITS); + sample <<= (32 - XUA_I2S_N_BITS); + } + index++; + + int chanIndex = ((frameCount-2) & (I2S_CHANS_PER_FRAME-1)) + i; // channels 0, 2, 4.. on each line. #if (AUD_TO_USB_RATIO > 1) if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) @@ -344,7 +367,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); } #endif /* (AUD_TO_USB_RATIO > 1) */ - p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]); + 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])); } #endif // (I2S_CHANS_DAC != 0) @@ -417,8 +443,15 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out { /* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */ unsigned sample; - asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index])); sample = bitrev(sample); + if(XUA_I2S_N_BITS != 32) + { + set_port_shift_count(p_i2s_adc[index], XUA_I2S_N_BITS); + sample <<= (32 - XUA_I2S_N_BITS); + } + index++; + int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line. #if (AUD_TO_USB_RATIO > 1 && !I2S_DOWNSAMPLE_MONO_IN) if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) @@ -450,7 +483,6 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out #endif index = 0; -#pragma xta endpoint "i2s_output_r" #if (I2S_CHANS_DAC != 0) /* Output "odd" channel to DAC (i.e. right) */ #pragma loop unroll @@ -469,7 +501,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); } #endif /* (AUD_TO_USB_RATIO > 1) */ - p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]); + 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])); } #endif // (I2S_CHANS_DAC != 0) @@ -523,7 +558,6 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out } } } -#pragma xta endpoint "deliver_return" return 0; } @@ -681,13 +715,13 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, /* Calculate master clock to bit clock (or DSD clock) divide for current sample freq * e.g. 11.289600 / (176400 * 64) = 1 */ { -#if (XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM) - /* I2S has 32 bits per sample. *8 as 8 channels */ - unsigned numBits = 256; -#else - /* I2S has 32 bits per sample. *2 as 2 channels */ - unsigned numBits = 64; -#endif + unsigned numBits = XUA_I2S_N_BITS * 2; + + if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM) + { + /* TDM has 8 channels */ + numBits *= 4; + } #if (DSD_CHANS_DAC > 0) if(dsdMode == DSD_MODE_DOP) @@ -703,7 +737,15 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, #endif divide = mClk / (curSamFreq * numBits); - /* TODO; we should catch and handle the case when divide is 0. Currently design will lock up */ + //Do some checks + xassert((divide > 0) && "Error: divider is 0, BCLK rate unachievable"); + + unsigned remainder = mClk % ( curSamFreq * numBits); + xassert((!remainder) && "Error: MCLK not divisible into BCLK by an integer number"); + + unsigned divider_is_odd = divide & 0x1; + xassert((!divider_is_odd) && "Error: divider is odd, clockblock cannot produce desired BCLK"); + } #if (DSD_CHANS_DAC > 0) diff --git a/lib_xua/src/core/ports/audioports.xc b/lib_xua/src/core/ports/audioports.xc index 10fd328f..fac58cbc 100644 --- a/lib_xua/src/core/ports/audioports.xc +++ b/lib_xua/src/core/ports/audioports.xc @@ -100,7 +100,7 @@ void ConfigAudioPorts( /* Do some clocking shifting to get data in the valid window */ /* E.g. Only shift when running at 88.2+ kHz TDM slave */ int bClkDelay_fall = 0; - if(curSamFreq * I2S_CHANS_PER_FRAME * 32 >= 20000000) + if(curSamFreq * I2S_CHANS_PER_FRAME * XUA_I2S_N_BITS >= 20000000) { /* 18 * 2ns = 36ns. This results in a -4ns (36 - 40) shift at 96KHz and -8ns (36 - 44) at 88.4KHz */ bClkDelay_fall = 18; diff --git a/lib_xua/src/core/warnings.xc b/lib_xua/src/core/warnings.xc index 16ffc49e..1a8fadd5 100644 --- a/lib_xua/src/core/warnings.xc +++ b/lib_xua/src/core/warnings.xc @@ -1,8 +1,8 @@ -// Copyright 2013-2021 XMOS LIMITED. +// Copyright 2013-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. /* -Warnings relating to configuration defines located in this XC source file rather than the devicedefines.h header file in order to avoid multiple warnings being issued when the devicedefines.h header file is included in multiple files. +Warnings relating to configuration defines located in this XC source file rather than the xua_conf.h header file in order to avoid multiple warnings being issued when the xua_conf.h header file is included in multiple files. */ #include "xua_conf_full.h" diff --git a/tests/test_i2s_loopback.py b/tests/test_i2s_loopback.py index c824a355..fdf67bae 100644 --- a/tests/test_i2s_loopback.py +++ b/tests/test_i2s_loopback.py @@ -1,4 +1,4 @@ -# Copyright 2018-2022 XMOS LIMITED. +# Copyright 2018-2023 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. import pytest import Pyxsim @@ -11,16 +11,21 @@ import sys def test_file(request): return str(request.node.fspath) - def do_test( - pcm_format, i2s_role, channel_count, sample_rate, test_file, options, capfd + pcm_format, i2s_role, channel_count, sample_rate, word_length, test_file, options, capfd ): build_options = [] output = [] testname, _ = os.path.splitext(os.path.basename(test_file)) - desc = f"simulation_{pcm_format}_{i2s_role}_{channel_count}in_{channel_count}out_{sample_rate}" + build_options += [f"pcm_format={pcm_format}"] + build_options += [f"i2s_role={i2s_role}"] + build_options += [f"channel_count={channel_count}"] + build_options += [f"sample_rate={sample_rate}"] + build_options += [f"word_length={word_length}"] + + desc = f"simulation_{pcm_format}_{i2s_role}_{channel_count}in_{channel_count}out_{sample_rate}_{word_length}bit" binary = f"{testname}/bin/{desc}/{testname}_{desc}.xe" tester = testers.ComparisonTester(open("pass.expect")) @@ -52,6 +57,7 @@ def do_test( result = Pyxsim.run_on_simulator( binary, + build_options=build_options, tester=tester, simargs=simargs, capfd=capfd, @@ -65,25 +71,26 @@ def do_test( @pytest.mark.parametrize("i2s_role", ["master", "slave"]) @pytest.mark.parametrize("pcm_format", ["i2s", "tdm"]) @pytest.mark.parametrize("channel_count", [2, 8, 16]) -@pytest.mark.parametrize("sample_rate", ["48khz", "96khz", "192khz"]) +@pytest.mark.parametrize("word_length", [16, 32]) # I2S world length in bits +@pytest.mark.parametrize("sample_rate", [48000, 96000, 192000]) def test_i2s_loopback( - i2s_role, pcm_format, channel_count, sample_rate, test_file, options, capfd + i2s_role, pcm_format, channel_count, sample_rate, word_length, test_file, options, capfd ): if pcm_format == "i2s" and channel_count == 16: pytest.skip("Invalid parameter combination") - if pcm_format == "i2s" and sample_rate not in ["48khz", "192khz"]: + if pcm_format == "i2s" and sample_rate not in [48000, 192000]: pytest.skip("Invalid parameter combination") if pcm_format == "tdm" and channel_count == 2: pytest.skip("Invalid parameter combination") - if pcm_format == "tdm" and sample_rate == "192khz": + if pcm_format == "tdm" and sample_rate == 192000: pytest.skip("Invalid parameter combination") result = do_test( - pcm_format, i2s_role, channel_count, sample_rate, test_file, options, capfd + pcm_format, i2s_role, channel_count, sample_rate, word_length, test_file, options, capfd ) assert result diff --git a/tests/test_i2s_loopback/Makefile b/tests/test_i2s_loopback/Makefile index 32615bb1..87a4b96c 100644 --- a/tests/test_i2s_loopback/Makefile +++ b/tests/test_i2s_loopback/Makefile @@ -1,126 +1,44 @@ TARGET = xk-audio-216-mc.xn USED_MODULES = lib_xua lib_i2c lib_logging -BUILD_FLAGS = -O0 -g -lflash -DXUD_CORE_CLOCK=600 -fxscope -save-temps -march=xs2a -DUSB_TILE=tile[1] +BUILD_FLAGS = -O3 -g -lflash -DXUD_CORE_CLOCK=600 -fxscope -save-temps -march=xs2a -DUSB_TILE=tile[1] \ + -DXUA_ADAT_RX_EN=0 -DXUA_ADAT_TX_EN=0 -DXUA_SPDIF_RX_EN=0 -DXUA_SPDIF_TX_EN=0 -DMIDI=0 \ + -DSIMULATION=1 -BUILD_FLAGS_i2s_master_2in_2out_48khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \ - -D DEFAULT_FREQ=48000 +ifndef pcm_format +$(error pcm_format is not set) +endif -BUILD_FLAGS_i2s_slave_2in_2out_48khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \ - -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 +ifndef i2s_role +$(error i2s_role is not set) +endif -BUILD_FLAGS_i2s_master_2in_2out_192khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -D I2S_CHANS_ADC=2 -D I2S_CHANS_DAC=2 \ - -D DEFAULT_FREQ=192000 +ifndef channel_count +$(error channel_count is not set) +endif -BUILD_FLAGS_i2s_slave_2in_2out_192khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \ - -D DEFAULT_FREQ=192000 -DCODEC_MASTER=1 +ifndef sample_rate +$(error sample_rate is not set) +endif -BUILD_FLAGS_i2s_master_8in_8out_48khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=48000 +ifndef word_length +$(error word_length is not set) +endif -BUILD_FLAGS_i2s_slave_8in_8out_48khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 +ifeq ($(pcm_format),tdm) + BUILD_FLAGS += -DXUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM +endif +ifeq ($(i2s_role),slave) + BUILD_FLAGS += -DCODEC_MASTER=1 +endif -BUILD_FLAGS_i2s_master_8in_8out_192khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=192000 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_i2s_slave_8in_8out_192khz = $(BUILD_FLAGS) \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=192000 -DCODEC_MASTER=1 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_tdm_master_8in_8out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=48000 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_tdm_master_8in_8out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=96000 \ - -O3 # optimisations to meet timing - -BUILD_FLAGS_tdm_slave_8in_8out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_tdm_slave_8in_8out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ - -D DEFAULT_FREQ=96000 -DCODEC_MASTER=1 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_tdm_master_16in_16out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \ - -D DEFAULT_FREQ=48000 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_tdm_master_16in_16out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \ - -D DEFAULT_FREQ=96000 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_tdm_slave_16in_16out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \ - -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \ - -O2 # optimisations to meet timing - -BUILD_FLAGS_tdm_slave_16in_16out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \ - -D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \ - -D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \ - -D DEFAULT_FREQ=96000 -DCODEC_MASTER=1 \ - -O2 # optimisations to meet timing - - -#XCC_FLAGS_hardware_i2s_master_2in_2out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_48khz) -#XCC_FLAGS_hardware_i2s_master_2in_2out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_192khz) -#XCC_FLAGS_hardware_i2s_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_48khz) -#XCC_FLAGS_hardware_i2s_master_8in_8out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_192khz) -#XCC_FLAGS_hardware_tdm_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_tdm_master_8in_8out_48khz) - -XCC_FLAGS_simulation_i2s_master_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_48khz) -XCC_FLAGS_simulation_i2s_slave_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_48khz) - -XCC_FLAGS_simulation_i2s_master_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_192khz) -XCC_FLAGS_simulation_i2s_slave_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_192khz) - -XCC_FLAGS_simulation_i2s_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_48khz) -XCC_FLAGS_simulation_i2s_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_48khz) - -XCC_FLAGS_simulation_i2s_master_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_192khz) -XCC_FLAGS_simulation_i2s_slave_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_192khz) - -XCC_FLAGS_simulation_tdm_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_8in_8out_48khz) -XCC_FLAGS_simulation_tdm_master_8in_8out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_8in_8out_96khz) -XCC_FLAGS_simulation_tdm_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_8in_8out_48khz) -XCC_FLAGS_simulation_tdm_slave_8in_8out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_8in_8out_96khz) - -XCC_FLAGS_simulation_tdm_master_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_16in_16out_48khz) -XCC_FLAGS_simulation_tdm_master_16in_16out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_16in_16out_96khz) -XCC_FLAGS_simulation_tdm_slave_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_16in_16out_48khz) -XCC_FLAGS_simulation_tdm_slave_16in_16out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_16in_16out_96khz) +XCC_FLAGS_simulation_${pcm_format}_${i2s_role}_$(channel_count)in_$(channel_count)out_$(sample_rate)_$(word_length)bit = $(BUILD_FLAGS) \ + -DNUM_USB_CHAN_IN=${channel_count} \ + -DNUM_USB_CHAN_OUT=${channel_count} \ + -DI2S_CHANS_DAC=${channel_count} \ + -DI2S_CHANS_ADC=${channel_count} \ + -DDEFAULT_FREQ=${sample_rate} \ + -DXUA_I2S_N_BITS=${word_length} XMOS_MAKE_PATH ?= ../.. -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/test_i2s_loopback/main.xc b/tests/test_i2s_loopback/main.xc index a98bc9ec..de36129f 100644 --- a/tests/test_i2s_loopback/main.xc +++ b/tests/test_i2s_loopback/main.xc @@ -1,4 +1,4 @@ -// Copyright 2016-2022 XMOS LIMITED. +// Copyright 2016-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include #include @@ -9,7 +9,6 @@ #define DEBUG_UNIT MAIN #include "debug_print.h" - /* Port declarations. Note, the defines come from the xn file */ #if I2S_WIRES_DAC > 0 on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] = @@ -92,9 +91,10 @@ clock clk_audio_mclk = on tile[AUDIO_IO_TILE]: XS1_CLKBLK_2; /* #define TOTAL_TEST_FRAMES (5 * DEFAULT_FREQ) #endif -#define SAMPLE(frame_count, channel_num) (((frame_count) << 8) | ((channel_num) & 0xFF)) -#define SAMPLE_FRAME_NUM(test_word) ((test_word) >> 8) -#define SAMPLE_CHANNEL_NUM(test_word) ((test_word) & 0xFF) +#define SHIFT (16) /* Note, we shift samples up such that we can test down to 16bit I2S */ +#define SAMPLE(frame_count, channel_num) ((((frame_count) << 8) | ((channel_num) & 0xFF))<>SHIFT) >> 8) +#define SAMPLE_CHANNEL_NUM(test_word) ((test_word>>SHIFT) & 0xFF) void generator(chanend c_checker, chanend c_out) { @@ -105,7 +105,6 @@ void generator(chanend c_checker, chanend c_out) frame_count = 0; - while (1) { underflow_word = inuint(c_out); diff --git a/tests/test_i2s_loopback/simulation.xc b/tests/test_i2s_loopback/simulation.xc index 44513a04..9aafcf00 100644 --- a/tests/test_i2s_loopback/simulation.xc +++ b/tests/test_i2s_loopback/simulation.xc @@ -1,4 +1,4 @@ -// Copyright 2016-2022 XMOS LIMITED. +// Copyright 2016-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifdef SIMULATION @@ -41,7 +41,7 @@ extern out port p_lrclk_gen; extern clock clk_audio_lrclk_gen; void slave_mode_clk_setup(const unsigned samFreq, const unsigned chans_per_frame){ - const unsigned data_bits = 32; + const unsigned data_bits = XUA_I2S_N_BITS; const unsigned mclk_freq = 24576000; const unsigned mclk_bclk_ratio = mclk_freq / (chans_per_frame * samFreq * data_bits); @@ -61,5 +61,4 @@ void slave_mode_clk_setup(const unsigned samFreq, const unsigned chans_per_frame master_mode_clk_setup(); } #endif - #endif From 45e5ef770221860b0495a7eb8d4c548676e89304 Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Sat, 10 Jun 2023 18:07:25 +0100 Subject: [PATCH 03/12] Enabling a static HID report descriptor in addition to the built-in dynamically created one. This is required for AudioWeaver. This also enables the option of an OUT HID endpoint --- lib_xua/api/xua_conf_default.h | 39 +++- lib_xua/module_build_info | 2 +- lib_xua/src/core/buffer/ep/ep_buffer.xc | 10 +- lib_xua/src/core/endpoint0/descriptor_defs.h | 7 +- lib_xua/src/core/endpoint0/xua_endpoint0.c | 24 +- .../src/core/endpoint0/xua_ep0_descriptors.h | 17 +- lib_xua/src/core/main.xc | 218 +++++++----------- lib_xua/src/core/user/hid/user_hid.h | 2 +- lib_xua/src/hid/hid.xc | 2 +- lib_xua/src/hid/hid_report.c | 2 +- .../xua_hid_endpoint_descriptor_contents.h | 28 +++ .../xua_hid_interface_descriptor_contents.h | 3 +- 12 files changed, 200 insertions(+), 154 deletions(-) diff --git a/lib_xua/api/xua_conf_default.h b/lib_xua/api/xua_conf_default.h index 8b6242cd..d78457d3 100644 --- a/lib_xua/api/xua_conf_default.h +++ b/lib_xua/api/xua_conf_default.h @@ -431,6 +431,40 @@ #define HID_CONTROLS (0) #endif +/** + * HID may be required in two forms: the built-in XUA-HID reports, or a + * user-provided static HID. Some sections of code are always needed, they + * are enclosed in XUA_OR_STATIC_HID_ENABLED; code specific to XUA-HID + * reports are enclosed in XUA_HID_ENABLED. + * + * HID_CONTROLS implies that the XUA_HID is used, and hence defines both. + * In order to roll your own, do not enable HID_CONTROLS, but instead + * create a file static_hid_report.h that contains the static descriptor. + * + * You must also supply your own function to deal with the HID endpoint(s) + * in this case. + */ +#if( 0 < HID_CONTROLS ) +#define XUA_HID_ENABLED (1) +#define XUA_OR_STATIC_HID_ENABLED (1) +#endif + + +#if defined(__static_hid_report_h_exists__) +#define XUA_OR_STATIC_HID_ENABLED (1) +#endif + +/** + * @brief Enable a HID OUT endpoint. Only use this if you supply your own HID control. + * + * 1 for enabled, 0 for disabled. + * + * Default 0 (Disabled) + */ +#ifndef HID_OUT_REQUIRED +#define HID_OUT_REQUIRED (0) +#endif + /** * @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks) * @@ -1146,7 +1180,7 @@ enum USBEndpointNumber_In #ifdef MIDI ENDPOINT_NUMBER_IN_MIDI, #endif -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED ENDPOINT_NUMBER_IN_HID, #endif #ifdef IAP @@ -1173,6 +1207,9 @@ enum USBEndpointNumber_Out #ifdef IAP_EA_NATIVE_TRANS ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS, #endif +#endif +#if XUA_OR_STATIC_HID_ENABLED && HID_OUT_REQUIRED + ENDPOINT_NUMBER_OUT_HID, #endif XUA_ENDPOINT_COUNT_OUT /* End marker */ }; diff --git a/lib_xua/module_build_info b/lib_xua/module_build_info index b95b65f6..f66eb0f0 100644 --- a/lib_xua/module_build_info +++ b/lib_xua/module_build_info @@ -35,7 +35,7 @@ XCC_FLAGS_dfu.xc = $(MODULE_XCC_FLAGS) -Os -mno-dual-issue XCC_FLAGS_flash_interface.c = $(MODULE_XCC_FLAGS) -Os -mno-dual-issue XCC_FLAGS_flashlib_user.c = $(MODULE_XCC_FLAGS) -Os -mno-dual-issue -OPTIONAL_HEADERS += xua_conf.h +OPTIONAL_HEADERS += xua_conf.h static_hid_report.h EXPORT_INCLUDE_DIRS = api \ src/core \ diff --git a/lib_xua/src/core/buffer/ep/ep_buffer.xc b/lib_xua/src/core/buffer/ep/ep_buffer.xc index 0fc7a13e..20d84bcd 100644 --- a/lib_xua/src/core/buffer/ep/ep_buffer.xc +++ b/lib_xua/src/core/buffer/ep/ep_buffer.xc @@ -10,7 +10,7 @@ #include "xud.h" #include "testct_byref.h" -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED #include "xua_hid_report.h" #include "user_hid.h" #include "xua_hid.h" @@ -134,7 +134,7 @@ void XUA_Buffer( c_clk_int, #endif c_sof, c_aud_ctl, p_off_mclk -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED , c_hid #endif #ifdef CHAN_BUFF_CTRL @@ -224,7 +224,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out, XUD_ep ep_int = XUD_InitEp(c_ep_int); #endif -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED XUD_ep ep_hid = XUD_InitEp(c_hid); #endif unsigned u_tmp; @@ -332,7 +332,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out, #endif #endif -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED while (!hidIsReportDescriptorPrepared()) ; @@ -897,7 +897,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out, #endif #endif -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED /* HID Report Data */ case XUD_SetData_Select(c_hid, ep_hid, result): hid_ready_flag = 0U; diff --git a/lib_xua/src/core/endpoint0/descriptor_defs.h b/lib_xua/src/core/endpoint0/descriptor_defs.h index 42567878..c7dc866b 100644 --- a/lib_xua/src/core/endpoint0/descriptor_defs.h +++ b/lib_xua/src/core/endpoint0/descriptor_defs.h @@ -33,6 +33,7 @@ #define ENDPOINT_ADDRESS_OUT_MIDI (ENDPOINT_NUMBER_OUT_MIDI) #define ENDPOINT_ADDRESS_OUT_IAP (ENDPOINT_NUMBER_OUT_IAP) #define ENDPOINT_ADDRESS_OUT_IAP_EA_NATIVE_TRANS (ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS) +#define ENDPOINT_ADDRESS_OUT_HID (ENDPOINT_NUMBER_OUT_HID) /* Interface numbers enum */ enum USBInterfaceNumber @@ -60,7 +61,7 @@ enum USBInterfaceNumber INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS, #endif #endif -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED INTERFACE_NUMBER_HID, #endif INTERFACE_COUNT /* End marker */ @@ -70,4 +71,8 @@ enum USBInterfaceNumber #define ENDPOINT_INT_INTERVAL_IN_HID 0x08 #endif +#ifndef ENDPOINT_INT_INTERVAL_OUT_HID +#define ENDPOINT_INT_INTERVAL_OUT_HID 0x08 +#endif + #endif diff --git a/lib_xua/src/core/endpoint0/xua_endpoint0.c b/lib_xua/src/core/endpoint0/xua_endpoint0.c index a21e605a..c24dfefc 100755 --- a/lib_xua/src/core/endpoint0/xua_endpoint0.c +++ b/lib_xua/src/core/endpoint0/xua_endpoint0.c @@ -26,7 +26,7 @@ #include "xc_ptr.h" #include "xua_ep0_uacreqs.h" -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED #include "hid.h" #include "xua_hid.h" #include "xua_hid_report.h" @@ -442,6 +442,15 @@ void XUA_Endpoint0_setBcdDevice(unsigned short bcd) { #endif // AUDIO_CLASS == 1} } +#if defined(__static_hid_report_h_exists__) +#define hidReportDescriptorLength (sizeof(hidReportDescriptorPtr)) +static unsigned char hidReportDescriptorPtr[] = { +#include "static_hid_report.h" +}; +#endif + + + void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(chanend, c_audioControl), chanend c_mix_ctl, chanend c_clk_ctl, chanend c_EANativeTransport_ctrl, CLIENT_INTERFACE(i_dfu, dfuInterface) VENDOR_REQUESTS_PARAMS_DEC_) { @@ -513,11 +522,13 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c #endif // XUA_USB_DESCRIPTOR_OVERWRITE_RATE_RES -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED +#if XUA_HID_ENABLED hidReportInit(); hidPrepareReportDescriptor(); size_t hidReportDescriptorLength = hidGetReportDescriptorLength(); +#endif unsigned char hidReportDescriptorLengthLo = hidReportDescriptorLength & 0xFF; unsigned char hidReportDescriptorLengthHi = (hidReportDescriptorLength & 0xFF00) >> 8; @@ -528,6 +539,7 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET ] = hidReportDescriptorLengthLo; hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET + 1] = hidReportDescriptorLengthHi; + #endif // 0 < HID_CONTROLS } @@ -731,7 +743,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 switch(sp.bRequest) { -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED case USB_GET_DESCRIPTOR: /* Check what inteface request is for */ @@ -746,15 +758,17 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 { /* Return HID Descriptor */ result = XUD_DoGetRequest(ep0_out, ep0_in, hidDescriptor, - sizeof(hidDescriptor), sp.wLength); + hidDescriptor[0], sp.wLength); } break; case HID_REPORT: { /* Return HID report descriptor */ +#if XUA_HID_ENABLED unsigned char* hidReportDescriptorPtr; hidReportDescriptorPtr = hidGetReportDescriptor(); size_t hidReportDescriptorLength = hidGetReportDescriptorLength(); +#endif result = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptorPtr, hidReportDescriptorLength, sp.wLength); } @@ -858,7 +872,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 } } #endif -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED if (interfaceNum == INTERFACE_NUMBER_HID) { result = HidInterfaceClassRequests(ep0_out, ep0_in, &sp); diff --git a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h index 91fd3b94..f08697ca 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h +++ b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h @@ -787,10 +787,13 @@ typedef struct #endif #endif // IAP -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED USB_Descriptor_Interface_t HID_Interface; USB_HID_Descriptor_t HID_Descriptor; USB_Descriptor_Endpoint_t HID_In_Endpoint; +#if HID_OUT_REQUIRED + USB_Descriptor_Endpoint_t HID_Out_Endpoint; +#endif #endif }__attribute__((packed)) USB_Config_Descriptor_Audio2_t; @@ -2208,14 +2211,14 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= #endif #endif /* IAP */ -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED #include "xua_hid_descriptors.h" #endif }; #endif /* (AUDIO_CLASS == 2) */ -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED #if (AUDIO_CLASS ==1 ) unsigned char hidDescriptor[] = { @@ -2330,14 +2333,14 @@ const unsigned num_freqs_a1 = MAX(3, (0 #define DFU_INTERFACES_A1 0 #endif -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED /* * The value of HID_INTERFACE_BYTES must match the length of the descriptors defined in * - xua_hid_descriptor_contents.h * - xua_hid_endpoint_descriptor_contents.h and * - xua_hid_interface_descriptor_contents.h */ -#define HID_INTERFACE_BYTES ( 9 + 9 + 7 ) +#define HID_INTERFACE_BYTES ( 9 + 9 + (7 * (1 + HID_OUT_REQUIRED))) // always IN #define HID_INTERFACES_A1 1 #else #define HID_INTERFACE_BYTES 0 @@ -2379,7 +2382,7 @@ const unsigned num_freqs_a1 = MAX(3, (0 #endif -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED #define USB_HID_DESCRIPTOR_OFFSET (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + INTERFACE_DESCRIPTOR_BYTES) #endif @@ -2893,7 +2896,7 @@ unsigned char cfgDesc_Audio1[] = offsetof(StringDescTable_t, ctrlStr)/sizeof(char *), /* 8 iInterface */ #endif -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED #include "xua_hid_descriptors.h" #endif diff --git a/lib_xua/src/core/main.xc b/lib_xua/src/core/main.xc index 17c418e1..1e2a5145 100755 --- a/lib_xua/src/core/main.xc +++ b/lib_xua/src/core/main.xc @@ -213,6 +213,9 @@ XUD_EpType epTypeTableOut[ENDPOINT_COUNT_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_EN #ifdef MIDI XUD_EPTYPE_BUL, /* MIDI */ #endif +#if HID_OUT_REQUIRED + XUD_EPTYPE_INT, +#endif #ifdef IAP XUD_EPTYPE_BUL, /* iAP */ #ifdef IAP_EA_NATIVE_TRANS @@ -233,7 +236,7 @@ XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENAB #ifdef MIDI XUD_EPTYPE_BUL, #endif -#if( 0 < HID_CONTROLS ) +#if XUA_OR_STATIC_HID_ENABLED XUD_EPTYPE_INT, #endif #ifdef IAP @@ -267,115 +270,6 @@ void xscope_user_init() } #endif -#if XUA_USB_EN -/* Core USB Audio functions - must be called on the Tile connected to the USB Phy */ -void usb_audio_core(chanend c_mix_out -#ifdef MIDI - , chanend c_midi -#endif -#if (MIXER) - , chanend c_mix_ctl -#endif - , chanend ?c_clk_int - , chanend ?c_clk_ctl - , client interface i_dfu ?dfuInterface -#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) - , client interface pll_ref_if i_pll_ref -#endif -VENDOR_REQUESTS_PARAMS_DEC_ -) -{ - chan c_sof; - chan c_xud_out[ENDPOINT_COUNT_OUT]; /* Endpoint channels for XUD */ - chan c_xud_in[ENDPOINT_COUNT_IN]; - chan c_aud_ctl; - -#if (!MIXER) -#define c_mix_ctl null -#endif - -#ifdef IAP_EA_NATIVE_TRANS - chan c_EANativeTransport_ctrl; -#else -#define c_EANativeTransport_ctrl null -#endif - - par - { - { -#ifdef XUD_PRIORITY_HIGH - set_core_high_priority_on(); -#endif - - /* Run UAC2.0 at high-speed, UAC1.0 at full-speed */ - unsigned usbSpeed = (AUDIO_CLASS == 2) ? XUD_SPEED_HS : XUD_SPEED_FS; - - unsigned xudPwrCfg = (XUA_POWERMODE == XUA_POWERMODE_SELF) ? XUD_PWR_SELF : XUD_PWR_BUS; - - /* USB interface core */ - XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN, - c_sof, epTypeTableOut, epTypeTableIn, usbSpeed, xudPwrCfg); - } - - { - 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 */ - XUA_Buffer(c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO],/* Audio Out*/ -#if (NUM_USB_CHAN_IN > 0) - - c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */ -#endif -#if (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 (HID_CONTROLS) - , c_xud_in[ENDPOINT_NUMBER_IN_HID] -#endif - , c_mix_out -#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) - , i_pll_ref -#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_); - } - - //: - } -} -#endif /* XUA_USB_EN */ - - #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) void SpdifTxWrapper(chanend c_spdif_tx) { @@ -575,6 +469,20 @@ int main() #if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) interface pll_ref_if i_pll_ref; +#endif + chan c_sof; + chan c_xud_out[ENDPOINT_COUNT_OUT]; /* Endpoint channels for XUD */ + chan c_xud_in[ENDPOINT_COUNT_IN]; + chan c_aud_ctl; + +#if (!MIXER) +#define c_mix_ctl null +#endif + +#ifdef IAP_EA_NATIVE_TRANS + chan c_EANativeTransport_ctrl; +#else +#define c_EANativeTransport_ctrl null #endif USER_MAIN_DECLARATIONS @@ -597,27 +505,77 @@ int main() #endif #endif #if XUA_USB_EN - /* Core USB audio task, buffering, USB etc */ - usb_audio_core(c_mix_out -#ifdef MIDI - , c_midi -#endif -#ifdef IAP - , c_iap -#ifdef IAP_EA_NATIVE_TRANS - , c_ea_data -#endif -#endif -#if (MIXER) - , c_mix_ctl -#endif - , c_clk_int, c_clk_ctl, dfuInterface -#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) - , i_pll_ref -#endif - VENDOR_REQUESTS_PARAMS_ - ); + /* Core USB task, buffering, USB etc */ + { +#ifdef XUD_PRIORITY_HIGH + set_core_high_priority_on(); +#endif + + /* Run UAC2.0 at high-speed, UAC1.0 at full-speed */ + unsigned usbSpeed = (AUDIO_CLASS == 2) ? XUD_SPEED_HS : XUD_SPEED_FS; + + unsigned xudPwrCfg = (XUA_POWERMODE == XUA_POWERMODE_SELF) ? XUD_PWR_SELF : XUD_PWR_BUS; + + /* USB interface core */ + XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN, + c_sof, epTypeTableOut, epTypeTableIn, usbSpeed, xudPwrCfg); + } + + /* Core USB audio task, buffering, USB etc */ + { + 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 */ + XUA_Buffer(c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO],/* Audio Out*/ +#if (NUM_USB_CHAN_IN > 0) + + c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */ +#endif +#if (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) + , i_pll_ref +#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_); + } + #endif /* XUA_USB_EN */ } diff --git a/lib_xua/src/core/user/hid/user_hid.h b/lib_xua/src/core/user/hid/user_hid.h index b17a4dd5..c14411a7 100644 --- a/lib_xua/src/core/user/hid/user_hid.h +++ b/lib_xua/src/core/user/hid/user_hid.h @@ -34,7 +34,7 @@ typedef struct hidEvent_t { #define HID_MAX_DATA_BYTES ( 4 ) #define HID_EVENT_INVALID_ID ( 0x100 ) -#if( 0 < HID_CONTROLS ) +#if XUA_HID_REQUIRED /** * \brief Get the data for the next HID Report diff --git a/lib_xua/src/hid/hid.xc b/lib_xua/src/hid/hid.xc index 0f506d59..ade13c4a 100644 --- a/lib_xua/src/hid/hid.xc +++ b/lib_xua/src/hid/hid.xc @@ -13,7 +13,7 @@ #define DEBUG_PRINT_ENABLE_HID_XC 0 #include "debug_print.h" -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED static unsigned HidCalcNewReportTime( const unsigned currentPeriod, const unsigned reportTime, const unsigned reportToSetIdleInterval, const unsigned newPeriod ); static unsigned HidCalcReportToSetIdleInterval( const unsigned reportTime ); static unsigned HidFindSetIdleActivationPoint( const unsigned currentPeriod, const unsigned timeWithinPeriod ); diff --git a/lib_xua/src/hid/hid_report.c b/lib_xua/src/hid/hid_report.c index 204f6235..28161776 100644 --- a/lib_xua/src/hid/hid_report.c +++ b/lib_xua/src/hid/hid_report.c @@ -1,7 +1,7 @@ // Copyright 2021-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include "xua_conf_full.h" -#if( 0 < HID_CONTROLS ) +#if XUA_HID_ENABLED #include #include diff --git a/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h b/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h index d6bcc6b3..17ec8cf3 100644 --- a/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h +++ b/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h @@ -31,6 +31,19 @@ HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_HI, /* 5 wMaxPacketSize */ ENDPOINT_INT_INTERVAL_IN_HID, /* 6 bInterval */ +#if (HID_OUT_REQUIRED) + + /* HID Endpoint descriptor (OUT) */ + HID_ENDPOINT_DESCRIPTOR_LENGTH, /* 0 bLength */ + HID_ENDPOINT_DESCRIPTOR_TYPE, /* 1 bDescriptorType */ + ENDPOINT_ADDRESS_OUT_HID, /* 2 bEndpointAddress */ + HID_ENDPOINT_ATTRIBUTES, /* 3 bmAttributes (INTERRUPT) */ + HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_LO, /* 4 wMaxPacketSize */ + HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_HI, /* 5 wMaxPacketSize */ + ENDPOINT_INT_INTERVAL_OUT_HID, /* 6 bInterval */ + +#endif + #elif (AUDIO_CLASS == 2) .HID_In_Endpoint = @@ -44,6 +57,21 @@ .bInterval = ENDPOINT_INT_INTERVAL_IN_HID, }, +#if (HID_OUT_REQUIRED) + + .HID_Out_Endpoint = + { + /* Endpoint descriptor (OUT) */ + .bLength = sizeof(USB_Descriptor_Endpoint_t), + .bDescriptorType = HID_ENDPOINT_DESCRIPTOR_TYPE, + .bEndpointAddress = ENDPOINT_ADDRESS_OUT_HID, + .bmAttributes = HID_ENDPOINT_ATTRIBUTES, + .wMaxPacketSize = HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_LO, + .bInterval = ENDPOINT_INT_INTERVAL_OUT_HID, + }, + +#endif + #else #error "Unknown Audio Class" #endif diff --git a/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h b/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h index 83d69fbd..241b673e 100644 --- a/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h +++ b/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h @@ -15,7 +15,8 @@ #define HID_INTERFACE_DESCRIPTOR_LENGTH ( 0x09 ) /* Size of descriptor in Bytes */ #define HID_INTERFACE_DESCRIPTOR_TYPE ( 0x04 ) /* Interface 0x04 */ #define HID_INTERFACE_ALTERNATE_SETTING ( 0x00 ) /* Value used alternate interfaces using SetInterface Request */ -#define HID_INTERFACE_NUMBER_OF_ENDPOINTS ( 0x01 ) /* Number of endpoitns for this interface (excluding 0) */ +#define HID_INTERFACE_NUMBER_OF_ENDPOINTS ( 0x01 + HID_OUT_REQUIRED ) + /* Number of endpoints for this interface (excluding 0) */ #define HID_INTERFACE_CLASS ( 0x03 ) #define HID_INTERFACE_SUBCLASS ( 0x00 ) /* No boot device */ #define HID_INTERFACE_PROTOCOL ( 0x00 ) From 136ec2506cbbcb18ac0c9eea929b63a15f02147b Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Mon, 12 Jun 2023 09:20:43 +0100 Subject: [PATCH 04/12] One of the intermediate XUA_HID_REQUIRED slipped through the refactoring --- lib_xua/src/core/user/hid/user_hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/user/hid/user_hid.h b/lib_xua/src/core/user/hid/user_hid.h index c14411a7..a391601a 100644 --- a/lib_xua/src/core/user/hid/user_hid.h +++ b/lib_xua/src/core/user/hid/user_hid.h @@ -34,7 +34,7 @@ typedef struct hidEvent_t { #define HID_MAX_DATA_BYTES ( 4 ) #define HID_EVENT_INVALID_ID ( 0x100 ) -#if XUA_HID_REQUIRED +#if XUA_HID_ENABLED /** * \brief Get the data for the next HID Report From 1702078e7c0c3e3bad3b5674273d5a248f4cdad1 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 12 Jun 2023 17:14:42 +0100 Subject: [PATCH 05/12] Update copyright comment --- lib_xua/src/core/buffer/ep/ep_buffer.xc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/buffer/ep/ep_buffer.xc b/lib_xua/src/core/buffer/ep/ep_buffer.xc index 20d84bcd..a2e42199 100644 --- a/lib_xua/src/core/buffer/ep/ep_buffer.xc +++ b/lib_xua/src/core/buffer/ep/ep_buffer.xc @@ -1,4 +1,4 @@ -// Copyright 2011-2022 XMOS LIMITED. +// Copyright 2011-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include "xua.h" #if XUA_USB_EN From b0e732110da5deeb9d57cafc28f7e3ed8c917b6d Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 12 Jun 2023 17:15:21 +0100 Subject: [PATCH 06/12] Update copyright comment --- lib_xua/src/core/endpoint0/descriptor_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/endpoint0/descriptor_defs.h b/lib_xua/src/core/endpoint0/descriptor_defs.h index c7dc866b..c547dfad 100644 --- a/lib_xua/src/core/endpoint0/descriptor_defs.h +++ b/lib_xua/src/core/endpoint0/descriptor_defs.h @@ -1,4 +1,4 @@ -// Copyright 2015-2021 XMOS LIMITED. +// Copyright 2015-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef __DESCRIPTOR_DEFS_H__ From 5ca0738b026748be8ba8dff3878e5f3dcad2c7e0 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 12 Jun 2023 17:15:42 +0100 Subject: [PATCH 07/12] Update copyright comment --- lib_xua/src/core/user/hid/user_hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/user/hid/user_hid.h b/lib_xua/src/core/user/hid/user_hid.h index a391601a..b5c6090d 100644 --- a/lib_xua/src/core/user/hid/user_hid.h +++ b/lib_xua/src/core/user/hid/user_hid.h @@ -1,4 +1,4 @@ -// Copyright 2013-2021 XMOS LIMITED. +// Copyright 2013-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. /** From a6387d5fefa0120cf70a9b00c5350f910c6236c9 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 12 Jun 2023 17:16:11 +0100 Subject: [PATCH 08/12] Update copyright comment --- lib_xua/src/hid/hid.xc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/hid/hid.xc b/lib_xua/src/hid/hid.xc index ade13c4a..99d33b51 100644 --- a/lib_xua/src/hid/hid.xc +++ b/lib_xua/src/hid/hid.xc @@ -1,4 +1,4 @@ -// Copyright 2019-2022 XMOS LIMITED. +// Copyright 2019-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include #include From 3d7e66bdc07c5208cdc0c379392ccf6ac59de627 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 12 Jun 2023 17:16:26 +0100 Subject: [PATCH 09/12] Update copyright comment --- lib_xua/src/hid/hid_report.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/hid/hid_report.c b/lib_xua/src/hid/hid_report.c index 28161776..f74c478d 100644 --- a/lib_xua/src/hid/hid_report.c +++ b/lib_xua/src/hid/hid_report.c @@ -1,4 +1,4 @@ -// Copyright 2021-2022 XMOS LIMITED. +// Copyright 2021-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include "xua_conf_full.h" #if XUA_HID_ENABLED From 799ad7ba868fa35ed580f36f7722e53d855c4c19 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 12 Jun 2023 17:16:43 +0100 Subject: [PATCH 10/12] Update copyright comment --- lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h b/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h index 17ec8cf3..293ee13c 100644 --- a/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h +++ b/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h @@ -1,4 +1,4 @@ -// Copyright 2021 XMOS LIMITED. +// Copyright 2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. /** From 6815f12a903cf2000cbac8f41177e61291879654 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 12 Jun 2023 17:16:56 +0100 Subject: [PATCH 11/12] Update copyright comment --- lib_xua/src/hid/xua_hid_interface_descriptor_contents.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h b/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h index 241b673e..548bb4ec 100644 --- a/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h +++ b/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h @@ -1,4 +1,4 @@ -// Copyright 2021 XMOS LIMITED. +// Copyright 2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. /** From 36d52013652fe112287c86823abdf08e9d381997 Mon Sep 17 00:00:00 2001 From: Daniel Pieczko Date: Wed, 14 Jun 2023 08:09:33 +0100 Subject: [PATCH 12/12] Update copyright years --- lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h | 2 +- lib_xua/src/hid/xua_hid_interface_descriptor_contents.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h b/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h index 293ee13c..6287fe4b 100644 --- a/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h +++ b/lib_xua/src/hid/xua_hid_endpoint_descriptor_contents.h @@ -1,4 +1,4 @@ -// Copyright 2023 XMOS LIMITED. +// Copyright 2021-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. /** diff --git a/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h b/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h index 548bb4ec..450814f6 100644 --- a/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h +++ b/lib_xua/src/hid/xua_hid_interface_descriptor_contents.h @@ -1,4 +1,4 @@ -// Copyright 2023 XMOS LIMITED. +// Copyright 2021-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. /**