From 73955c1a4c5030a648dbb8248c8d90908f2bd252 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Wed, 1 Feb 2023 11:54:48 +0000 Subject: [PATCH] =?UTF-8?q?-=20Added=20mixer=20related=20defines=20to=20re?= =?UTF-8?q?duce=20use=20of=20magic=20numbers=20-=20Increases=20debug=20out?= =?UTF-8?q?put=20when=20DEBUG=20flag=20set=20-=20Removed=20some=20dead=20c?= =?UTF-8?q?ode=20-=20Increased=20alignment=20of=20asm=20mixer=20functions?= =?UTF-8?q?=20-=20Removed=20some=20usages=20of=20=E2=80=9Cxc=5Fptr?= =?UTF-8?q?=E2=80=9D=20type=20in=20favour=20of=20native=20pointers=20in=20?= =?UTF-8?q?XC=20-=20Added=20some=20asserts=20to=20mixer=20-=20Added=20test?= =?UTF-8?q?=5Fmixer=5Frouting=5Finput=20-=20Moved=20test=5Fmixer=5Frouting?= =?UTF-8?q?=5Foutput=20to=20use=20shared=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib_xua/api/xua_mixer.h | 12 + lib_xua/module_build_info | 4 +- lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc | 23 +- lib_xua/src/core/mixer/fastmix.S | 4 +- lib_xua/src/core/mixer/mixer.xc | 184 +++++----- tests/test_mixer_routing_input.py | 45 +++ tests/test_mixer_routing_input/Makefile | 19 ++ tests/test_mixer_routing_input/src/main.xc | 243 +++++++++++++ .../src/test_xs3_600.xn | 24 ++ tests/test_mixer_routing_input/src/xua_conf.h | 45 +++ tests/test_mixer_routing_output/Makefile | 12 +- tests/test_mixer_routing_output/src/main.xc | 283 +-------------- .../src/mixer_test_shared.h | 323 ++++++++++++++++++ 13 files changed, 835 insertions(+), 386 deletions(-) create mode 100644 tests/test_mixer_routing_input.py create mode 100644 tests/test_mixer_routing_input/Makefile create mode 100644 tests/test_mixer_routing_input/src/main.xc create mode 100644 tests/test_mixer_routing_input/src/test_xs3_600.xn create mode 100644 tests/test_mixer_routing_input/src/xua_conf.h create mode 100644 tests/test_mixer_routing_output/src/mixer_test_shared.h diff --git a/lib_xua/api/xua_mixer.h b/lib_xua/api/xua_mixer.h index ee44fe00..319c12d1 100644 --- a/lib_xua/api/xua_mixer.h +++ b/lib_xua/api/xua_mixer.h @@ -3,6 +3,8 @@ #ifndef _XUA_MIXER_H_ #define _XUA_MIXER_H_ +#include "xua.h" + enum mix_ctl_cmd { SET_SAMPLES_TO_HOST_MAP, SET_SAMPLES_TO_DEVICE_MAP, @@ -31,4 +33,14 @@ enum mix_ctl_cmd { */ void mixer(chanend c_to_host, chanend c_to_audio, chanend c_mix_ctl); +#define XUA_MIXER_OFFSET_OUT (0) +#define XUA_MIXER_OFFSET_IN (NUM_USB_CHAN_OUT) +#define XUA_MIXER_OFFSET_MIX (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN) +#define XUA_MIXER_OFFSET_OFF (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT) + +/* Defines uses for DB to actual muliplier conversion */ +#define XUA_MIXER_MULT_FRAC_BITS (25) +#define XUA_MIXER_DB_FRAC_BITS (8) +#define XUA_MIXER_MAX_MULT (1<=2.1.0) \ diff --git a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc index 7626cc0e..57d4aaad 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc +++ b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc @@ -677,10 +677,6 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c { if (c < NUM_USB_CHAN_OUT) { - //outuint(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP); - //outuint(c_mix_ctl, c); - //outuint(c_mix_ctl, channelMapAud[c]); - //outct(c_mix_ctl, XS1_CT_END); UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP, c, channelMapAud[c]); /* Send 0 Length as status stage */ @@ -717,10 +713,6 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c { if (!isnull(c_mix_ctl)) { - //outuint(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP); - //outuint(c_mix_ctl, c); - //outuint(c_mix_ctl, channelMapUsb[c]); - //outct(c_mix_ctl, XS1_CT_END); UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP, c, channelMapUsb[c]); return XUD_DoSetRequestStatus(ep0_in); @@ -774,22 +766,15 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c /* Update all mix maps */ for (int i = 0; i < MAX_MIX_COUNT; i++) { - //outuint(c_mix_ctl, SET_MIX_MAP); - //outuint(c_mix_ctl, i); /* Mix bus */ - //outuint(c_mix_ctl, cn); /* Mixer input */ - //outuint(c_mix_ctl, (int) mixSel[cn]); /* Source */ - //outct(c_mix_ctl, XS1_CT_END); + /* i : Mix bus */ + /* cn: Mixer input */ + /* mixSel[i][cn]): Source */ UpdateMixMap(c_mix_ctl, i, cn, (int) mixSel[cn]); } } else { /* Update relevant mix map */ - //outuint(c_mix_ctl, SET_MIX_MAP); /* Command */ - //outuint(c_mix_ctl, (cs-1)); /* Mix bus */ - //outuint(c_mix_ctl, cn); /* Mixer input */ - //outuint(c_mix_ctl, (int) mixSel[cs][cn]); /* Source */ - //outct(c_mix_ctl, XS1_CT_END); /* Wait for handshake back */ UpdateMixMap(c_mix_ctl, cs-1, cn, (int) mixSel[cs][cn]); } @@ -838,7 +823,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c } else { - volume = db_to_mult(mixer1Weights[sp.wValue & 0xff], 8, 25); + volume = db_to_mult(mixer1Weights[sp.wValue & 0xff], XUA_MIXER_DB_FRAC_BITS, XUA_MIXER_MULT_FRAC_BITS); } if (!isnull(c_mix_ctl)) { diff --git a/lib_xua/src/core/mixer/fastmix.S b/lib_xua/src/core/mixer/fastmix.S index 9f298115..a2374a5e 100644 --- a/lib_xua/src/core/mixer/fastmix.S +++ b/lib_xua/src/core/mixer/fastmix.S @@ -6,7 +6,7 @@ #define DOMIX_TOP(i) \ .cc_top doMix##i.function,doMix##i; \ - .align 4 ;\ + .align 16 ;\ .globl doMix##i ;\ .type doMix##i, @function ;\ .globl doMix##i##.nstackwords ;\ @@ -124,7 +124,7 @@ DOMIX_BOT(7) #undef BODY #define N MAX_MIX_COUNT .cc_top setPtr.function,setPtr; -.align 4 ; +.align 16 ; .globl setPtr; .type setPtr, @function .globl setPtr.nstackwords; diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index 58af02c8..a5d6795f 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -1,7 +1,9 @@ -// Copyright 2011-2022 XMOS LIMITED. +// Copyright 2011-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. +#define XASSERT_UNIT MIXER +#include "xassert.h" + #include -#include #include "xua.h" #include "xc_ptr.h" #include "xua_commands.h" @@ -36,15 +38,12 @@ static unsigned abs(int x) #endif static int samples_array[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1]; /* One larger for an "off" channel for mixer sources" */ -xc_ptr samples; unsafe { static int volatile * const unsafe ptr_samples = samples_array; } -int savedsamples2[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; - int samples_to_host_map_array[NUM_USB_CHAN_IN]; xc_ptr samples_to_host_map; @@ -77,18 +76,6 @@ static int samples_from_host_streams[NUM_USB_CHAN_OUT]; /* Peak samples for audi static int samples_mixer_outputs[MAX_MIX_COUNT]; /* Peak samples out of the mixer */ xc_ptr samples_mixer_outputs_ptr; -#if 0 -#pragma xta command "add exclusion mixer1_rate_change" -#pragma xta command "analyse path mixer1_req mixer1_req" -#pragma xta command "set required - 10400 ns" /* 96kHz */ -#endif - -#if 0 -#pragma xta command "add exclusion mixer2_rate_change" -#pragma xta command "analyse path mixer2_req mixer2_req" -#pragma xta command "set required - 10400 ns" /* 96kHz */ -#endif - #if defined (LEVEL_METER_LEDS) || defined (LEVEL_METER_HOST) static inline void ComputeMixerLevel(int sample, int i) { @@ -110,20 +97,20 @@ static inline void ComputeMixerLevel(int sample, int i) #endif #ifdef FAST_MIXER void setPtr(int src, int dst, int mix); -int doMix0(xc_ptr samples, xc_ptr mult); -int doMix1(xc_ptr samples, xc_ptr mult); -int doMix2(xc_ptr samples, xc_ptr mult); -int doMix3(xc_ptr samples, xc_ptr mult); -int doMix4(xc_ptr samples, xc_ptr mult); -int doMix5(xc_ptr samples, xc_ptr mult); -int doMix6(xc_ptr samples, xc_ptr mult); -int doMix7(xc_ptr samples, xc_ptr mult); -int doMix8(xc_ptr samples, xc_ptr mult); +int doMix0(int * unsafe samples, xc_ptr mult); +int doMix1(int * unsafe samples, xc_ptr mult); +int doMix2(int * unsafe samples, xc_ptr mult); +int doMix3(int * unsafe samples, xc_ptr mult); +int doMix4(int * unsafe samples, xc_ptr mult); +int doMix5(int * unsafe samples, xc_ptr mult); +int doMix6(int * unsafe samples, xc_ptr mult); +int doMix7(int * unsafe samples, xc_ptr mult); +int doMix8(int * unsafe samples, xc_ptr mult); #else /* DO NOT inline, causes 10.4.2 tools to add extra loads in loop */ /* At 18 x 12dB we could get 64 x bigger */ #pragma unsafe arrays -static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) +static inline int doMix(xc_ptr samples, xc_ptr mixMapSlice, xc_ptr mixMultSlice) { int h=0; int l=0; @@ -132,18 +119,17 @@ static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) #pragma loop unroll for (int i=0; i>7); } -#endif return h<<7; } #endif @@ -179,7 +164,6 @@ static inline void GiveSamplesToHost(chanend c, xc_ptr ptr, xc_ptr multIn) #endif unsafe { - //read_via_xc_ptr_indexed(sample,samples,index); sample = ptr_samples[index]; } @@ -269,7 +253,12 @@ static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut) read_via_xc_ptr_indexed(index, ptr, i); /* Read the actual sample value */ - read_via_xc_ptr_indexed(sample, samples, index); + //read_via_xc_ptr_indexed(sample, samples, index); + unsafe + { + /* Read the actual sample value */ + sample = ptr_samples[index]; + } #else unsafe { @@ -284,7 +273,6 @@ static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut) read_via_xc_ptr_indexed(mult, multOut, i); {h, l} = macs(mult, sample, 0, 0); h<<=3; // Shift used to be done in audio thread but now done here incase of 32bit support -#error #if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1) h |= (l >>29)& 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit) // Note: We need all 32bits for Native DSD @@ -307,7 +295,7 @@ static inline void GetSamplesFromDevice(chanend c) #endif #pragma loop unroll - for (int i=0;i 2 + unsafe + { #ifdef FAST_MIXER - mixed = doMix2(samples, mix_mult_slice(2)); + mixed = doMix2(ptr_samples, mix_mult_slice(2)); #else - mixed = doMix(samples, mix_map_slice(2),mix_mult_slice(2)); + mixed = doMix(ptr_samples, mix_map_slice(2), mix_mult_slice(2)); #endif - write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 2), mixed); + ptr_samples[XUA_MIXER_OFFSET_MIX + 2] = mixed; + } #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 2); @@ -574,26 +573,30 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #endif #if MAX_MIX_COUNT > 4 + unsafe + { #ifdef FAST_MIXER - mixed = doMix4(samples, mix_mult_slice(4)); + mixed = doMix4(ptr_samples, mix_mult_slice(4)); #else - mixed = doMix(samples, mix_map_slice(4),mix_mult_slice(4)); + mixed = doMix(samples, mix_map_slice(4), mix_mult_slice(4)); #endif - write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 4), mixed); - + ptr_samples[XUA_MIXER_OFFSET_MIX + 4] = mixed; + } #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 4); #endif #endif #if MAX_MIX_COUNT > 6 + unsafe + { #ifdef FAST_MIXER - mixed = doMix6(samples, mix_mult_slice(6)); + mixed = doMix6(ptr_samples, mix_mult_slice(6)); #else - mixed = doMix(samples, mix_map_slice(6),mix_mult_slice(6)); + mixed = doMix(samples, mix_map_slice(6), mix_mult_slice(6)); #endif - write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 6), mixed); - + ptr_samples[XUA_MIXER_OFFSET_MIX + 6] = mixed; + } #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 6); #endif @@ -661,7 +664,10 @@ static void mixer2(chanend c_mixer1, chanend c_audio) for (int i=0;i 1 + unsafe + { #ifdef FAST_MIXER - mixed = doMix1(samples, mix_mult_slice(1)); + mixed = doMix1(ptr_samples, mix_mult_slice(1)); #else - mixed = doMix(samples, mix_map_slice(1),mix_mult_slice(1)); + mixed = doMix(samples, mix_map_slice(1), mix_mult_slice(1)); #endif - - write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 1), mixed); - + ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 1] = mixed; + } #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 1); #endif #endif - #if (MAX_FREQ > 96000) /* Fewer mixes when running higher than 96kHz */ if (!mixer2_mix2_flag) #endif { #if MAX_MIX_COUNT > 3 + unsafe + { #ifdef FAST_MIXER - mixed = doMix3(samples, mix_mult_slice(3)); + mixed = doMix3(ptr_samples, mix_mult_slice(3)); #else - mixed = doMix(samples, mix_map_slice(3),mix_mult_slice(3)); + mixed = doMix(samples, mix_map_slice(3), mix_mult_slice(3)); #endif - - write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 3), mixed); - + ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 3] = mixed; + } #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 3); #endif #endif #if MAX_MIX_COUNT > 5 + unsafe + { #ifdef FAST_MIXER - mixed = doMix5(samples, mix_mult_slice(5)); + mixed = doMix5(ptr_samples, mix_mult_slice(5)); #else - mixed = doMix(samples, mix_map_slice(5),mix_mult_slice(5)); + mixed = doMix(samples, mix_map_slice(5), mix_mult_slice(5)); #endif - write_via_xc_ptr_indexed(samples, NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 5, mixed); - + ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 5] = mixed; + } #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 5); #endif #endif #if MAX_MIX_COUNT > 7 + unsafe + { #ifdef FAST_MIXER - mixed = doMix7(samples, mix_mult_slice(7)); + mixed = doMix7(ptr_samples, mix_mult_slice(7)); #else - mixed = doMix(samples, mix_map_slice(7),mix_mult_slice(7)); + mixed = doMix(samples, mix_map_slice(7), mix_mult_slice(7)); #endif - - write_via_xc_ptr_indexed(samples, NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 7, mixed); + ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 7] = mixed; + } #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 7); #endif @@ -751,7 +762,7 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) multOut = array_to_xc_ptr((multOut_array,unsigned[])); multIn = array_to_xc_ptr((multIn_array,unsigned[])); - samples = array_to_xc_ptr((samples_array,unsigned[])); + //samples = array_to_xc_ptr((samples_array,unsigned[])); samples_to_host_map = array_to_xc_ptr((samples_to_host_map_array,unsigned[])); samples_to_device_map = array_to_xc_ptr((samples_to_device_map_array,unsigned[])); @@ -770,7 +781,6 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) for (int i=0;i 0 @@ -809,7 +819,7 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) #ifndef FAST_MIXER write_word_to_mix_map(i,j, j < 16 ? j : j + 2); #endif - write_word_to_mix_mult(i,j, i==j ? db_to_mult(0, 8, 25) : 0); + write_word_to_mix_mult(i,j, i==j ? db_to_mult(0, XUA_MIXER_DB_FRAC_BITS, XUA_MIXER_MULT_FRAC_BITS) : 0); } #endif diff --git a/tests/test_mixer_routing_input.py b/tests/test_mixer_routing_input.py new file mode 100644 index 00000000..7550c78b --- /dev/null +++ b/tests/test_mixer_routing_input.py @@ -0,0 +1,45 @@ +# Copyright 2023 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +import pytest +import Pyxsim +from Pyxsim import testers +import os +import sys + + +def do_test(options, capfd, test_file, test_seed): + + testname, _ = os.path.splitext(os.path.basename(test_file)) + + binary = f"{testname}/bin/{testname}.xe" + + tester = testers.ComparisonTester(open("pass.expect")) + + max_cycles = 15000000 + + simargs = [ + "--max-cycles", + str(max_cycles), + ] + + build_options = [] + build_options += ["TEST_SEED=" + str(test_seed)] + + result = Pyxsim.run_on_simulator( + binary, + tester=tester, + build_options=build_options, + simargs=simargs, + capfd=capfd, + instTracing=options.enabletracing, + vcdTracing=options.enablevcdtracing, + ) + + return result + + +def test_mixer_routing_input(options, capfd, test_file, test_seed): + + result = do_test(options, capfd, test_file, test_seed) + + assert result diff --git a/tests/test_mixer_routing_input/Makefile b/tests/test_mixer_routing_input/Makefile new file mode 100644 index 00000000..f8e3a49d --- /dev/null +++ b/tests/test_mixer_routing_input/Makefile @@ -0,0 +1,19 @@ + +DEBUG ?= 0 + +ifeq ($(DEBUG),1) +TEST_DEBUG_FLAGS = -g -DDEBUG_PRINT_ENABLE=1 +else +TEST_DEBUG_FLAGS = +endif + +TEST_FLAGS = -DTEST_SEED=$(TEST_SEED) $(TEST_DEBUG_FLAGS) + +XCC_FLAGS = -O3 $(TEST_FLAGS) + +TARGET = test_xs3_600.xn + +USED_MODULES = lib_xua lib_logging lib_random + +XMOS_MAKE_PATH ?= ../.. +-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/test_mixer_routing_input/src/main.xc b/tests/test_mixer_routing_input/src/main.xc new file mode 100644 index 00000000..7aaaab02 --- /dev/null +++ b/tests/test_mixer_routing_input/src/main.xc @@ -0,0 +1,243 @@ +// Copyright 2022-2023 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +/* Tests that routing of mixer inputs behaves as expected + * + * The device supports MAX_MIX_COUNT mixers each with MIX_INPUTS inputs. + * + * This test also assumes/checks that the default routing into each of the MIX_INPUTS inputs into + * each of the M mixer units is as follows: + * + * MIXER[0]: + * USB_FROM_HOST[0] -> MIXER[0].INPUT[0] + * USB_FROM_HOST[1] -> MIXER[0].INPUT[1] + * ... + USB_TO_HOST[0] -> MIXER[0].INPUT[NUM_USB_CHAN_OUT] + USB_TO_HOST[1] -> MIXER[0].INPUT[NUM_USB_CHAN_OUT+1] + ... + + * MIXER[MAX_MIX_COUNT-1]: + * USB_FROM_HOST[0] -> MIXER[MAX_MIX_COUNT-1].INPUT[0] + * USB_FROM_HOST[1] -> MIXER[MAX_MIX_COUNT-1].INPUT[1] + * ... + * +*/ +#include +#include +#include "platform.h" +#include "xua.h" +#include "debug_print.h" +#include "assert.h" +#include "random.h" + +#ifndef TEST_ITERATIONS +#define TEST_ITERATIONS (300) +#endif + +#include "./../test_mixer_routing_output/src/mixer_test_shared.h" + +struct ModelMixer +{ + uint32_t deviceMap[NUM_USB_CHAN_OUT]; + uint32_t hostMap[NUM_USB_CHAN_IN]; + uint32_t mixMap_input[MAX_MIX_COUNT]; + uint32_t mixMap_src[MAX_MIX_COUNT]; + uint32_t mixOutput[MAX_MIX_COUNT]; +}; + +void InitModel(struct ModelMixer &modelMixer) +{ + for(size_t i = 0; i < NUM_USB_CHAN_OUT; i++) + { + modelMixer.deviceMap[i] = i; + } + + for(size_t i = 0; i < NUM_USB_CHAN_IN; i++) + { + modelMixer.hostMap[i] = NUM_USB_CHAN_OUT+i; + } + + for(size_t i = 0; i < MAX_MIX_COUNT; i++) + { + // This test only allows for one "active" input to each mixer + modelMixer.mixMap_src[i] = i; + modelMixer.mixMap_input[i] = i; + + uint32_t sample = i; + SET_SOURCE(sample, SRC_HOST); + SET_CHANNEL(sample, i); + modelMixer.mixOutput[i] = sample; + } +} + +void GenExpectedSamples(struct ModelMixer &modelMixer, + uint32_t modelOut[NUM_USB_CHAN_OUT], + uint32_t modelIn[NUM_USB_CHAN_IN]) +{ + /* First generate model mix outputs - run MIX tiles to allow mix inputs derived from mix outputs to propagate */ + for(int j = 0; j < MAX_MIX_COUNT; j++) + { + for(size_t i = 0; i < MAX_MIX_COUNT; i++) + { + int src = modelMixer.mixMap_src[i]; + modelMixer.mixOutput[i] = CreateSample(modelMixer.mixOutput, src); + } + } + + for(size_t i = 0; i + + + tileref tile[2] + + + + + + + + + + + + + + + + + + diff --git a/tests/test_mixer_routing_input/src/xua_conf.h b/tests/test_mixer_routing_input/src/xua_conf.h new file mode 100644 index 00000000..c27f54a6 --- /dev/null +++ b/tests/test_mixer_routing_input/src/xua_conf.h @@ -0,0 +1,45 @@ +// Copyright 2016-2023 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 (10) +#define NUM_USB_CHAN_IN (10) +#define I2S_CHANS_DAC (10) +#define I2S_CHANS_ADC (10) + +#define EXCLUDE_USB_AUDIO_MAIN + +#define MIXER (1) +#define MAX_MIX_COUNT (8) + +#define UAC_FORCE_FEEDBACK_EP (0) +#define XUA_NUM_PDM_MICS 0 +#define XUD_TILE 1 +#define AUDIO_IO_TILE 0 + +#ifndef MCLK_441 +#define MCLK_441 (512 * 44100) +#endif + +#ifndef MCLK_48 +#define MCLK_48 (512 * 48000) +#endif + +#define MIN_FREQ (44100) +#define MAX_FREQ (192000) +#define SPDIF_TX_INDEX 0 +#define VENDOR_STR "XMOS" +#define VENDOR_ID 0x20B1 +#define PRODUCT_STR_A2 "Test device" +#define PRODUCT_STR_A1 "Test device" +#define PID_AUDIO_1 1 +#define PID_AUDIO_2 2 +#define AUDIO_CLASS 2 +#define AUDIO_CLASS_FALLBACK 0 +#define BCD_DEVICE 0x1234 +#define XUA_DFU_EN 0 +#define MIC_DUAL_ENABLED 1 //Use single thread, dual PDM mic +#define XUA_MIC_FRAME_SIZE 240 + +#endif diff --git a/tests/test_mixer_routing_output/Makefile b/tests/test_mixer_routing_output/Makefile index 70e16ec3..f8e3a49d 100644 --- a/tests/test_mixer_routing_output/Makefile +++ b/tests/test_mixer_routing_output/Makefile @@ -1,7 +1,15 @@ -TEST_FLAGS ?= -DTEST_SEED=$(TEST_SEED) +DEBUG ?= 0 -XCC_FLAGS = -O3 -g -DDEBUG_PRINT_ENABLE_main=0 $(TEST_FLAGS) +ifeq ($(DEBUG),1) +TEST_DEBUG_FLAGS = -g -DDEBUG_PRINT_ENABLE=1 +else +TEST_DEBUG_FLAGS = +endif + +TEST_FLAGS = -DTEST_SEED=$(TEST_SEED) $(TEST_DEBUG_FLAGS) + +XCC_FLAGS = -O3 $(TEST_FLAGS) TARGET = test_xs3_600.xn diff --git a/tests/test_mixer_routing_output/src/main.xc b/tests/test_mixer_routing_output/src/main.xc index 1c12700e..43a8ffb2 100644 --- a/tests/test_mixer_routing_output/src/main.xc +++ b/tests/test_mixer_routing_output/src/main.xc @@ -43,7 +43,6 @@ #include #include "platform.h" #include "xua.h" -#define DEBUG_UNIT main #include "debug_print.h" #include "assert.h" #include "random.h" @@ -52,115 +51,7 @@ #define TEST_ITERATIONS (100) #endif -#ifndef TEST_SEED -#error TEST_SEED must be defined! -#endif - -void exit(int); - -// Test sample format: -// byte[0]: Sample counter -// byte[1]: Channel -// byte[3]: Source (HOST:1/AUD IF:0) -#define SRC_HOST (2) -#define SRC_AUDIF (1) -#define SRC_OFF (0) // Important that this is 0 since mixer will generate 0 samples for 'off' - -#define GET_COUNT(x) (x & 0xff) -#define GET_CHANNEL(x) ((x >> 8) & 0xff) -#define GET_SOURCE(x) ((x >> 16) & 0xff) - -#define SET_COUNT(x, y) y = y & 0xff; x = x | y; -#define SET_CHANNEL(x, y) y = y & 0xff; x = x | (y<<8); -#define SET_SOURCE(x, y) x = x | (y<<16); - -/* A limitation of the design is that the number of routable output destinations cannot be larger than NUM_USB_CHAN_OUT. - * This is due to the transfer samples from Mixer to AudioHub tasks being in blocks of NUM_USB_CHAN_OUT. - * This is not normally an issue - since every physical output interface channel on the device is normally derived from a - * USB channel from the host, but it certainly is a restriction. - */ -#define CHANNEL_MAP_AUD_SIZE NUM_USB_CHAN_OUT - -/* Number of channel sources, the channel ordering is as follows - * i.e. - * [0:NUM_USB_CHAN_OUT-1] : Channels from USB Host - * [NUM_USB_CHAN_OUT:NUM_USB_CHAN_IN-1] : Channels from Audio Interfaces - * [NUM_USB_CHAN_N:MAX_MIX_COUNT-1] : Channels from Mixers - * [MAX_MIX_COUNT]: "Off" (Essentially samples always 0) - */ -/* Note, One larger for an "off" channel for mixer sources" */ -#define SOURCE_COUNT (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1) - -#pragma select handler -static inline void testct_byref(chanend c, unsigned &isCt) -{ - isCt = testct(c); -} - -void PrintSourceString(unsigned source) -{ - debug_printf(" "); - if(source < NUM_USB_CHAN_OUT) - { - debug_printf("(DEVICE IN - HOST%d)", source); - } - else if(source < (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN)) - { - debug_printf("(DEVICE IN - AudioIF %d)", source - NUM_USB_CHAN_OUT); - } - else if(source < (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT)) - { - debug_printf("(MIX %d)", source - NUM_USB_CHAN_OUT - NUM_USB_CHAN_IN); - } - else - debug_printf("(off)"); - debug_printf(" "); -} - -void PrintDestString(unsigned map, unsigned dest) -{ - switch(map) - { - case SET_SAMPLES_TO_DEVICE_MAP: - debug_printf("(DEVICE OUT - AudioIF)"); - break; - case SET_SAMPLES_TO_HOST_MAP: - debug_printf("(DEVICE OUT - HOST)"); - break; - } -} - -void PrintSample(unsigned sample) -{ - debug_printf("SOURCE: "); - if(GET_SOURCE(sample) == SRC_HOST) - debug_printf("HOST "); - else if(GET_SOURCE(sample) == SRC_AUDIF) - debug_printf("AUDIF "); - else if(GET_SOURCE(sample) == SRC_OFF) - debug_printf("OFF "); - else - debug_printf("UNKNOWN "); - - debug_printf("CHANNEL: %d", GET_CHANNEL(sample)); -} - -/* Required by lib_xua */ -void AudioHwInit() -{ - return; -} - -/* Required by lib_xua */ -void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) -{ - return; -} - -/* From xua_ep0_uacreqs.xc */ -void UpdateMixerOutputRouting(chanend c_mix_ctl, unsigned map, unsigned dst, unsigned src); -void UpdateMixMap(chanend c_mix_ctl, int mix, int input, int src); -void UpdateMixerWeight(chanend c_mix_ctl, int mix, int index, unsigned val); +#include "./mixer_test_shared.h" void UpdateModel(uint32_t modelOut[CHANNEL_MAP_AUD_SIZE], uint32_t modelMixerOut[MAX_MIX_COUNT], uint32_t modelIn[NUM_USB_CHAN_IN], int map, int dst, int src) @@ -214,7 +105,6 @@ void stim(chanend c_stim_ah, chanend c_stim_de, chanend c_mix_ctl) uint32_t testCmd[] = {SET_SAMPLES_TO_HOST_MAP, SET_SAMPLES_TO_DEVICE_MAP}; random_generator_t rg = random_create_generator_from_seed(TEST_SEED); - //assert(NUM_USB_CHAN_OUT >= MIX_INPUTS); /* By default the mixer should output samples from USB host unmodified * See mixer.xc L780 @@ -247,17 +137,10 @@ void stim(chanend c_stim_ah, chanend c_stim_de, chanend c_mix_ctl) modelIn[i] = sample; } - outuint(c_stim_ah, 0); - /* Check default routing */ /* Send expected to AudioHub */ - for(int i = 0; i < CHANNEL_MAP_AUD_SIZE; i++) - { - outuint(c_stim_ah, modelOut[i]); - } - - /* Wait for handshake back and move on to next test */ - inuint(c_stim_ah); + SendTrigger(c_stim_ah, 2); + SendExpected(c_stim_ah, c_stim_de, modelOut, modelIn); for(int testIter = 0; testIter < TEST_ITERATIONS; testIter++) { @@ -276,6 +159,7 @@ void stim(chanend c_stim_ah, chanend c_stim_de, chanend c_mix_ctl) debug_printf("\n"); /* Update the mixer */ + SendTrigger(c_stim_ah, 1); UpdateMixerOutputRouting(c_mix_ctl, map, dst, src); break; @@ -287,43 +171,23 @@ void stim(chanend c_stim_ah, chanend c_stim_de, chanend c_mix_ctl) debug_printf("\n"); /* Update the mixer */ + SendTrigger(c_stim_ah, 1); UpdateMixerOutputRouting(c_mix_ctl, map, dst, src); break; default: - printstrln("ERROR BAD CMD"); + printstr("ERROR: Bad cmd in stim(): "); + printintln(map); break; } /* Update the model */ UpdateModel(modelOut, modelMixerOut, modelIn, map, dst, src); - /* Send expected to AudioHub */ - outuint(c_stim_ah, 0); - for(int i = 0; i < CHANNEL_MAP_AUD_SIZE; i++) - { - outuint(c_stim_ah, modelOut[i]); - } + SendExpected(c_stim_ah, c_stim_de, modelOut, modelIn); - /* Wait for handshake back and move on to next test */ - inuint(c_stim_ah); - - /* Send expected to Decouple */ - outuint(c_stim_de, 0); - for(int i = 0; i < NUM_USB_CHAN_IN; i++) - { - outuint(c_stim_de, modelIn[i]); - } - - /* Wait for handshake back and move on to next test */ - inuint(c_stim_de); } - timer t; - unsigned time; - t :> time; - t when timerafter(time+10000) :> void; - /* Send kill messages to Fake AudioHub & Fake Decouple */ outct(c_stim_ah, XS1_CT_END); inct(c_stim_ah); @@ -335,136 +199,6 @@ void stim(chanend c_stim_ah, chanend c_stim_de, chanend c_mix_ctl) exit(0); } -void CheckBlock(unsigned samplesOut[], uint32_t expectedOut[], size_t len) -{ - for(int j = 0; j < len; j++) - { - debug_printf("%d: Expected: ", j); - PrintSample(expectedOut[j]); - debug_printf("\n"); - if(expectedOut[j] != samplesOut[j]) - { - printstr("ERROR: Actual: "); - PrintSample(samplesOut[j]); - } - assert(expectedOut[j] == samplesOut[j]); - } -} - -/* From xua_audiohub.xc */ -extern unsigned samplesOut[NUM_USB_CHAN_OUT]; -extern unsigned samplesIn[2][NUM_USB_CHAN_IN]; -#include "xua_audiohub_st.h" - -int Fake_XUA_AudioHub(chanend c_mix_aud, chanend c_stim) -{ - int readBuffNo = 0; - unsigned underflowWord = 0; - uint32_t expectedOut[NUM_USB_CHAN_OUT]; - unsigned ct = 0; - - for(size_t i = 0; i < NUM_USB_CHAN_IN; i++) - { - /* Note, we only used readBufNo = 0 */ - unsigned sample = 0; - SET_SOURCE(sample, SRC_AUDIF); - SET_CHANNEL(sample, i); - samplesIn[0][i] = sample; - } - - while(!ct) - { - /* This will populate samplesOut and send out samplesIn[readBuffNo] */ - unsigned command = DoSampleTransfer(c_mix_aud, readBuffNo, underflowWord); - - select - { - case testct_byref(c_stim, ct): - - if(!ct) - { - inuint(c_stim); // TODO don't really need this - - /* Get expected */ - for(int j = 0; j < NUM_USB_CHAN_OUT; j++) - { - expectedOut[j] = inuint(c_stim); - } - - CheckBlock(samplesOut, expectedOut, NUM_USB_CHAN_OUT); - - /* Handshake back */ - outuint(c_stim, 0); - } - break; - - default: - break; - } - } - - outct(c_stim, XS1_CT_END); - inct(c_stim); - return 0; -} - -int Fake_XUA_Buffer_Decouple(chanend c_dec_mix, chanend c_stim) -{ - unsigned tmp; - uint32_t expectedSamplesIn[NUM_USB_CHAN_IN]; - unsigned samplesIn[NUM_USB_CHAN_IN]; - unsigned ct; - unsigned underflowSample; - - while(!ct) - { - select - { - case inuint_byref(c_dec_mix, underflowSample): - - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - unsigned sample = 0; - SET_SOURCE(sample, SRC_HOST); - SET_CHANNEL(sample, i); - outuint(c_dec_mix, sample); - } - - for(int i = 0; i < NUM_USB_CHAN_IN; i++) - { - samplesIn[i] = inuint(c_dec_mix); - } - break; - - case testct_byref(c_stim, ct): - - if(!ct) - { - inuint(c_stim); // TODO don't really need this - - /* Get expected */ - for(int j = 0; j < NUM_USB_CHAN_IN; j++) - { - expectedSamplesIn[j] = inuint(c_stim); - } - - CheckBlock(samplesIn, expectedSamplesIn, NUM_USB_CHAN_IN); - - /* Handshake back */ - outuint(c_stim, 0); - } - break; - - default: - break; - } - } - - outct(c_stim, XS1_CT_END); - inct(c_stim); - return 0; -} - int main() { chan c_dec_mix; @@ -487,3 +221,4 @@ int main() /* TODO to hit this we need to fully close down i.e. kill mixer */ return 0; } + diff --git a/tests/test_mixer_routing_output/src/mixer_test_shared.h b/tests/test_mixer_routing_output/src/mixer_test_shared.h new file mode 100644 index 00000000..b586059f --- /dev/null +++ b/tests/test_mixer_routing_output/src/mixer_test_shared.h @@ -0,0 +1,323 @@ +// Copyright 2023 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#ifndef TEST_SEED +#error TEST_SEED must be defined! +#endif + +/* A limitation of the design is that the number of routable output destinations cannot be larger than NUM_USB_CHAN_OUT. + * This is due to the transfer samples from Mixer to AudioHub tasks being in blocks of NUM_USB_CHAN_OUT. + * This is not normally an issue - since every physical output interface channel on the device is normally derived from a + * USB channel from the host, but it certainly is a restriction. + */ +#define CHANNEL_MAP_AUD_SIZE NUM_USB_CHAN_OUT + +/* Number of channel sources, the channel ordering is as follows + * i.e. + * [0:NUM_USB_CHAN_OUT-1] : Channels from USB Host + * [NUM_USB_CHAN_OUT:NUM_USB_CHAN_IN-1] : Channels from Audio Interfaces + * [NUM_USB_CHAN_N:MAX_MIX_COUNT-1] : Channels from Mixers + * [MAX_MIX_COUNT]: "Off" (Essentially samples always 0) + */ +/* Note, One larger for an "off" channel for mixer sources" */ +#define SOURCE_COUNT (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1) + +#define SET_EXPECTED (9) +#define TRIGGER (7) + +// Test sample format: +// byte[0]: Sample counter +// byte[1]: Channel +// byte[3]: Source (HOST:1/AUD IF:0) +#define SRC_HOST (2) +#define SRC_AUDIF (1) +#define SRC_OFF (0) // Important that this is 0 since mixer will generate 0 samples for 'off' + +#define GET_COUNT(x) ((x>>8) & 0xff) +#define GET_CHANNEL(x) ((x >> 16) & 0xff) +#define GET_SOURCE(x) ((x >> 24) & 0xff) + +#define SET_COUNT(x, y) y = y & 0xff; x = x | (y<<8); +#define SET_CHANNEL(x, y) y = y & 0xff; x = x | (y<<16); +#define SET_SOURCE(x, y) x = x | (y<<24); + +void exit(int); + +#pragma select handler +static inline void testct_byref(chanend c, unsigned &isCt) +{ + isCt = testct(c); +} + +void SendTrigger(chanend c_stim_ah, int count) +{ + for(int i = 0; i < count; i++) + outuint(c_stim_ah, TRIGGER); +} + +uint32_t CreateSample(uint32_t modelMixerOutput[], int src) +{ + uint32_t sample = 0; + + if(src == (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT)) + { + SET_SOURCE(sample, SRC_OFF); + } + else if(src >= (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN)) + { + src -= (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN); + sample = modelMixerOutput[src]; + } + else if (src >= NUM_USB_CHAN_IN) + { + SET_SOURCE(sample, SRC_AUDIF); + src -= NUM_USB_CHAN_OUT; + SET_CHANNEL(sample, src); + } + else + { + SET_SOURCE(sample, SRC_HOST); + SET_CHANNEL(sample, src); + } + + return sample; +} + +void PrintSourceString(unsigned source) +{ + debug_printf(" "); + if(source < NUM_USB_CHAN_OUT) + { + debug_printf("(DEVICE IN - HOST%d)", source); + } + else if(source < (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN)) + { + debug_printf("(DEVICE IN - AudioIF %d)", source - NUM_USB_CHAN_OUT); + } + else if(source < (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT)) + { + debug_printf("(MIX %d)", source - NUM_USB_CHAN_OUT - NUM_USB_CHAN_IN); + } + else + debug_printf("(off)"); + debug_printf(" "); +} + +void PrintDestString(unsigned map, unsigned dest) +{ + switch(map) + { + case SET_SAMPLES_TO_DEVICE_MAP: + debug_printf("(DEVICE OUT - AudioIF)"); + break; + case SET_SAMPLES_TO_HOST_MAP: + debug_printf("(DEVICE OUT - HOST)"); + break; + } +} + +void PrintSample(unsigned sample) +{ + debug_printf("SOURCE: "); + if(GET_SOURCE(sample) == SRC_HOST) + debug_printf("HOST "); + else if(GET_SOURCE(sample) == SRC_AUDIF) + debug_printf("AUDIF "); + else if(GET_SOURCE(sample) == SRC_OFF) + debug_printf("OFF "); + else + debug_printf("UNKNOWN "); + + debug_printf("CHANNEL: %d", GET_CHANNEL(sample)); +} + +/* Required by lib_xua */ +void AudioHwInit() +{ + return; +} + +/* Required by lib_xua */ +void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) +{ + return; +} + +/* From xua_ep0_uacreqs.xc */ +void UpdateMixerOutputRouting(chanend c_mix_ctl, unsigned map, unsigned dst, unsigned src); +void UpdateMixMap(chanend c_mix_ctl, int mix, int input, int src); +void UpdateMixerWeight(chanend c_mix_ctl, int mix, int index, unsigned val); + +void CheckBlock(unsigned samplesOut[], uint32_t expectedOut[], size_t len) +{ + int fail = 0;; + for(int j = 0; j < len; j++) + { + debug_printf("%d: Expected: ", j); + PrintSample(expectedOut[j]); + debug_printf("\n"); + if(expectedOut[j] != samplesOut[j]) + { + printstr("ERROR: Actual: "); + PrintSample(samplesOut[j]); + debug_printf(" (%x)", samplesOut[j]); + printstr("\n"); + fail = 1; + } + //assert(expectedOut[j] == samplesOut[j]); + } + assert(!fail); +} + +/* Sending expected also causes fake_audiohub and fake_decouple to run sample checks */ +void SendExpected(chanend c_stim_ah, chanend c_stim_de, uint32_t modelOut[], uint32_t modelIn[]) +{ + /* Send expected to AudioHub */ + outuint(c_stim_ah, SET_EXPECTED); + + for(int i = 0; i < CHANNEL_MAP_AUD_SIZE; i++) + { + outuint(c_stim_ah, modelOut[i]); + } + + /* Wait for handshake back and move on to next test */ + inuint(c_stim_ah); + + /* Send expected to Decouple */ + outuint(c_stim_de, SET_EXPECTED); + for(int i = 0; i < NUM_USB_CHAN_IN; i++) + { + outuint(c_stim_de, modelIn[i]); + } + + /* Wait for handshake back and move on to next test */ + inuint(c_stim_de); +} + + + + +/* From xua_audiohub.xc */ +extern unsigned samplesOut[NUM_USB_CHAN_OUT]; +extern unsigned samplesIn[2][NUM_USB_CHAN_IN]; +#include "xua_audiohub_st.h" + +int Fake_XUA_AudioHub(chanend c_mix_aud, chanend c_stim) +{ + int readBuffNo = 0; + unsigned underflowWord = 0; + uint32_t expectedOut[NUM_USB_CHAN_OUT]; + unsigned ct = 0; + unsigned cmd = 0; + + for(size_t i = 0; i < NUM_USB_CHAN_IN; i++) + { + /* Note, we only used readBufNo = 0 */ + unsigned sample = 0; + SET_SOURCE(sample, SRC_AUDIF); + SET_CHANNEL(sample, i); + samplesIn[0][i] = sample; + } + + while(!ct) + { + + select + { + case testct_byref(c_stim, ct): + + if(!ct) + { + cmd = inuint(c_stim); + + switch(cmd) + { + case SET_EXPECTED: + + for(int j = 0; j < NUM_USB_CHAN_OUT; j++) + { + expectedOut[j] = inuint(c_stim); + } + + debug_printf("AudioHub:\n"); + CheckBlock(samplesOut, expectedOut, NUM_USB_CHAN_OUT); + /* Handshake back */ + outuint(c_stim, 0); + break; + + case TRIGGER: + /* This will populate samplesOut and send out samplesIn[readBuffNo] */ + unsigned command = DoSampleTransfer(c_mix_aud, readBuffNo, underflowWord); + break; + + default: + printstr("ERROR: bad cmd in Fake_XUA_AudioHub: "); + printintln(cmd); + assert(0); + break; + } + } + break; + } + } + + outct(c_stim, XS1_CT_END); + inct(c_stim); + return 0; +} + +int Fake_XUA_Buffer_Decouple(chanend c_dec_mix, chanend c_stim) +{ + uint32_t expectedSamplesIn[NUM_USB_CHAN_IN]; + unsigned samplesIn[NUM_USB_CHAN_IN]; + unsigned ct; + unsigned underflowSample; + + while(!ct) + { + select + { + case inuint_byref(c_dec_mix, underflowSample): + + for(int i = 0; i < NUM_USB_CHAN_OUT; i++) + { + unsigned sample = 0; + SET_SOURCE(sample, SRC_HOST); + SET_CHANNEL(sample, i); + outuint(c_dec_mix, sample); + } + + for(int i = 0; i < NUM_USB_CHAN_IN; i++) + { + samplesIn[i] = inuint(c_dec_mix); + } + + break; + + case testct_byref(c_stim, ct): + + if(!ct) + { + inuint(c_stim); // TODO don't really need this + + /* Get expected */ + for(int j = 0; j < NUM_USB_CHAN_IN; j++) + { + expectedSamplesIn[j] = inuint(c_stim); + } + + debug_printf("Decouple:\n"); + CheckBlock(samplesIn, expectedSamplesIn, NUM_USB_CHAN_IN); + + /* Handshake back */ + outuint(c_stim, 0); + } + break; + } + } + + outct(c_stim, XS1_CT_END); + inct(c_stim); + return 0; +} + +