From c51ee0c46030d151c3315772dbbcb22d7a44873b Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 21 Nov 2022 20:05:20 +0000 Subject: [PATCH 01/26] Removed extra whitespace from example makefiles --- examples/AN00246_xua_example/Makefile | 1 - examples/AN00247_xua_example_spdif_tx/Makefile | 1 - examples/AN00248_xua_example_pdm_mics/Makefile | 1 - 3 files changed, 3 deletions(-) diff --git a/examples/AN00246_xua_example/Makefile b/examples/AN00246_xua_example/Makefile index a2c5ccdf..4efaa759 100644 --- a/examples/AN00246_xua_example/Makefile +++ b/examples/AN00246_xua_example/Makefile @@ -21,4 +21,3 @@ USED_MODULES = lib_xua lib_xud lib_i2c XMOS_MAKE_PATH ?= ../.. include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common - diff --git a/examples/AN00247_xua_example_spdif_tx/Makefile b/examples/AN00247_xua_example_spdif_tx/Makefile index 43f0f3fe..046f3659 100644 --- a/examples/AN00247_xua_example_spdif_tx/Makefile +++ b/examples/AN00247_xua_example_spdif_tx/Makefile @@ -20,4 +20,3 @@ USED_MODULES = lib_xua lib_xud lib_spdif XMOS_MAKE_PATH ?= ../.. include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common - diff --git a/examples/AN00248_xua_example_pdm_mics/Makefile b/examples/AN00248_xua_example_pdm_mics/Makefile index 5adce1f7..b43c1925 100644 --- a/examples/AN00248_xua_example_pdm_mics/Makefile +++ b/examples/AN00248_xua_example_pdm_mics/Makefile @@ -19,4 +19,3 @@ USED_MODULES = lib_xua lib_xud lib_mic_array XMOS_MAKE_PATH ?= ../.. include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common - From 395c88cb22977bc9a8a863b9069d21d4408dad3d Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 10 Jan 2023 11:27:37 +0000 Subject: [PATCH 02/26] - Removed unused mixer variable. - Use of mixer defines rather than fixed values --- lib_xua/src/core/endpoint0/xua_endpoint0.c | 5 ++--- lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib_xua/src/core/endpoint0/xua_endpoint0.c b/lib_xua/src/core/endpoint0/xua_endpoint0.c index d69fb57e..165356f5 100755 --- a/lib_xua/src/core/endpoint0/xua_endpoint0.c +++ b/lib_xua/src/core/endpoint0/xua_endpoint0.c @@ -107,8 +107,7 @@ int volsIn[NUM_USB_CHAN_IN + 1]; unsigned int mutesIn[NUM_USB_CHAN_IN + 1]; #ifdef MIXER -unsigned char mixer1Crossbar[18]; -short mixer1Weights[18*8]; +short mixer1Weights[MIX_INPUTS * MAX_MIX_COUNT]; unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; unsigned char channelMapAud[NUM_USB_CHAN_OUT]; @@ -427,7 +426,7 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c #ifdef MIXER /* Set up mixer default state */ - for (int i = 0; i < 18*8; i++) + for (int i = 0; i < MIXER_INPUTS * MAX_MIX_COUNT; i++) { mixer1Weights[i] = 0x8001; //-inf } diff --git a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc index b2085eb7..32fd997a 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc +++ b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc @@ -32,7 +32,6 @@ extern unsigned int mutesIn[]; /* Mixer settings */ #ifdef MIXER -extern unsigned char mixer1Crossbar[]; extern short mixer1Weights[]; /* Device channel mapping */ From da7c45500d35d685468ea3bd9a407f6baf9560df Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 16 Jan 2023 17:28:04 +0000 Subject: [PATCH 03/26] - Added test_mixer_routing_output - Various buffers no longer marked static to allow for easier unit testing - Added some comments and removed some dead code from the implementation - Moved mixer control comms to functions for unit test convenience --- lib_xua/src/core/audiohub/xua_audiohub.xc | 6 +- lib_xua/src/core/endpoint0/xua_endpoint0.c | 24 +- lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc | 79 ++- tests/conftest.py | 17 + tests/test_mixer_routing_output.py | 45 ++ tests/test_mixer_routing_output/Makefile | 11 + tests/test_mixer_routing_output/src/main.xc | 493 ++++++++++++++++++ .../src/test_xs3_600.xn | 24 + .../test_mixer_routing_output/src/xua_conf.h | 45 ++ 9 files changed, 702 insertions(+), 42 deletions(-) create mode 100644 tests/test_mixer_routing_output.py create mode 100644 tests/test_mixer_routing_output/Makefile create mode 100644 tests/test_mixer_routing_output/src/main.xc create mode 100644 tests/test_mixer_routing_output/src/test_xs3_600.xn create mode 100644 tests/test_mixer_routing_output/src/xua_conf.h diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 75a9124c..c2e4b021 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -43,12 +43,12 @@ #define MAX(x,y) ((x)>(y) ? (x) : (y)) -static unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)]; +unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)]; /* Two buffers for ADC data to allow for DAC and ADC I2S ports being offset */ #define IN_CHAN_COUNT (I2S_CHANS_ADC + XUA_NUM_PDM_MICS + (8*XUA_ADAT_RX_EN) + (2*XUA_SPDIF_RX_EN)) -static unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)]; +unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)]; #ifdef XTA_TIMING_AUDIO #pragma xta command "add exclusion received_command" @@ -91,7 +91,7 @@ unsigned dsdMode = DSD_MODE_OFF; #endif #pragma unsafe arrays -static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) +unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) { if(XUA_USB_EN) { diff --git a/lib_xua/src/core/endpoint0/xua_endpoint0.c b/lib_xua/src/core/endpoint0/xua_endpoint0.c index 165356f5..f62abcb4 100755 --- a/lib_xua/src/core/endpoint0/xua_endpoint0.c +++ b/lib_xua/src/core/endpoint0/xua_endpoint0.c @@ -109,9 +109,14 @@ unsigned int mutesIn[NUM_USB_CHAN_IN + 1]; #ifdef MIXER short mixer1Weights[MIX_INPUTS * MAX_MIX_COUNT]; -unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; +//unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; +/* Mapping of channels to output audio interfaces */ unsigned char channelMapAud[NUM_USB_CHAN_OUT]; + +/* Mapping of channels to USB host */ unsigned char channelMapUsb[NUM_USB_CHAN_IN]; + +/* Mapping of channels to Mixer(s) */ unsigned char mixSel[MAX_MIX_COUNT][MIX_INPUTS]; #endif @@ -426,12 +431,13 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c #ifdef MIXER /* Set up mixer default state */ - for (int i = 0; i < MIXER_INPUTS * MAX_MIX_COUNT; i++) + for (int i = 0; i < MIX_INPUTS * MAX_MIX_COUNT; i++) { mixer1Weights[i] = 0x8001; //-inf } /* Configure default connections */ + // TODO this should be a loop using defines. mixer1Weights[0] = 0; mixer1Weights[9] = 0; mixer1Weights[18] = 0; @@ -456,20 +462,6 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c } #endif - /* Set up channel mapping default */ - for (int i = 0; i < NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN; i++) - { - channelMap[i] = i; - } - -#if MAX_MIX_COUNT > 0 - /* Mixer outputs mapping defaults */ - for (int i = 0; i < MAX_MIX_COUNT; i++) - { - channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i] = i; - } -#endif - /* Init mixer inputs */ for(int j = 0; j < MAX_MIX_COUNT; j++) for(int i = 0; i < MIX_INPUTS; i++) diff --git a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc index 32fd997a..a9758ef7 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc +++ b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc @@ -265,6 +265,32 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl) } #endif +void UpdateMixerOutputRouting(chanend c_mix_ctl, unsigned map, unsigned dst, unsigned src) +{ + outuint(c_mix_ctl, map); + outuint(c_mix_ctl, dst); + outuint(c_mix_ctl, src); + outct(c_mix_ctl, XS1_CT_END); +} + +void UpdateMixMap(chanend c_mix_ctl, int mix, int input, int src) +{ + outuint(c_mix_ctl, SET_MIX_MAP); + outuint(c_mix_ctl, mix); /* Mix bus */ + outuint(c_mix_ctl, input); /* Mixer input (cn) */ + outuint(c_mix_ctl, src); /* Source (mixSel[cn]) */ + outct(c_mix_ctl, XS1_CT_END); +} + +void UpdateMixerWeight(chanend c_mix_ctl, int mix, int index, unsigned val) +{ + outuint(c_mix_ctl, SET_MIX_MULT); + outuint(c_mix_ctl, mix); + outuint(c_mix_ctl, index); + outuint(c_mix_ctl, val); + outct(c_mix_ctl, XS1_CT_END); +} + /* Handles the audio class specific requests * returns: XUD_RES_OKAY if request dealt with successfully without error, * XUD_RES_RST for device reset @@ -651,10 +677,12 @@ 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); + //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 */ return XUD_DoSetRequestStatus(ep0_in); } @@ -689,10 +717,12 @@ 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); + //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); } } @@ -744,21 +774,23 @@ 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); + //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); + 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 */ + //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]); } return XUD_DoSetRequestStatus(ep0_in); @@ -810,11 +842,12 @@ 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_MIX_MULT); - outuint(c_mix_ctl, (sp.wValue & 0xff) % 8); - outuint(c_mix_ctl, (sp.wValue & 0xff) / 8); - outuint(c_mix_ctl, volume); - outct(c_mix_ctl, XS1_CT_END); + //outuint(c_mix_ctl, SET_MIX_MULT); + //outuint(c_mix_ctl, (sp.wValue & 0xff) % 8); + //outuint(c_mix_ctl, (sp.wValue & 0xff) / 8); + //outuint(c_mix_ctl, volume); + //outct(c_mix_ctl, XS1_CT_END); + UpdateMixerWeight(c_mix_ctl, (sp.wValue & 0xff) % 8, (sp.wValue & 0xff) / 8, volume); } /* Send 0 Length as status stage */ diff --git a/tests/conftest.py b/tests/conftest.py index f5cca7f7..61945cad 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,23 @@ # Copyright 2022 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. import pytest +import time + + +@pytest.fixture() +def test_file(request): + return str(request.node.fspath) + + +@pytest.fixture(scope="session") # Use same seed for whole run +def test_seed(request): + + seed = str(int(time.time())) + # We dont need the following since pytest will print the values of our fixtures on a failure + # capmanager = request.config.pluginmanager.getplugin("capturemanager") + # with capmanager.global_and_fixture_disabled(): + # print("Using seed: "+ seed) + return seed def pytest_addoption(parser): diff --git a/tests/test_mixer_routing_output.py b/tests/test_mixer_routing_output.py new file mode 100644 index 00000000..a7893bf5 --- /dev/null +++ b/tests/test_mixer_routing_output.py @@ -0,0 +1,45 @@ +# Copyright 2022 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 = 1500000 + + 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_output(options, capfd, test_file, test_seed): + + result = do_test(options, capfd, test_file, test_seed) + + assert result diff --git a/tests/test_mixer_routing_output/Makefile b/tests/test_mixer_routing_output/Makefile new file mode 100644 index 00000000..70e16ec3 --- /dev/null +++ b/tests/test_mixer_routing_output/Makefile @@ -0,0 +1,11 @@ + +TEST_FLAGS ?= -DTEST_SEED=$(TEST_SEED) + +XCC_FLAGS = -O3 -g -DDEBUG_PRINT_ENABLE_main=0 $(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_output/src/main.xc b/tests/test_mixer_routing_output/src/main.xc new file mode 100644 index 00000000..fcd05ca7 --- /dev/null +++ b/tests/test_mixer_routing_output/src/main.xc @@ -0,0 +1,493 @@ +// TODO +// - use lib_random +// - use random seed from pytest + +// Copyright 2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +/* Tests that routing of mixer outputs behaves as expected + * + * "Outputs" from the device are to the USB host of one of the various audio interaces supported. + + * This test assumes/checks the default routing for the USB host & audio interfaces is as follows: + * + * USB_FROM_HOST[0] -> AUD_INTERFACE_OUTPUT[0] + * USB_FROM_HOST[1] -> AUD_INTERFACE_OUTPUT[1] + * ... + * USB_TO_HOST[0] <- AUD_INTERFACE_INPUT[0] + * USB_TO_HOST[1] <- AUD_INTERFACE_INPUT[1] + * ... + * + * 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] + * ... + * + * (If the number of mixer inputs > NUM_USB_CHAN_OUT then see ordering in comment regarding + * SOURCE_COUNT below) + * + * By default none of the MAX_MIX_COUNT output from the mixers are routed anywwhere, but this test ensures + * that they can be. + * + * This test assumes that none of the mixer weights are changed. + * This test does not test changing the inputs to the mixer. +*/ +#include +#include +#include "platform.h" +#include "xua.h" +#define DEBUG_UNIT main +#include "debug_print.h" +#include "assert.h" +#include "random.h" + +#ifndef TEST_ITERATIONS +#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); + +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) +{ + unsigned 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 = modelMixerOut[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); + } + + switch(map) + { + case SET_SAMPLES_TO_DEVICE_MAP: + modelOut[dst] = sample; + break; + + case SET_SAMPLES_TO_HOST_MAP: + modelIn[dst] = sample; + break; + + default: + assert(0); + break; + } +} + +/* This task configures the routing and maintains a model of the expected routing output + * it provides this to the Fake AudioHub and Fake Decouple tasks such that they can self check + */ +void stim(chanend c_stim_ah, chanend c_stim_de, chanend c_mix_ctl) +{ + uint32_t modelOut[CHANNEL_MAP_AUD_SIZE]; + uint32_t modelIn[NUM_USB_CHAN_IN]; + uint32_t modelMixerOut[MAX_MIX_COUNT]; + 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 + */ + for(size_t i = 0; i < MAX_MIX_COUNT; i++) + { + uint32_t sample = 0; + SET_SOURCE(sample, SRC_HOST); + SET_CHANNEL(sample, i); + modelMixerOut[i] = sample; + } + + /* Init modelOut for default routing */ + /* Default routing is USB[0] -> AUD_IF[0] etc */ + for(size_t i = 0; i < CHANNEL_MAP_AUD_SIZE; i++) + { + uint32_t sample = 0; + SET_SOURCE(sample, SRC_HOST); + SET_CHANNEL(sample, i); + modelOut[i] = sample; + } + + /* Init modelIn for default routing */ + /* Default routing is AUD_IF[0] -> USB[0] etc */ + for(size_t i = 0; i < NUM_USB_CHAN_IN; i++) + { + uint32_t sample = 0; + SET_SOURCE(sample, SRC_AUDIF); + SET_CHANNEL(sample, i); + 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); + + for(int testIter = 0; testIter < TEST_ITERATIONS; testIter++) + { + /* Make a random update to the routing - route a random source to a random destination */ + unsigned map = testCmd[random_get_random_number(rg) % (sizeof(testCmd)/sizeof(testCmd[0]))]; + unsigned dst = random_get_random_number(rg) % CHANNEL_MAP_AUD_SIZE; + unsigned src = random_get_random_number(rg) % NUM_USB_CHAN_OUT; + + switch(map) + { + case SET_SAMPLES_TO_DEVICE_MAP: + debug_printf("Mapping output to AudioIF: %d", dst); + PrintDestString(map, dst); + debug_printf(" from %d", src); + PrintSourceString(src); + debug_printf("\n"); + + /* Update the mixer */ + UpdateMixerOutputRouting(c_mix_ctl, map, dst, src); + break; + + case SET_SAMPLES_TO_HOST_MAP: + debug_printf("Mapping output to Host : %d", dst); + PrintDestString(map, dst); + debug_printf(" from %d", src); + PrintSourceString(src); + debug_printf("\n"); + + /* Update the mixer */ + UpdateMixerOutputRouting(c_mix_ctl, map, dst, src); + break; + + default: + printstrln("ERROR BAD CMD"); + 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]); + } + + /* 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); + + outct(c_stim_de, XS1_CT_END); + inct(c_stim_de); + + printstrln("PASS"); + 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 */ +unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord); +extern unsigned samplesOut[NUM_USB_CHAN_OUT]; +extern unsigned samplesIn[2][NUM_USB_CHAN_IN]; + +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; + chan c_mix_aud; + chan c_mix_ctl; + chan c_stim_ah; + chan c_stim_de; + + par + { + Fake_XUA_Buffer_Decouple(c_dec_mix, c_stim_de); + Fake_XUA_AudioHub(c_mix_aud, c_stim_ah); + + /* Mixer from lib_xua */ + mixer(c_dec_mix, c_mix_aud, c_mix_ctl); + + stim(c_stim_ah, c_stim_de, c_mix_ctl); + } + + /* 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/test_xs3_600.xn b/tests/test_mixer_routing_output/src/test_xs3_600.xn new file mode 100644 index 00000000..20e8eeb6 --- /dev/null +++ b/tests/test_mixer_routing_output/src/test_xs3_600.xn @@ -0,0 +1,24 @@ + + + + tileref tile[2] + + + + + + + + + + + + + + + + + + diff --git a/tests/test_mixer_routing_output/src/xua_conf.h b/tests/test_mixer_routing_output/src/xua_conf.h new file mode 100644 index 00000000..80509712 --- /dev/null +++ b/tests/test_mixer_routing_output/src/xua_conf.h @@ -0,0 +1,45 @@ +// Copyright 2016-2022 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 From 513761ef5b9262e0dca22f4caa920dbac56a2936 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 17 Jan 2023 11:33:52 +0000 Subject: [PATCH 04/26] Moved DoSampleTransfer to a header file so it can still be inlined (but also used in unit tests). Resolves fails in test_i2s_loopback --- lib_xua/api/xua_audiohub.h | 8 +-- lib_xua/src/core/audiohub/xua_audiohub.xc | 63 +-------------------- lib_xua/src/core/audiohub/xua_audiohub_st.h | 63 +++++++++++++++++++++ tests/test_mixer_routing_output/src/main.xc | 2 +- 4 files changed, 69 insertions(+), 67 deletions(-) create mode 100644 lib_xua/src/core/audiohub/xua_audiohub_st.h diff --git a/lib_xua/api/xua_audiohub.h b/lib_xua/api/xua_audiohub.h index 485abb0d..5f3e9ca2 100644 --- a/lib_xua/api/xua_audiohub.h +++ b/lib_xua/api/xua_audiohub.h @@ -1,9 +1,9 @@ // Copyright 2011-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. -#ifndef __XUA_AUDIOHUB_H__ -#define __XUA_AUDIOHUB_H__ +#ifndef _XUA_AUDIOHUB_H_ +#define _XUA_AUDIOHUB_H_ -#if __XC__ +#ifdef __XC__ #include "xccompat.h" #include "xs1.h" @@ -80,4 +80,4 @@ void UserBufferManagementInit(); void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]); -#endif // __XUA_AUDIOHUB_H__ +#endif // _XUA_AUDIOHUB_H_ diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index c2e4b021..b10bc3d9 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -90,68 +90,7 @@ unsigned dsdMode = DSD_MODE_OFF; #include "audiohub_adat.h" #endif -#pragma unsafe arrays -unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) -{ - if(XUA_USB_EN) - { - outuint(c_out, underflowWord); - - /* Check for sample freq change (or other command) or new samples from mixer*/ - if(testct(c_out)) - { - unsigned command = inct(c_out); -#ifndef CODEC_MASTER - if(dsdMode == DSD_MODE_OFF) - { -#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) - /* Set clocks low */ - p_lrclk <: 0; - p_bclk <: 0; -#endif - } - else - { -#if(DSD_CHANS_DAC != 0) - /* DSD Clock might not be shared with lrclk or bclk... */ - p_dsd_clk <: 0; -#endif - } -#endif -#if (DSD_CHANS_DAC > 0) - if(dsdMode == DSD_MODE_DOP) - dsdMode = DSD_MODE_OFF; -#endif - return command; - } - else - { -#if NUM_USB_CHAN_OUT > 0 -#pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - int tmp = inuint(c_out); - samplesOut[i] = tmp; - } -#else - inuint(c_out); -#endif - UserBufferManagement(samplesOut, samplesIn[readBuffNo]); - -#if NUM_USB_CHAN_IN > 0 -#pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_IN; i++) - { - outuint(c_out, samplesIn[readBuffNo][i]); - } -#endif - } - } - else - UserBufferManagement(samplesOut, samplesIn[readBuffNo]); - - return 0; -} +#include "xua_audiohub_st.h" static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:32 p_lrclk) { diff --git a/lib_xua/src/core/audiohub/xua_audiohub_st.h b/lib_xua/src/core/audiohub/xua_audiohub_st.h new file mode 100644 index 00000000..80c651fb --- /dev/null +++ b/lib_xua/src/core/audiohub/xua_audiohub_st.h @@ -0,0 +1,63 @@ +#pragma unsafe arrays +inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) +{ + if(XUA_USB_EN) + { + outuint(c_out, underflowWord); + + /* Check for sample freq change (or other command) or new samples from mixer*/ + if(testct(c_out)) + { + unsigned command = inct(c_out); +#ifndef CODEC_MASTER + if(dsdMode == DSD_MODE_OFF) + { +#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) + /* Set clocks low */ + p_lrclk <: 0; + p_bclk <: 0; +#endif + } + else + { +#if(DSD_CHANS_DAC != 0) + /* DSD Clock might not be shared with lrclk or bclk... */ + p_dsd_clk <: 0; +#endif + } +#endif +#if (DSD_CHANS_DAC > 0) + if(dsdMode == DSD_MODE_DOP) + dsdMode = DSD_MODE_OFF; +#endif + return command; + } + else + { +#if NUM_USB_CHAN_OUT > 0 +#pragma loop unroll + for(int i = 0; i < NUM_USB_CHAN_OUT; i++) + { + int tmp = inuint(c_out); + samplesOut[i] = tmp; + } +#else + inuint(c_out); +#endif + UserBufferManagement(samplesOut, samplesIn[readBuffNo]); + +#if NUM_USB_CHAN_IN > 0 +#pragma loop unroll + for(int i = 0; i < NUM_USB_CHAN_IN; i++) + { + outuint(c_out, samplesIn[readBuffNo][i]); + } +#endif + } + } + else + UserBufferManagement(samplesOut, samplesIn[readBuffNo]); + + return 0; +} + diff --git a/tests/test_mixer_routing_output/src/main.xc b/tests/test_mixer_routing_output/src/main.xc index fcd05ca7..f5afd627 100644 --- a/tests/test_mixer_routing_output/src/main.xc +++ b/tests/test_mixer_routing_output/src/main.xc @@ -356,9 +356,9 @@ void CheckBlock(unsigned samplesOut[], uint32_t expectedOut[], size_t len) } /* From xua_audiohub.xc */ -unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord); 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) { From 8966ad1bb95a221ee23b6c349d8282424069dcd4 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 17 Jan 2023 11:39:22 +0000 Subject: [PATCH 05/26] Add external linkage to inline DoSampleTransfer --- lib_xua/src/core/audiohub/xua_audiohub_st.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib_xua/src/core/audiohub/xua_audiohub_st.h b/lib_xua/src/core/audiohub/xua_audiohub_st.h index 80c651fb..7669c799 100644 --- a/lib_xua/src/core/audiohub/xua_audiohub_st.h +++ b/lib_xua/src/core/audiohub/xua_audiohub_st.h @@ -1,3 +1,5 @@ +extern unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord); + #pragma unsafe arrays inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) { From 2404eaf35f3c77e1313fd27b9f27e3f53409a206 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 17 Jan 2023 11:53:44 +0000 Subject: [PATCH 06/26] Remove extern, mark static inline --- lib_xua/api/xua_audiohub.h | 2 +- lib_xua/src/core/audiohub/xua_audiohub.xc | 3 +-- lib_xua/src/core/audiohub/xua_audiohub_st.h | 6 ++++-- lib_xua/src/core/endpoint0/xua_endpoint0.c | 2 +- lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc | 2 +- tests/conftest.py | 2 +- tests/test_mixer_routing_output/src/main.xc | 6 +----- tests/test_mixer_routing_output/src/xua_conf.h | 2 +- 8 files changed, 11 insertions(+), 14 deletions(-) diff --git a/lib_xua/api/xua_audiohub.h b/lib_xua/api/xua_audiohub.h index 5f3e9ca2..4d018c1f 100644 --- a/lib_xua/api/xua_audiohub.h +++ b/lib_xua/api/xua_audiohub.h @@ -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. #ifndef _XUA_AUDIOHUB_H_ #define _XUA_AUDIOHUB_H_ diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index b10bc3d9..4853822c 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.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. /** * @file xua_audiohub.xc @@ -89,7 +89,6 @@ unsigned dsdMode = DSD_MODE_OFF; #if (XUA_ADAT_TX_EN) #include "audiohub_adat.h" #endif - #include "xua_audiohub_st.h" static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:32 p_lrclk) diff --git a/lib_xua/src/core/audiohub/xua_audiohub_st.h b/lib_xua/src/core/audiohub/xua_audiohub_st.h index 7669c799..40dc01e8 100644 --- a/lib_xua/src/core/audiohub/xua_audiohub_st.h +++ b/lib_xua/src/core/audiohub/xua_audiohub_st.h @@ -1,7 +1,9 @@ -extern unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord); +// Copyright 2011-2023 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + #pragma unsafe arrays -inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) +static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) { if(XUA_USB_EN) { diff --git a/lib_xua/src/core/endpoint0/xua_endpoint0.c b/lib_xua/src/core/endpoint0/xua_endpoint0.c index f62abcb4..9a9c0c32 100755 --- a/lib_xua/src/core/endpoint0/xua_endpoint0.c +++ b/lib_xua/src/core/endpoint0/xua_endpoint0.c @@ -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. /** * @brief Implements endpoint zero for an USB Audio 1.0/2.0 device diff --git a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc index a9758ef7..7626cc0e 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc +++ b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.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. /** * @brief Implements relevant requests from the USB Audio 2.0 Specification diff --git a/tests/conftest.py b/tests/conftest.py index 61945cad..3117626c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright 2022 XMOS LIMITED. +# Copyright 2022-2023 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. import pytest import time diff --git a/tests/test_mixer_routing_output/src/main.xc b/tests/test_mixer_routing_output/src/main.xc index f5afd627..1c12700e 100644 --- a/tests/test_mixer_routing_output/src/main.xc +++ b/tests/test_mixer_routing_output/src/main.xc @@ -1,8 +1,4 @@ -// TODO -// - use lib_random -// - use random seed from pytest - -// Copyright 2022 XMOS LIMITED. +// Copyright 2022-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. /* Tests that routing of mixer outputs behaves as expected diff --git a/tests/test_mixer_routing_output/src/xua_conf.h b/tests/test_mixer_routing_output/src/xua_conf.h index 80509712..c27f54a6 100644 --- a/tests/test_mixer_routing_output/src/xua_conf.h +++ b/tests/test_mixer_routing_output/src/xua_conf.h @@ -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. #ifndef _XUA_CONF_H_ #define _XUA_CONF_H_ From 0ce91bec906604f5da31d28b0575ffe386684df4 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 17 Jan 2023 12:12:46 +0000 Subject: [PATCH 07/26] Copyright comment --- lib_xua/src/core/audiohub/xua_audiohub_st.h | 1 - tests/test_mixer_routing_output.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub_st.h b/lib_xua/src/core/audiohub/xua_audiohub_st.h index 40dc01e8..e265de77 100644 --- a/lib_xua/src/core/audiohub/xua_audiohub_st.h +++ b/lib_xua/src/core/audiohub/xua_audiohub_st.h @@ -1,7 +1,6 @@ // Copyright 2011-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. - #pragma unsafe arrays static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord) { diff --git a/tests/test_mixer_routing_output.py b/tests/test_mixer_routing_output.py index a7893bf5..a01e9c7a 100644 --- a/tests/test_mixer_routing_output.py +++ b/tests/test_mixer_routing_output.py @@ -1,4 +1,4 @@ -# Copyright 2022 XMOS LIMITED. +# Copyright 2023 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. import pytest import Pyxsim From 73955c1a4c5030a648dbb8248c8d90908f2bd252 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Wed, 1 Feb 2023 11:54:48 +0000 Subject: [PATCH 08/26] =?UTF-8?q?-=20Added=20mixer=20related=20defines=20t?= =?UTF-8?q?o=20reduce=20use=20of=20magic=20numbers=20-=20Increases=20debug?= =?UTF-8?q?=20output=20when=20DEBUG=20flag=20set=20-=20Removed=20some=20de?= =?UTF-8?q?ad=20code=20-=20Increased=20alignment=20of=20asm=20mixer=20func?= =?UTF-8?q?tions=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; +} + + From 3d50c96595661f6e44b19daa4e5ad7bc73608c44 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 10:59:20 +0000 Subject: [PATCH 09/26] - Removed dead XTA pragmas and code from mixer - Added some more asserts to mixer --- lib_xua/src/core/mixer/mixer.xc | 34 ++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index a5d6795f..ce381e30 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -37,6 +37,8 @@ static unsigned abs(int x) } #endif +static const int SOURCE_COUNT = NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1; + 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" */ unsafe @@ -253,7 +255,6 @@ 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); unsafe { /* Read the actual sample value */ @@ -347,7 +348,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) while (1) { -#pragma xta endpoint "mixer1_req" /* Request from audio()/mixer2() */ request = inuint(c_mixer2); @@ -383,7 +383,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) break; case SET_MIX_MULT: - mix = inuint(c_mix_ctl); index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); @@ -394,22 +393,34 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) write_word_to_mix_mult(mix, index, val); } - assert((index < MIX_INPUTS) && (mix < MAX_MIX_COUNT) && msg("Mix mult index out of range")); + assert((mix < MAX_MIX_COUNT) && msg("Mix mult mix out of range")); + assert((index < MIX_INPUTS) && msg("Mix mult index out of range")); break; case SET_MIX_MAP: - mix = inuint(c_mix_ctl); - index = inuint(c_mix_ctl); /* mixer input */ - val = inuint(c_mix_ctl); /* source */ - inct(c_mix_ctl); + { + unsigned mix = inuint(c_mix_ctl); + unsigned input = inuint(c_mix_ctl); /* mixer input */ + unsigned source = inuint(c_mix_ctl); /* source */ + inct(c_mix_ctl); + + assert((mix < MAX_MIX_COUNT) && msg("Mix map mix out of range")); + assert((input < MIX_INPUTS) && msg("Mix map index out of range")); + assert((source < SOURCE_COUNT) && msg("Mix map source out of range")); + + if((input << MIX_INPUTS) && (mix < MAX_MIX_COUNT) && (source < SOURCE_COUNT)) + { #ifdef FAST_MIXER - setPtr(index, val, mix); + setPtr(index, val, mix); #else - write_word_to_mix_map(mix, index, val); + write_word_to_mix_map(mix, input, source); #endif + } + } break; #endif /* if MAX_MIX_COUNT > 0 */ + #ifdef IN_VOLUME_IN_MIXER case SET_MIX_IN_VOL: index = inuint(c_mix_ctl); @@ -487,7 +498,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) if(testct(c_host)) { int sampFreq; -#pragma xta endpoint "mixer1_rate_change" unsigned command = inct(c_host); switch(command) @@ -624,7 +634,6 @@ static void mixer2(chanend c_mixer1, chanend c_audio) while (1) { -#pragma xta endpoint "mixer2_req" request = inuint(c_audio); /* Forward the request on */ @@ -636,7 +645,6 @@ static void mixer2(chanend c_mixer1, chanend c_audio) if(testct(c_mixer1)) { int sampFreq; -#pragma xta endpoint "mixer2_rate_change" unsigned command = inct(c_mixer1); switch(command) From fd4dfd40a9d3201d710655175287cdabae7134a3 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 11:05:21 +0000 Subject: [PATCH 10/26] Tidy .gitignore --- .gitignore | 55 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 0cffca23..3cc9f3c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,24 @@ -*.log -*.dSYM -*/.build_*/* -*/bin/* -*.o +# XMOS bin files *.xe -*.vcd -*.swo +*.bin +*/bin/* + +# XMOS temp files +.build* +*.a +_build* +*.i *.s *.xi -*.i -*.bin -*~ -*.a -*.swp -*.*~ -*.pyc -.build* +*.o +*/.build_*/* + +# Temp files .DS_Store -test_results.csv -_build* -**/.venv/** -**/.vscode/** -**.egg-info -*.pdf -*tests/logs/* +*.*~ +*.swp +*~ +*.swo # waf build files .lock-waf_* @@ -36,3 +31,19 @@ xscope.xmt # Traces *.gtkw *.vcd + +# Host binaries +host_usb_mixer_control/xmos_mixer + +# Documentation build +*.pdf + +# Misc +*.log +*.dSYM +*.vcd +*.pyc +**/.venv/** +**/.vscode/** +**.egg-info +*tests/logs/* From 0d7224bd6d1fdd79b7a1e4a8e7d9aa8b98d0787b Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 11:06:13 +0000 Subject: [PATCH 11/26] Added -arch for to mixer host app makefile --- host_usb_mixer_control/Makefile.OSX | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/host_usb_mixer_control/Makefile.OSX b/host_usb_mixer_control/Makefile.OSX index d46367f9..aa69f273 100644 --- a/host_usb_mixer_control/Makefile.OSX +++ b/host_usb_mixer_control/Makefile.OSX @@ -1,2 +1,3 @@ all: - g++ -g -o xmos_mixer OSX/usb_mixer.cpp mixer_app.cpp -I. -IOSX OSX/libusb-1.0.0.dylib -m64 \ No newline at end of file + g++ -g -o xmos_mixer OSX/usb_mixer.cpp mixer_app.cpp -I. -IOSX OSX/libusb-1.0.0.dylib -arch x86_64 + From 39ed2354761a028ce2105463a53a2e0645169e07 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 11:06:23 +0000 Subject: [PATCH 12/26] Removed old module_description file --- host_usb_mixer_control/module_description | 1 - 1 file changed, 1 deletion(-) delete mode 100644 host_usb_mixer_control/module_description diff --git a/host_usb_mixer_control/module_description b/host_usb_mixer_control/module_description deleted file mode 100644 index 7c62e64d..00000000 --- a/host_usb_mixer_control/module_description +++ /dev/null @@ -1 +0,0 @@ -Sample code for a host usb mixer app (not this is a host/pc program and cannot be built in the XDE) From fc732b8512b4b4196399e29adb5eec86f971e9b5 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 11:06:40 +0000 Subject: [PATCH 13/26] Updated changelog --- CHANGELOG.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c13729eb..bb19de6c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,10 @@ lib_xua Change Log UNRELEASED ---------- - * FIXED: Exception on startup when USB input disabled + * ADDED: Unit tests for mixer functionalty + * ADDED: Host mixer control applicatons (for Win/macOS) + * CHANGED: Small tidies to mixer implementation + * FIXED: Exception on startup when USB input disabled 3.3.1 ----- From 6754f812c9294adc2175d8c55ac2baaab3c8411c Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 11:08:06 +0000 Subject: [PATCH 14/26] Fixed issues with setting mix map in mixer host app --- host_usb_mixer_control/OSX/usb_mixer.cpp | 73 +++++++++++++++--------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/host_usb_mixer_control/OSX/usb_mixer.cpp b/host_usb_mixer_control/OSX/usb_mixer.cpp index b678a7ed..d7d99beb 100644 --- a/host_usb_mixer_control/OSX/usb_mixer.cpp +++ b/host_usb_mixer_control/OSX/usb_mixer.cpp @@ -139,33 +139,33 @@ int usb_audio_class_get(unsigned char bRequest, unsigned char cs, unsigned char bRequest, (cs<<8) | cn, /* wValue */ (unitID & 0xff) << 8 | 0x0, - data, - wLength, - 0); + data, + wLength, + 0); } /* Issue a generic control/class SET request to a specific unit in the Audio Interface */ int usb_audio_class_set(unsigned char bRequest, unsigned char cs, unsigned char cn, unsigned short unitID, unsigned short wLength, unsigned char *data) { - return libusb_control_transfer(devh, - USB_REQUEST_TO_DEV, + return libusb_control_transfer(devh, + USB_REQUEST_TO_DEV, bRequest, - (cs<<8) | cn, /* wValue */ + (cs<<8) | cn, /* wValue */ (unitID & 0xff) << 8 | 0x0, - data, - wLength, - 0); + data, + wLength, + 0); } /* Note, this never get cached in an object since it can change on the device side */ int usb_mixer_mem_get(unsigned int mixer, unsigned offset, unsigned char *data) { - return libusb_control_transfer(devh, - USB_REQUEST_FROM_DEV, /* nRequest */ - MEM, /* bRequest */ - offset, /* wValue */ - (usb_mixers->usb_mixer[mixer].id & 0xff) << 8 | 0x0, /* wIndex */ - data, 64, 0); + return libusb_control_transfer(devh, + USB_REQUEST_FROM_DEV, /* nRequest */ + MEM, /* bRequest */ + offset, /* wValue */ + (usb_mixers->usb_mixer[mixer].id & 0xff) << 8 | 0x0, /* wIndex */ + data, 64, 0); } static const unsigned char *find_input_term_unit_by_id(const unsigned char *data, int length, int id) @@ -252,7 +252,7 @@ static double dev_get_mixer_value(unsigned int mixer, unsigned int nodeId) { // MU_MIXER_CONTROL 0x01 short data; - usb_audio_class_get(CUR, 0x01<<8, nodeId, usb_mixers->usb_mixer[mixer].id, 2,(unsigned char *) &data); + usb_audio_class_get(CUR, ((unsigned char) (0x01<<8)), nodeId, usb_mixers->usb_mixer[mixer].id, 2,(unsigned char *) &data); return ((double) data / 256); } @@ -435,8 +435,17 @@ int addStrings(const unsigned char *data, int length, int mixer_index, int id, i /* Returns the source of an mix sel output */ static unsigned char get_mixsel_value(unsigned int mixer, unsigned int channel) { + + unsigned char bRequest = CUR; + //unsigned cs = CS_XU_SEL; + unsigned char cs = 1; /* Note, currently the host app configures all mix sel's indentically, so if we get one they all should match */ + unsigned char cn = channel; + unsigned short unitId = usb_mixers->usb_mixSel[mixer].id; + unsigned short wLength = 1; unsigned char data[64]; - usb_audio_class_get(CUR, CS_XU_SEL, channel, usb_mixers->usb_mixSel[mixer].id, 1, (unsigned char *)data); + + usb_audio_class_get(CUR, cs, cn, unitId, wLength, (unsigned char *)data); + return data[0]; } @@ -782,25 +791,27 @@ int usb_mixer_get_layout(unsigned int mixer, unsigned int *inputs, unsigned int /* MixSel getters and setters */ char *usb_mixsel_get_input_string(unsigned int mixer, unsigned int input) { - return usb_mixers->usb_mixSel[mixer].inputStrings[input]; + return usb_mixers->usb_mixSel[mixer].inputStrings[input]; } int usb_mixsel_get_input_count(unsigned int mixer) { - return usb_mixers->usb_mixSel[mixer].numInputs; + return usb_mixers->usb_mixSel[mixer].numInputs; } int usb_mixsel_get_output_count(unsigned int mixer) { - return usb_mixers->usb_mixSel[mixer].numOutputs; + return usb_mixers->usb_mixSel[mixer].numOutputs; } -char *usb_mixer_get_input_name(unsigned int mixer, unsigned int input) { - return usb_mixers->usb_mixer[mixer].input_names[input]; +char *usb_mixer_get_input_name(unsigned int mixer, unsigned int input) +{ + return usb_mixers->usb_mixer[mixer].input_names[input]; } -char *usb_mixer_get_output_name(unsigned int mixer, unsigned int output) { - return usb_mixers->usb_mixer[mixer].output_names[output]; +char *usb_mixer_get_output_name(unsigned int mixer, unsigned int output) +{ + return usb_mixers->usb_mixer[mixer].output_names[output]; } unsigned char usb_mixsel_get_state(unsigned int mixer, unsigned int channel) @@ -810,13 +821,19 @@ unsigned char usb_mixsel_get_state(unsigned int mixer, unsigned int channel) void usb_mixsel_set_state(unsigned int mixer, unsigned int dst, unsigned int src) { - // write to device - usb_audio_class_set(CUR, CS_XU_SEL, dst, usb_mixers->usb_mixSel[mixer].id, 1, (unsigned char *)&src); + // Write to device + // Note, we are updating inputs to all mixers here with a hard-coded 0, though the device allows + // for separate input mapping per mixer + unsigned bRequest = CUR; + unsigned cs = 0; + unsigned cn = usb_mixers->usb_mixSel[mixer].id; + unsigned wLength = 1; + usb_audio_class_set(CUR, 0, dst, usb_mixers->usb_mixSel[mixer].id, wLength, (unsigned char *)&src); - // update object state + // Update object state usb_mixers->usb_mixSel[mixer].state[dst] = src; - // update local object strings + // Update local object strings // TODO we don't really need to store strings since we can look them up...*/ strcpy(usb_mixers->usb_mixer[mixer].input_names[dst], usb_mixers->usb_mixSel[mixer].inputStrings[src]); } From 43f77c177d1836aaad8134ad38443ce1d2759809 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 11:08:23 +0000 Subject: [PATCH 15/26] Small updates to mixer control README --- host_usb_mixer_control/README | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/host_usb_mixer_control/README b/host_usb_mixer_control/README index b194224a..7b42c4b5 100644 --- a/host_usb_mixer_control/README +++ b/host_usb_mixer_control/README @@ -1,4 +1,4 @@ -The XMOS USB Audio L2 Reference Design contains an 18x8 mixer unit +The XMOS USB Audio Reference Design, by default, contains an 18x8 mixer unit (note that at sample rates above 96Khz only the first two outputs are enabled). @@ -29,7 +29,6 @@ should always be 0): --help - --display-info Show information about the device. @@ -105,11 +104,4 @@ Show the DAW output channel map sources. --vendor-audio-request-get bRequest, ControlSelector, ChannelNumber, UnitId --vendor-audio-request-set bRequest, ControlSelector, ChannelNumber, UnitId, Data[0], Data[1],... - - - - - - - From 0e07dc29bcda24f7c8fc65a2081cf145cb7d0d9d Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 3 Feb 2023 11:09:43 +0000 Subject: [PATCH 16/26] Fix issue in mixer host app when retrieving mixer input strings. Also firmed up some usage error checking. --- host_usb_mixer_control/mixer_app.cpp | 36 +++++++++++++--------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/host_usb_mixer_control/mixer_app.cpp b/host_usb_mixer_control/mixer_app.cpp index 5736ae3e..1ee2f079 100644 --- a/host_usb_mixer_control/mixer_app.cpp +++ b/host_usb_mixer_control/mixer_app.cpp @@ -175,7 +175,6 @@ void display_available_mixer_sources(int mixIndex) } } - /* Gets the current mixer inputs from the device an displays them */ void display_mixer_sources(int mixerIndex) { @@ -190,7 +189,7 @@ void display_mixer_sources(int mixerIndex) for(int i = 0; i < usb_mixsel_get_output_count(mixerIndex); i++) { int inputChan = (int)usb_mixsel_get_state(mixerIndex, i); - char *str = usb_mixer_get_input_name(mixerIndex,i); + char *str = usb_mixer_get_input_name(mixerIndex,inputChan); printf(" Mixer input %d: Source chan id: %d (%s)\n", i, inputChan, str); } } @@ -564,27 +563,26 @@ int main (int argc, char **argv) { { display_daw_channel_map_sources(); } + else if (strcmp(argv[1], "--set-aud-channel-map") == 0) + { + unsigned int dst = 0; + unsigned int src = 0; + if (argc != 4) + { + usage_error(); + return -1; + } + dst = atoi(argv[2]); + src = atoi(argv[3]); - - else if (strcmp(argv[1], "--set-aud-channel-map") == 0) - { - unsigned int dst = 0; - unsigned int src = 0; - if (argc < 4) { - usage_error(); - return -1; - } - dst = atoi(argv[2]); - src = atoi(argv[3]); - - usb_set_aud_channel_map(dst, src); - } - + usb_set_aud_channel_map(dst, src); + } else if (strcmp(argv[1], "--set-daw-channel-map") == 0) { unsigned int dst = 0; unsigned int src = 0; - if (argc < 4) { + if (argc != 4) + { usage_error(); return -1; } @@ -592,8 +590,6 @@ int main (int argc, char **argv) { src = atoi(argv[3]); usb_set_usb_channel_map(dst, src); - - } else if(strcmp(argv[1], "--get-mixer-levels-input") == 0 || strcmp(argv[1],"--get-mixer-levels-output") == 0) From ef97d667de649094531695ab02521b8ff9ce48e0 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 6 Feb 2023 18:09:33 +0000 Subject: [PATCH 17/26] Further moving of mixer from xc_ptr type to XC pointers --- lib_xua/src/core/mixer/mixer.xc | 143 +++++++++++++++----------------- 1 file changed, 67 insertions(+), 76 deletions(-) diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index ce381e30..a80d5428 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -40,18 +40,16 @@ static unsigned abs(int x) static const int SOURCE_COUNT = NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1; 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" */ +int samples_to_host_map_array[NUM_USB_CHAN_IN]; +int samples_to_device_map_array[NUM_USB_CHAN_OUT]; unsafe { - static int volatile * const unsafe ptr_samples = samples_array; + int volatile * const unsafe ptr_samples = samples_array; + int volatile * const unsafe samples_to_host_map = samples_to_host_map_array; + int volatile * const unsafe samples_to_device_map = samples_to_device_map_array; } -int samples_to_host_map_array[NUM_USB_CHAN_IN]; -xc_ptr samples_to_host_map; - -int samples_to_device_map_array[NUM_USB_CHAN_OUT]; -xc_ptr samples_to_device_map; - #if MAX_MIX_COUNT > 0 int mix_mult_array[MAX_MIX_COUNT][MIX_INPUTS]; xc_ptr mix_mult; @@ -99,20 +97,19 @@ static inline void ComputeMixerLevel(int sample, int i) #endif #ifdef FAST_MIXER void setPtr(int src, int dst, int mix); -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); +int doMix0(volatile int * const unsafe samples, xc_ptr mult); +int doMix1(volatile int * const unsafe samples, xc_ptr mult); +int doMix2(volatile int * const unsafe samples, xc_ptr mult); +int doMix3(volatile int * const unsafe samples, xc_ptr mult); +int doMix4(volatile int * const unsafe samples, xc_ptr mult); +int doMix5(volatile int * const unsafe samples, xc_ptr mult); +int doMix6(volatile int * const unsafe samples, xc_ptr mult); +int doMix7(volatile int * const 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 mixMapSlice, xc_ptr mixMultSlice) +static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) { int h=0; int l=0; @@ -121,13 +118,13 @@ static inline int doMix(xc_ptr samples, xc_ptr mixMapSlice, xc_ptr mixMultSlice) #pragma loop unroll for (int i=0; i 0 - read_via_xc_ptr_indexed(index,ptr,i); -#else - index = i + NUM_USB_CHAN_OUT; -#endif +#if (MAX_MIX_COUNT > 0) unsafe { - sample = ptr_samples[index]; + sample = ptr_samples[hostMap[i]]; } +#else + sample = ptr_sample[i + NUM_USB_CHAN_OUT]; +#endif #if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) #warning IN Vols in mixer, AFTER mix & map @@ -232,7 +227,7 @@ static inline void GetSamplesFromHost(chanend c) } #pragma unsafe arrays -static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut) +static inline void GiveSamplesToDevice(chanend c, volatile int * unsafe deviceMap, xc_ptr multOut) { #if(NUM_USB_CHAN_OUT == 0) outuint(c, 0); @@ -250,15 +245,10 @@ static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut) #if MAX_MIX_COUNT > 0 /* If mixer turned on sort out the channel mapping */ - - /* Read pointer to sample from the map */ - read_via_xc_ptr_indexed(index, ptr, i); - - /* Read the actual sample value */ unsafe { - /* Read the actual sample value */ - sample = ptr_samples[index]; + /* Read index to sample from the map then Read the actual sample value */ + sample = ptr_samples[deviceMap[i]]; } #else unsafe @@ -372,14 +362,22 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); inct(c_mix_ctl); - write_via_xc_ptr_indexed(samples_to_host_map, index, val); + unsafe + { + // TODO bounds checking + samples_to_host_map[index] = val; + } break; case SET_SAMPLES_TO_DEVICE_MAP: index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); inct(c_mix_ctl); - write_via_xc_ptr_indexed(samples_to_device_map,index,val); + unsafe + { + // TODO bounds checking + samples_to_device_map[index] = val; + } break; case SET_MIX_MULT: @@ -389,13 +387,13 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) inct(c_mix_ctl); if((index < MIX_INPUTS) && (mix < MAX_MIX_COUNT)) - { + unsafe { + //mix_mult[(mix * MIX_INPUTS) + index] = val; write_word_to_mix_mult(mix, index, val); } assert((mix < MAX_MIX_COUNT) && msg("Mix mult mix out of range")); assert((index < MIX_INPUTS) && msg("Mix mult index out of range")); - break; case SET_MIX_MAP: @@ -409,10 +407,10 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) assert((input < MIX_INPUTS) && msg("Mix map index out of range")); assert((source < SOURCE_COUNT) && msg("Mix map source out of range")); - if((input << MIX_INPUTS) && (mix < MAX_MIX_COUNT) && (source < SOURCE_COUNT)) + if((input < MIX_INPUTS) && (mix < MAX_MIX_COUNT) && (source < SOURCE_COUNT)) { #ifdef FAST_MIXER - setPtr(index, val, mix); + setPtr(input, source, mix); #else write_word_to_mix_map(mix, input, source); #endif @@ -420,7 +418,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) } break; #endif /* if MAX_MIX_COUNT > 0 */ - #ifdef IN_VOLUME_IN_MIXER case SET_MIX_IN_VOL: index = inuint(c_mix_ctl); @@ -549,15 +546,16 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) inuint(c_mixer2); /* Do the mixing */ +#ifdef FAST_MIXER + mixed = doMix0(ptr_samples, mix_mult_slice(0)); +#else + mixed = doMix(ptr_samples, mix_map_slice(0),mix_mult_slice(0)); +#endif unsafe { -#ifdef FAST_MIXER - mixed = doMix0(ptr_samples, mix_mult_slice(0)); -#else - mixed = doMix(ptr_samples, mix_map_slice(0), mix_mult_slice(0)); -#endif - ptr_samples[XUA_MIXER_OFFSET_MIX + 0] = mixed; + ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 0] = mixed; } + #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 0); #endif @@ -566,17 +564,17 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) if (!mixer1_mix2_flag) #endif { + #if MAX_MIX_COUNT > 2 unsafe { #ifdef FAST_MIXER mixed = doMix2(ptr_samples, mix_mult_slice(2)); #else - mixed = doMix(ptr_samples, mix_map_slice(2), mix_mult_slice(2)); + mixed = doMix(samples, mix_map_slice(2),mix_mult_slice(2)); #endif - ptr_samples[XUA_MIXER_OFFSET_MIX + 2] = mixed; + ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 2] = mixed; } - #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) ComputeMixerLevel(mixed, 2); #endif @@ -671,11 +669,8 @@ static void mixer2(chanend c_mixer1, chanend c_audio) } for (int i=0;i 5 - unsafe - { + unsafe + { #ifdef FAST_MIXER - mixed = doMix5(ptr_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 - ptr_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); + ComputeMixerLevel(mixed, 5); #endif #endif @@ -748,7 +744,7 @@ static void mixer2(chanend c_mixer1, chanend c_audio) #ifdef FAST_MIXER 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 ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 7] = mixed; } @@ -770,10 +766,6 @@ 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_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[])); - samples_to_host_inputs_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[])); #ifdef LEVEL_METER_LEDS samples_to_host_inputs_buff_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[])); @@ -796,8 +788,7 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) int num_mixes = DEFAULT_FREQ > 96000 ? 2 : MAX_MIX_COUNT; for (int i=0;i Date: Mon, 6 Feb 2023 18:14:48 +0000 Subject: [PATCH 18/26] Fixed build issue in mixer when FAST_MIXER not used --- lib_xua/src/core/mixer/mixer.xc | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index a80d5428..8acfd639 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -109,7 +109,7 @@ int doMix7(volatile int * const unsafe samples, xc_ptr mult); /* 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(volatile int * unsafe samples, xc_ptr ptr, xc_ptr mult) { int h=0; int l=0; @@ -117,14 +117,14 @@ static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) /* By breaking up the loop we keep things in the encoding for ldw (0-11) */ #pragma loop unroll for (int i=0; i Date: Mon, 6 Feb 2023 20:28:29 +0000 Subject: [PATCH 19/26] - Rationalised MIXER defines and usage - Further removal of xc_ptr type usage in mixer in favour of native xc pointers --- lib_xua/api/xua_conf_default.h | 51 +-- lib_xua/api/xua_mixer.h | 2 +- lib_xua/src/core/buffer/decouple/decouple.xc | 28 +- lib_xua/src/core/endpoint0/xua_endpoint0.c | 4 +- .../src/core/endpoint0/xua_ep0_descriptors.h | 50 +-- lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc | 26 +- lib_xua/src/core/main.xc | 18 +- lib_xua/src/core/mixer/fastmix.S | 2 +- lib_xua/src/core/mixer/mixer.xc | 303 ++++++++++-------- 9 files changed, 244 insertions(+), 240 deletions(-) diff --git a/lib_xua/api/xua_conf_default.h b/lib_xua/api/xua_conf_default.h index 9b89d8d3..24dd47e7 100644 --- a/lib_xua/api/xua_conf_default.h +++ b/lib_xua/api/xua_conf_default.h @@ -997,17 +997,12 @@ #define MIXER (0) #endif -/* Tidy up old ifndef usage */ -#if defined(MIXER) && (MIXER == 0) -#undef MIXER -#endif - /** * @brief Number of seperate mixes to perform * * Default: 8 if MIXER enabled, else 0 */ -#ifdef MIXER +#if (MIXER) #ifndef MAX_MIX_COUNT #define MAX_MIX_COUNT (8) #endif @@ -1087,44 +1082,24 @@ #define VOLUME_RES_MIXER (0x100) #endif -/* Handle out volume control in the mixer */ -#if defined(OUT_VOLUME_IN_MIXER) && (OUT_VOLUME_IN_MIXER==0) -#undef OUT_VOLUME_IN_MIXER -#else -#if defined(MIXER) -// Disabled by default -//#define OUT_VOLUME_IN_MIXER -#endif +/* Handle out volume control in the mixer - disabled by default */ +#ifndef OUT_VOLUME_IN_MIXER +#define OUT_VOLUME_IN_MIXER (0) #endif -/* Apply out volume controls after the mix */ -#if defined(OUT_VOLUME_AFTER_MIX) && (OUT_VOLUME_AFTER_MIX==0) -#undef OUT_VOLUME_AFTER_MIX -#else -#if defined(MIXER) && defined(OUT_VOLUME_IN_MIXER) -// Enabled by default -#define OUT_VOLUME_AFTER_MIX -#endif +/* Apply out volume controls after the mix. Only relevant when OUT_VOLUME_IN_MIXER enabled. Enabled by default */ +#ifndef OUT_VOLUME_AFTER_MIX +#define OUT_VOLUME_AFTER_MIX (1) #endif -/* Handle in volume control in the mixer */ -#if defined(IN_VOLUME_IN_MIXER) && (IN_VOLUME_IN_MIXER==0) -#undef IN_VOLUME_IN_MIXER -#else -#if defined(MIXER) -/* Disabled by default */ -//#define IN_VOLUME_IN_MIXER -#endif +/* Handle in volume control in the mixer - disabled by default */ +#ifdef IN_VOLUNE_IN_MIXER +#define IN_VOLUME_IN_MIXER (0) #endif -/* Apply in volume controls after the mix */ -#if defined(IN_VOLUME_AFTER_MIX) && (IN_VOLUME_AFTER_MIX==0) -#undef IN_VOLUME_AFTER_MIX -#else -#if defined(MIXER) && defined(IN_VOLUME_IN_MIXER) -// Enabled by default -#define IN_VOLUME_AFTER_MIX -#endif +/* Apply in volume controls after the mix. Only relebant when IN_VOLUMNE_IN MIXER enabled. Enabled by default */ +#ifndef IN_VOLUME_AFTER_MIX +#define IN_VOLUME_AFTER_MIX (1) #endif /* Always enable explicit feedback EP, even when input stream is present */ diff --git a/lib_xua/api/xua_mixer.h b/lib_xua/api/xua_mixer.h index 319c12d1..dfe561a7 100644 --- a/lib_xua/api/xua_mixer.h +++ b/lib_xua/api/xua_mixer.h @@ -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. #ifndef _XUA_MIXER_H_ #define _XUA_MIXER_H_ diff --git a/lib_xua/src/core/buffer/decouple/decouple.xc b/lib_xua/src/core/buffer/decouple/decouple.xc index ac27864a..2b2a91b9 100644 --- a/lib_xua/src/core/buffer/decouple/decouple.xc +++ b/lib_xua/src/core/buffer/decouple/decouple.xc @@ -58,11 +58,11 @@ #define IN_BUFFER_PREFILL (MAX(MAX_DEVICE_AUD_PACKET_SIZE_IN_HS, MAX_DEVICE_AUD_PACKET_SIZE_IN_FS)*2) /* Volume and mute tables */ -#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1) +#if (OUT_VOLUME_IN_MIXER == 0) && (OUTPUT_VOLUME_CONTROL == 1) unsigned int multOut[NUM_USB_CHAN_OUT + 1]; static xc_ptr p_multOut; #endif -#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1) +#if (IN_VOLUME_IN_MIXER == 0) && (INPUT_VOLUME_CONTROL == 1) unsigned int multIn[NUM_USB_CHAN_IN + 1]; static xc_ptr p_multIn; #endif @@ -206,7 +206,7 @@ __builtin_unreachable(); g_aud_from_host_rdptr+=2; sample <<= 16; -#if (OUTPUT_VOLUME_CONTROL == 1) && !defined(OUT_VOLUME_IN_MIXER) +#if (OUTPUT_VOLUME_CONTROL == 1) && (!OUT_VOLUME_IN_MIXER) asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multOut),"r"(i)); {h, l} = macs(mult, sample, 0, 0); /* Note, in 2 byte subslot mode - ignore lower result of macs */ @@ -234,7 +234,7 @@ __builtin_unreachable(); read_via_xc_ptr(sample, g_aud_from_host_rdptr); g_aud_from_host_rdptr+=4; -#if (OUTPUT_VOLUME_CONTROL == 1) && !defined(OUT_VOLUME_IN_MIXER) +#if (OUTPUT_VOLUME_CONTROL == 1) && (!OUT_VOLUME_IN_MIXER) asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multOut),"r"(i)); {h, l} = macs(mult, sample, 0, 0); h <<= 3; @@ -289,7 +289,7 @@ __builtin_unreachable(); } unpackState++; -#if (OUTPUT_VOLUME_CONTROL == 1) && !defined(OUT_VOLUME_IN_MIXER) +#if (OUTPUT_VOLUME_CONTROL == 1) && (!OUT_VOLUME_IN_MIXER) asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multOut),"r"(i)); {h, l} = macs(mult, sample, 0, 0); h <<= 3; @@ -335,7 +335,7 @@ __builtin_unreachable(); /* Receive sample */ int sample = inuint(c_mix_out); #if (INPUT_VOLUME_CONTROL == 1) -#if !defined(IN_VOLUME_IN_MIXER) +#if (!IN_VOLUME_IN_MIXER) /* Apply volume */ int mult; int h; @@ -345,7 +345,7 @@ __builtin_unreachable(); sample = h << 3; /* Note, in 2 byte sub slot - ignore lower bits of macs */ -#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) +#elif (IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) sample = sample << 3; #endif #endif @@ -365,7 +365,7 @@ __builtin_unreachable(); /* Receive sample */ int sample = inuint(c_mix_out); #if(INPUT_VOLUME_CONTROL == 1) -#if !defined(IN_VOLUME_IN_MIXER) +#if (!IN_VOLUME_IN_MIXER) /* Apply volume */ int mult; int h; @@ -376,7 +376,7 @@ __builtin_unreachable(); #if (STREAM_FORMAT_INPUT_RESOLUTION_32BIT_USED == 1) sample |= (l >> 29) & 0x7; // Note, this step is not required if we assume sample depth is 24 (rather than 32) #endif -#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) +#elif (IN_VOLUME_IN_MIXER) && (IN_VOLUME_AFTER_MIX) sample = sample << 3; #endif #endif @@ -396,7 +396,7 @@ __builtin_unreachable(); { /* Receive sample */ int sample = inuint(c_mix_out); -#if (INPUT_VOLUME_CONTROL) && !defined(IN_VOLUME_IN_MIXER) +#if (INPUT_VOLUME_CONTROL) && (!IN_VOLUME_IN_MIXER) /* Apply volume */ int mult; int h; @@ -640,10 +640,10 @@ void XUA_Buffer_Decouple(chanend c_mix_out int t = array_to_xc_ptr(outAudioBuff); -#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1) +#if (!OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1) p_multOut = array_to_xc_ptr(multOut); #endif -#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1) +#if (!IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1) p_multIn = array_to_xc_ptr(multIn); #endif @@ -670,14 +670,14 @@ void XUA_Buffer_Decouple(chanend c_mix_out xc_ptr aud_to_host_zeros = t; /* Init vol mult tables */ -#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1) +#if (OUT_VOLUME_IN_MIXER == 0) && (OUTPUT_VOLUME_CONTROL == 1) for (int i = 0; i < NUM_USB_CHAN_OUT + 1; i++) { asm volatile("stw %0, %1[%2]"::"r"(MAX_VOL),"r"(p_multOut),"r"(i)); } #endif -#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1) +#if (IN_VOLUME_IN_MIXER == 0) && (INPUT_VOLUME_CONTROL == 1) for (int i = 0; i < NUM_USB_CHAN_IN + 1; i++) { asm volatile("stw %0, %1[%2]"::"r"(MAX_VOL),"r"(p_multIn),"r"(i)); diff --git a/lib_xua/src/core/endpoint0/xua_endpoint0.c b/lib_xua/src/core/endpoint0/xua_endpoint0.c index 9a9c0c32..98d88e51 100755 --- a/lib_xua/src/core/endpoint0/xua_endpoint0.c +++ b/lib_xua/src/core/endpoint0/xua_endpoint0.c @@ -106,7 +106,7 @@ unsigned int mutesOut[NUM_USB_CHAN_OUT + 1]; int volsIn[NUM_USB_CHAN_IN + 1]; unsigned int mutesIn[NUM_USB_CHAN_IN + 1]; -#ifdef MIXER +#if (MIXER) short mixer1Weights[MIX_INPUTS * MAX_MIX_COUNT]; //unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; @@ -429,7 +429,7 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c #endif VendorRequests_Init(VENDOR_REQUESTS_PARAMS); -#ifdef MIXER +#if (MIXER) /* Set up mixer default state */ for (int i = 0; i < MIX_INPUTS * MAX_MIX_COUNT; i++) { diff --git a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h index 622ffcf2..2d5e21ea 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h +++ b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h @@ -308,28 +308,28 @@ typedef struct #error NUM_USB_CHAN > 32 #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if (MIXER) && (MAX_MIX_COUNT > 0) STR_TABLE_ENTRY(mixOutStr_1); #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 1) +#if (MIXER) && (MAX_MIX_COUNT > 1) STR_TABLE_ENTRY(mixOutStr_2); #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 2) +#if (MIXER) && (MAX_MIX_COUNT > 2) STR_TABLE_ENTRY(mixOutStr_3); #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 3) +#if (MIXER) && (MAX_MIX_COUNT > 3) STR_TABLE_ENTRY(mixOutStr_4); #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 4) +#if (MIXER) && (MAX_MIX_COUNT > 4) STR_TABLE_ENTRY(mixOutStr_5); #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 5) +#if (MIXER) && (MAX_MIX_COUNT > 5) STR_TABLE_ENTRY(mixOutStr_6); #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 6) +#if (MIXER) && (MAX_MIX_COUNT > 6) STR_TABLE_ENTRY(mixOutStr_7); #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 7) +#if (MIXER) && (MAX_MIX_COUNT > 7) STR_TABLE_ENTRY(mixOutStr_8); #endif #ifdef IAP @@ -391,31 +391,31 @@ StringDescTable_t g_strTable = #error NUM_USB_CHAN_IN > 32 #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if (MIXER) && (MAX_MIX_COUNT > 0) .mixOutStr_1 = "Mix 1", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 1) +#if (MIXER) && (MAX_MIX_COUNT > 1) .mixOutStr_2 = "Mix 2", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 2) +#if (MIXER) && (MAX_MIX_COUNT > 2) .mixOutStr_3 = "Mix 3", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 3) +#if (MIXER) && (MAX_MIX_COUNT > 3) .mixOutStr_4 = "Mix 4", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 4) +#if (MIXER) && (MAX_MIX_COUNT > 4) .mixOutStr_5 = "Mix 5", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 5) +#if (MIXER) && (MAX_MIX_COUNT > 5) .mixOutStr_6 = "Mix 6", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 6) +#if (MIXER) && (MAX_MIX_COUNT > 6) .mixOutStr_7 = "Mix 7", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 7) +#if (MIXER) && (MAX_MIX_COUNT > 7) .mixOutStr_8 = "Mix 8", #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 8) +#if (MIXER) && (MAX_MIX_COUNT > 8) #error #endif #ifdef IAP @@ -558,7 +558,7 @@ unsigned char devQualDesc_Null[] = }; -#if defined(MIXER) && !defined(AUDIO_PATH_XUS) && (MAX_MIX_COUNT > 0) +#if (MIXER) && !defined(AUDIO_PATH_XUS) && (MAX_MIX_COUNT > 0) //#warning Extension units on the audio path are required for mixer. Enabling them now. #define AUDIO_PATH_XUS #endif @@ -575,7 +575,7 @@ unsigned char devQualDesc_Null[] = #define DFU_LENGTH (0) #endif -#ifdef MIXER +#if (MIXER) #define MIX_BMCONTROLS_LEN_TMP ((MAX_MIX_COUNT * MIX_INPUTS) / 8) #if ((MAX_MIX_COUNT * MIX_INPUTS)%8)==0 @@ -666,7 +666,7 @@ typedef struct #if (NUM_USB_CHAN_OUT > 0) /* Output path */ USB_Descriptor_Audio_InputTerminal_t Audio_Out_InputTerminal; -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if (MIXER) && (MAX_MIX_COUNT > 0) USB_Descriptor_Audio_ExtensionUnit_t Audio_Out_ExtensionUnit; #endif #if(OUTPUT_VOLUME_CONTROL == 1) @@ -677,7 +677,7 @@ typedef struct #if (NUM_USB_CHAN_IN > 0) /* Input path */ USB_Descriptor_Audio_InputTerminal_t Audio_In_InputTerminal; -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if (MIXER) && (MAX_MIX_COUNT > 0) USB_Descriptor_Audio_ExtensionUnit_t Audio_In_ExtensionUnit; #endif #if(INPUT_VOLUME_CONTROL == 1) @@ -685,7 +685,7 @@ typedef struct #endif USB_Descriptor_Audio_OutputTerminal_t Audio_In_OutputTerminal; #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if (MIXER) && (MAX_MIX_COUNT > 0) USB_Descriptor_Audio_ExtensionUnit2_t Audio_Mix_ExtensionUnit; // Currently no struct for mixer unit // USB_Descriptor_Audio_MixerUnit_t Audio_MixerUnit; @@ -1168,7 +1168,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= UAC_CS_DESCTYPE_INTERFACE, /* 1 bDescriptorType: CS_INTERFACE */ UAC_CS_AC_INTERFACE_SUBTYPE_FEATURE_UNIT, /* 2 bDescriptorSubType: FEATURE_UNIT */ FU_USBIN, /* 3 bUnitID */ -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if (MIXER) && (MAX_MIX_COUNT > 0) ID_XU_IN, /* 4 bSourceID */ #else ID_IT_AUD, /* 4 bSourceID */ @@ -1300,7 +1300,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= }, #endif /* (NUM_USB_CHAN_IN > 0) */ -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if (MIXER) && (MAX_MIX_COUNT > 0) /* Extension Unit Descriptor (4.7.2.12) */ .Audio_Mix_ExtensionUnit = { @@ -1392,7 +1392,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= 0x00, /* bmControls */ 0 /* Mixer unit string descriptor index */ }, -#endif /* defined(MIXER) && (MAX_MIX_COUNT > 0) */ +#endif /* (MIXER) && (MAX_MIX_COUNT > 0) */ #if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) /* Standard AS Interrupt Endpoint Descriptor (4.8.2.1): */ diff --git a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc index 57d4aaad..e94e78fe 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc +++ b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc @@ -31,7 +31,7 @@ extern int volsIn[]; extern unsigned int mutesIn[]; /* Mixer settings */ -#ifdef MIXER +#if (MIXER) extern short mixer1Weights[]; /* Device channel mapping */ @@ -132,10 +132,10 @@ static unsigned longMul(unsigned a, unsigned b, int prec) static void updateMasterVol( int unitID, chanend ?c_mix_ctl) { int x; -#ifndef OUT_VOLUME_IN_MIXER +#if (OUT_VOLUME_IN_MIXER == 0) xc_ptr p_multOut = array_to_xc_ptr(multOut); #endif -#ifndef IN_VOLUME_IN_MIXER +#if (IN_VOLUME_IN_MIXER == 0) xc_ptr p_multIn = array_to_xc_ptr(multIn); #endif switch( unitID) @@ -152,7 +152,7 @@ static void updateMasterVol( int unitID, chanend ?c_mix_ctl) x = longMul(master_vol, vol, 29) * !mutesOut[0] * !mutesOut[i]; -#ifdef OUT_VOLUME_IN_MIXER +#if (OUT_VOLUME_IN_MIXER) if (!isnull(c_mix_ctl)) { outuint(c_mix_ctl, SET_MIX_OUT_VOL); @@ -178,7 +178,7 @@ static void updateMasterVol( int unitID, chanend ?c_mix_ctl) x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[i]; -#ifdef IN_VOLUME_IN_MIXER +#if (IN_VOLUME_IN_MIXER) if (!isnull(c_mix_ctl)) { outuint(c_mix_ctl, SET_MIX_IN_VOL); @@ -201,10 +201,10 @@ static void updateMasterVol( int unitID, chanend ?c_mix_ctl) static void updateVol(int unitID, int channel, chanend ?c_mix_ctl) { int x; -#ifndef OUT_VOLUME_IN_MIXER +#if (OUT_VOLUME_IN_MIXER == 0) xc_ptr p_multOut = array_to_xc_ptr(multOut); #endif -#ifndef IN_VOLUME_IN_MIXER +#if (IN_VOLUME_IN_MIXER == 0) xc_ptr p_multIn = array_to_xc_ptr(multIn); #endif /* Check for master volume update */ @@ -225,7 +225,7 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl) x = longMul(master_vol, vol, 29) * !mutesOut[0] * !mutesOut[channel]; -#ifdef OUT_VOLUME_IN_MIXER +#if (OUT_VOLUME_IN_MIXER) if (!isnull(c_mix_ctl)) { outuint(c_mix_ctl, SET_MIX_OUT_VOL); @@ -243,11 +243,11 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl) /* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */ /* 0x8000 is a special value representing -inf (i.e. mute) */ unsigned master_vol = volsIn[0] == 0x8000 ? 0 : db_to_mult(volsIn[0], 8, 29); - unsigned vol = volsIn[channel] == 0x8000 ? 0 : db_to_mult(volsIn[channel], 8, 29); + unsigned vol = volsIn[channel] == 0x8000 ? 0 : db_to_mult(volsIn[channel], 8, 29); x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[channel]; -#ifdef IN_VOLUME_IN_MIXER +#if (IN_VOLUME_IN_MIXER) if (!isnull(c_mix_ctl)) { outuint(c_mix_ctl, SET_MIX_IN_VOL); @@ -657,7 +657,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c break; /* FU_USBIN */ #endif -#if defined(MIXER) && (MAX_MIX_COUNT > 0) +#if ((MIXER) && (MAX_MIX_COUNT > 0)) case ID_XU_OUT: { if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */ @@ -974,7 +974,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c } break; -#ifdef MIXER +#if (MIXER) /* Mixer Unit */ case ID_MIXER_1: storeShort((buffer, unsigned char[]), 0, 1); @@ -994,7 +994,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c break; /* case: RANGE */ } -#if defined (MIXER) && (MAX_MIX_COUNT > 0) +#if ((MIXER) && (MAX_MIX_COUNT > 0)) case MEM: /* Memory Requests (5.2.7.1) */ unitID = sp.wIndex >> 8; diff --git a/lib_xua/src/core/main.xc b/lib_xua/src/core/main.xc index 86ef35d8..a79d3c26 100755 --- a/lib_xua/src/core/main.xc +++ b/lib_xua/src/core/main.xc @@ -273,7 +273,7 @@ void usb_audio_core(chanend c_mix_out #ifdef MIDI , chanend c_midi #endif - #ifdef MIXER +#if (MIXER) , chanend c_mix_ctl #endif , chanend ?c_clk_int @@ -290,7 +290,7 @@ VENDOR_REQUESTS_PARAMS_DEC_ chan c_xud_in[ENDPOINT_COUNT_IN]; chan c_aud_ctl; -#ifndef MIXER +#if (MIXER) #define c_mix_ctl null #endif @@ -401,7 +401,7 @@ void usb_audio_io(chanend ?c_aud_in, #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) chanend c_spdif_tx, #endif -#ifdef MIXER +#if (MIXER) chanend c_mix_ctl, #endif streaming chanend ?c_spdif_rx, @@ -422,7 +422,7 @@ void usb_audio_io(chanend ?c_aud_in, #endif ) { -#ifdef MIXER +#if (MIXER) chan c_mix_out; #endif @@ -446,7 +446,7 @@ void usb_audio_io(chanend ?c_aud_in, par { -#ifdef MIXER +#if (MIXER) /* Mixer cores(s) */ { thread_speed(); @@ -464,7 +464,7 @@ void usb_audio_io(chanend ?c_aud_in, /* Audio I/O core (pars additional S/PDIF TX Core) */ { thread_speed(); -#ifdef MIXER +#if (MIXER) #define AUDIO_CHANNEL c_mix_out #else #define AUDIO_CHANNEL c_aud_in @@ -531,7 +531,7 @@ int main() #endif #endif -#ifdef MIXER +#if (MIXER) chan c_mix_ctl; #endif @@ -608,7 +608,7 @@ int main() , c_ea_data #endif #endif -#ifdef MIXER +#if (MIXER) , c_mix_ctl #endif , c_clk_int, c_clk_ctl, dfuInterface @@ -628,7 +628,7 @@ int main() #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) , c_spdif_tx #endif -#ifdef MIXER +#if (MIXER) , c_mix_ctl #endif , c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int diff --git a/lib_xua/src/core/mixer/fastmix.S b/lib_xua/src/core/mixer/fastmix.S index a2374a5e..8a8e008f 100644 --- a/lib_xua/src/core/mixer/fastmix.S +++ b/lib_xua/src/core/mixer/fastmix.S @@ -1,4 +1,4 @@ -// Copyright 2018-2021 XMOS LIMITED. +// Copyright 2018-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #define MAX_MIX_COUNT 8 diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index 8acfd639..32f8ccca 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -5,23 +5,36 @@ #include #include "xua.h" -#include "xc_ptr.h" #include "xua_commands.h" #include "dbcalc.h" +#include "print.h" -#ifdef MIXER +#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) +#include "xc_ptr.h" +#endif + +#if (MIXER) /* FAST_MIXER has a bit of a nasty implentation but is more effcient */ -#define FAST_MIXER 1 +#ifndef FAST_MIXER +#define FAST_MIXER (1) +#endif -//#ifdef OUT_VOLUME_IN_MIXER +#if (OUT_VOLUME_IN_MIXER) static unsigned int multOut_array[NUM_USB_CHAN_OUT + 1]; -static xc_ptr multOut; -//#endif -//#ifdef IN_VOLUME_IN_MIXER +unsafe +{ + int volatile * unsafe multOut = multOut_array; +} +#endif + +#if (IN_VOLUME_IN_MIXER) static unsigned int multIn_array[NUM_USB_CHAN_IN + 1]; -static xc_ptr multIn; -//#endif +unsafe +{ + int volatile * unsafe multIn = multIn_array; +} +#endif #if defined (LEVEL_METER_LEDS) || defined (LEVEL_METER_HOST) static unsigned abs(int x) @@ -40,8 +53,8 @@ static unsigned abs(int x) static const int SOURCE_COUNT = NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1; 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" */ -int samples_to_host_map_array[NUM_USB_CHAN_IN]; -int samples_to_device_map_array[NUM_USB_CHAN_OUT]; +static int samples_to_host_map_array[NUM_USB_CHAN_IN]; +static int samples_to_device_map_array[NUM_USB_CHAN_OUT]; unsafe { @@ -50,19 +63,25 @@ unsafe int volatile * const unsafe samples_to_device_map = samples_to_device_map_array; } -#if MAX_MIX_COUNT > 0 -int mix_mult_array[MAX_MIX_COUNT][MIX_INPUTS]; -xc_ptr mix_mult; -#define write_word_to_mix_mult(x,y,val) write_via_xc_ptr_indexed(mix_mult,((x)*MIX_INPUTS)+(y), val) -#define mix_mult_slice(x) (mix_mult + x * MIX_INPUTS * sizeof(int)) -#ifndef FAST_MIXER -int mix_map_array[MAX_MIX_COUNT][MIX_INPUTS]; -xc_ptr mix_map; -#define write_word_to_mix_map(x,y,val) write_via_xc_ptr_indexed(mix_map,((x)*MIX_INPUTS)+(y), val) -#define mix_map_slice(x) (mix_map + x * MIX_INPUTS * sizeof(int)) -#endif +#if (MAX_MIX_COUNT > 0) +int mix_mult_array[MAX_MIX_COUNT * MIX_INPUTS]; +#if (FAST_MIXER == 0) +int mix_map_array[MAX_MIX_COUNT * MIX_INPUTS]; #endif +unsafe +{ + int volatile * const unsafe mix_mult = mix_mult_array; +#if (FAST_MIXER == 0) + int volatile * const unsafe mix_map = mix_map_array; +#endif +} + +#define slice(a, i) (a + i * MIX_INPUTS) + +#endif + +#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) /* Arrays for level data */ int samples_to_host_inputs[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. device inputs */ xc_ptr samples_to_host_inputs_ptr; @@ -76,7 +95,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 defined (LEVEL_METER_LEDS) || defined (LEVEL_METER_HOST) static inline void ComputeMixerLevel(int sample, int i) { int x; @@ -95,21 +113,22 @@ static inline void ComputeMixerLevel(int sample, int i) } } #endif -#ifdef FAST_MIXER + +#if (FAST_MIXER) void setPtr(int src, int dst, int mix); -int doMix0(volatile int * const unsafe samples, xc_ptr mult); -int doMix1(volatile int * const unsafe samples, xc_ptr mult); -int doMix2(volatile int * const unsafe samples, xc_ptr mult); -int doMix3(volatile int * const unsafe samples, xc_ptr mult); -int doMix4(volatile int * const unsafe samples, xc_ptr mult); -int doMix5(volatile int * const unsafe samples, xc_ptr mult); -int doMix6(volatile int * const unsafe samples, xc_ptr mult); -int doMix7(volatile int * const unsafe samples, xc_ptr mult); +int doMix0(volatile int * const unsafe samples, volatile int * const unsafe mult); +int doMix1(volatile int * const unsafe samples, volatile int * const unsafe mult); +int doMix2(volatile int * const unsafe samples, volatile int * const unsafe mult); +int doMix3(volatile int * const unsafe samples, volatile int * const unsafe mult); +int doMix4(volatile int * const unsafe samples, volatile int * const unsafe mult); +int doMix5(volatile int * const unsafe samples, volatile int * const unsafe mult); +int doMix6(volatile int * const unsafe samples, volatile int * const unsafe mult); +int doMix7(volatile int * const unsafe samples, volatile int * const unsafe 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(volatile int * unsafe samples, xc_ptr ptr, xc_ptr mult) +static inline int doMix(volatile int * unsafe samples, volatile int * unsafe const mixMap, volatile int * const unsafe mult) { int h=0; int l=0; @@ -121,7 +140,7 @@ static inline int doMix(volatile int * unsafe samples, xc_ptr ptr, xc_ptr mult) int sample; int source; int weight; - read_via_xc_ptr_indexed(source, ptr, i); + read_via_xc_ptr_indexed(source, mixMap, i); sample = samples[source]; read_via_xc_ptr_indexed(weight, mult, i); {h,l} = macs(sample, weight, h, l); @@ -142,9 +161,9 @@ static inline int doMix(volatile int * unsafe samples, xc_ptr ptr, xc_ptr mult) #endif #pragma unsafe arrays -static inline void GiveSamplesToHost(chanend c, volatile int * unsafe hostMap, xc_ptr multIn) +static inline void GiveSamplesToHost(chanend c, volatile int * unsafe hostMap) { -#if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) +#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX) int mult; int h; unsigned l; @@ -164,12 +183,15 @@ static inline void GiveSamplesToHost(chanend c, volatile int * unsafe hostMap, x sample = ptr_sample[i + NUM_USB_CHAN_OUT]; #endif -#if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) +#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX) #warning IN Vols in mixer, AFTER mix & map - //asm("ldw %0, %1[%2]":"=r"(mult):"r"(multIn),"r"(i)); - read_via_xc_ptr_indexed(mult, multIn, i); + + unsafe + { + mult = multIn[i]; + } {h, l} = macs(mult, sample, 0, 0); - + //h <<= 3 done on other side */ outuint(c, h); @@ -190,7 +212,7 @@ static inline void GetSamplesFromHost(chanend c) for (int i=0; i>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 + // Note: We need all 32bits for Native DSD #endif - write_via_xc_ptr_indexed(multOut, index, val); write_via_xc_ptr_indexed(samples_array, i, h); #else ptr_samples[i] = sample; @@ -227,23 +248,23 @@ static inline void GetSamplesFromHost(chanend c) } #pragma unsafe arrays -static inline void GiveSamplesToDevice(chanend c, volatile int * unsafe deviceMap, xc_ptr multOut) +static inline void GiveSamplesToDevice(chanend c, volatile int * unsafe deviceMap) { -#if(NUM_USB_CHAN_OUT == 0) +#if (NUM_USB_CHAN_OUT == 0) outuint(c, 0); #else #pragma loop unroll for (int i=0; i 0 +#if (MAX_MIX_COUNT > 0) /* If mixer turned on sort out the channel mapping */ unsafe { @@ -258,15 +279,19 @@ static inline void GiveSamplesToDevice(chanend c, volatile int * unsafe deviceMa } #endif -#if defined(OUT_VOLUME_IN_MIXER) && defined(OUT_VOLUME_AFTER_MIX) +#if (OUT_VOLUME_IN_MIXER && OUT_VOLUME_AFTER_MIX) /* Do volume control processing */ #warning OUT Vols in mixer, AFTER mix & map - read_via_xc_ptr_indexed(mult, multOut, i); + unsafe + { + 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 #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 + // Note: We need all 32bits for Native DSD #endif outuint(c, h); #else @@ -279,7 +304,7 @@ static inline void GiveSamplesToDevice(chanend c, volatile int * unsafe deviceMa #pragma unsafe arrays static inline void GetSamplesFromDevice(chanend c) { -#if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX) +#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX) int mult; int h; unsigned l; @@ -306,9 +331,12 @@ static inline void GetSamplesFromDevice(chanend c) } #endif -#if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX) +#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX) /* Read relevant multiplier */ - read_via_xc_ptr_indexed(mult, multIn, i); + unsafe + { + mult = multIn[i]; + } /* Do the multiply */ {h, l} = macs(mult, sample, 0, 0); @@ -357,7 +385,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) int mix, index, val; switch (cmd) { -#if MAX_MIX_COUNT > 0 +#if (MAX_MIX_COUNT > 0) case SET_SAMPLES_TO_HOST_MAP: index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); @@ -388,8 +416,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) if((index < MIX_INPUTS) && (mix < MAX_MIX_COUNT)) unsafe { - //mix_mult[(mix * MIX_INPUTS) + index] = val; - write_word_to_mix_mult(mix, index, val); + mix_mult[(mix * MIX_INPUTS) + index] = val; } assert((mix < MAX_MIX_COUNT) && msg("Mix mult mix out of range")); @@ -409,34 +436,46 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) if((input < MIX_INPUTS) && (mix < MAX_MIX_COUNT) && (source < SOURCE_COUNT)) { -#ifdef FAST_MIXER +#if (FAST_MIXER) setPtr(input, source, mix); #else - write_word_to_mix_map(mix, input, source); -#endif + unsafe + { + mix_map[(mix * MIX_INPUTS) + input] = source; + } +#endif } } break; #endif /* if MAX_MIX_COUNT > 0 */ -#ifdef IN_VOLUME_IN_MIXER +#if (IN_VOLUME_IN_MIXER) case SET_MIX_IN_VOL: index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); inct(c_mix_ctl); - write_via_xc_ptr_indexed(multIn, index, val); + if(index < NUM_USB_CHAN_IN+1) + unsafe{ + multIn[index] = val; + } + assert((index < (NUM_USB_CHAN_IN + 1)) && msg("In volume index out of range")); break; #endif -#ifdef OUT_VOLUME_IN_MIXER +#if (OUT_VOLUME_IN_MIXER) case SET_MIX_OUT_VOL: index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); inct(c_mix_ctl); - write_via_xc_ptr_indexed(multOut, index, val); + if(index < NUM_USB_CHAN_OUT+1) + unsafe{ + multOut[index] = val; + } + assert((index < (NUM_USB_CHAN_OUT + 1)) && msg("Out volume index out of range")); break; #endif +#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) /* Peak samples of stream from host to device (via USB) */ case GET_STREAM_LEVELS: index = inuint(c_mix_ctl); @@ -445,7 +484,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) outct(c_mix_ctl, XS1_CT_END); samples_from_host_streams[index] = 0; break; - case GET_INPUT_LEVELS: index = inuint(c_mix_ctl); chkct(c_mix_ctl, XS1_CT_END); @@ -481,6 +519,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) outuint(c_mix_ctl, val); outct(c_mix_ctl, XS1_CT_END); break; +#endif #endif } break; @@ -537,22 +576,22 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) } else { -#if MAX_MIX_COUNT > 0 +#if (MAX_MIX_COUNT > 0) GetSamplesFromHost(c_host); - GiveSamplesToHost(c_host, samples_to_host_map, multIn); + GiveSamplesToHost(c_host, samples_to_host_map); /* Sync with mixer 2 (once it has swapped samples with audiohub) */ outuint(c_mixer2, 0); inuint(c_mixer2); /* Do the mixing */ -#ifdef FAST_MIXER - mixed = doMix0(ptr_samples, mix_mult_slice(0)); -#else - mixed = doMix(ptr_samples, mix_map_slice(0), mix_mult_slice(0)); -#endif unsafe { +#if (FAST_MIXER) + mixed = doMix0(ptr_samples, slice(mix_mult, 0)); +#else + mixed = doMix(ptr_samples, slice(mix_map, 0), slice(mix_mult, 0)); +#endif ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 0] = mixed; } @@ -565,13 +604,13 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #endif { -#if MAX_MIX_COUNT > 2 +#if (MAX_MIX_COUNT > 2) unsafe { -#ifdef FAST_MIXER - mixed = doMix2(ptr_samples, mix_mult_slice(2)); +#if (FAST_MIXER) + mixed = doMix2(ptr_samples, slice(mix_mult, 2)); #else - mixed = doMix(ptr_samples, mix_map_slice(2), mix_mult_slice(2)); + mixed = doMix(ptr_samples, slice(mix_map, 2), slice(mix_mult, 2)); #endif ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 2] = mixed; } @@ -580,13 +619,13 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #endif #endif -#if MAX_MIX_COUNT > 4 +#if (MAX_MIX_COUNT > 4) unsafe { -#ifdef FAST_MIXER - mixed = doMix4(ptr_samples, mix_mult_slice(4)); +#if (FAST_MIXER) + mixed = doMix4(ptr_samples, slice(mix_mult, 4)); #else - mixed = doMix(ptr_samples, mix_map_slice(4), mix_mult_slice(4)); + mixed = doMix(ptr_samples, slice(mix_map, 4), slice(mix_mult, 4)); #endif ptr_samples[XUA_MIXER_OFFSET_MIX + 4] = mixed; } @@ -595,13 +634,13 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #endif #endif -#if MAX_MIX_COUNT > 6 +#if (MAX_MIX_COUNT > 6) unsafe { -#ifdef FAST_MIXER - mixed = doMix6(ptr_samples, mix_mult_slice(6)); +#if (FAST_MIXER) + mixed = doMix6(ptr_samples, slice(mix_mult, 6)); #else - mixed = doMix(ptr_samples, mix_map_slice(6), mix_mult_slice(6)); + mixed = doMix(ptr_samples, slice(mix_map, 6), slice(mix_mult, 6)); #endif ptr_samples[XUA_MIXER_OFFSET_MIX + 6] = mixed; } @@ -612,7 +651,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) } #else /* IF MAX_MIX_COUNT > 0 */ /* No mixes, this thread runs on its own doing just volume */ - GiveSamplesToDevice(c_mixer2, samples_to_device_map, multOut); + GiveSamplesToDevice(c_mixer2, samples_to_device_map); GetSamplesFromDevice(c_mixer2); GetSamplesFromHost(c_host); GiveSamplesToHost(c_host, samples_to_host_map, multIn); @@ -679,7 +718,7 @@ static void mixer2(chanend c_mixer1, chanend c_audio) } else { - GiveSamplesToDevice(c_audio, samples_to_device_map, multOut); + GiveSamplesToDevice(c_audio, samples_to_device_map); GetSamplesFromDevice(c_audio); /* Sync with mixer 1 (once it has swapped samples with the buffering sub-system) */ @@ -687,13 +726,13 @@ static void mixer2(chanend c_mixer1, chanend c_audio) outuint(c_mixer1, 0); /* Do the mixing */ -#if MAX_MIX_COUNT > 1 +#if (MAX_MIX_COUNT > 1) unsafe { -#ifdef FAST_MIXER - mixed = doMix1(ptr_samples, mix_mult_slice(1)); +#if (FAST_MIXER) + mixed = doMix1(ptr_samples, slice(mix_mult, 1)); #else - mixed = doMix(ptr_samples, mix_map_slice(1), mix_mult_slice(1)); + mixed = doMix(ptr_samples, slice(mix_map, 1), slice(mix_mult, 1)); #endif ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 1] = mixed; } @@ -707,13 +746,13 @@ static void mixer2(chanend c_mixer1, chanend c_audio) if (!mixer2_mix2_flag) #endif { -#if MAX_MIX_COUNT > 3 +#if (MAX_MIX_COUNT > 3) unsafe { -#ifdef FAST_MIXER - mixed = doMix3(ptr_samples, mix_mult_slice(3)); +#if (FAST_MIXER) + mixed = doMix3(ptr_samples, slice(mix_mult, 3)); #else - mixed = doMix(ptr_samples, mix_map_slice(3), mix_mult_slice(3)); + mixed = doMix(ptr_samples, slice(mix_map, 3), slice(mix_mult, 3)); #endif ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 3] = mixed; } @@ -722,29 +761,29 @@ static void mixer2(chanend c_mixer1, chanend c_audio) #endif #endif -#if MAX_MIX_COUNT > 5 - unsafe - { -#ifdef FAST_MIXER - mixed = doMix5(ptr_samples, mix_mult_slice(5)); +#if (MAX_MIX_COUNT > 5) + unsafe + { +#if (FAST_MIXER) + mixed = doMix5(ptr_samples, slice(mix_mult, 5)); #else - mixed = doMix(ptr_samples, mix_map_slice(5), mix_mult_slice(5)); + mixed = doMix(ptr_samples, slice(mix_map, 5), slice(mix_mult, 5)); #endif - ptr_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); + ComputeMixerLevel(mixed, 5); #endif #endif -#if MAX_MIX_COUNT > 7 +#if (MAX_MIX_COUNT > 7) unsafe { -#ifdef FAST_MIXER - mixed = doMix7(ptr_samples, mix_mult_slice(7)); +#if (FAST_MIXER) + mixed = doMix7(ptr_samples, slice(mix_mult, 7)); #else - mixed = doMix(ptr_samples, mix_map_slice(7), mix_mult_slice(7)); + mixed = doMix(ptr_samples, slice(mix_map, 7), slice(mix_mult, 7)); #endif ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 7] = mixed; } @@ -763,20 +802,13 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) #if (MAX_MIX_COUNT > 0) chan c; #endif - multOut = array_to_xc_ptr((multOut_array,unsigned[])); - multIn = array_to_xc_ptr((multIn_array,unsigned[])); +#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) samples_to_host_inputs_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[])); #ifdef LEVEL_METER_LEDS samples_to_host_inputs_buff_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[])); #endif samples_mixer_outputs_ptr = array_to_xc_ptr((samples_mixer_outputs, unsigned[])); - -#if MAX_MIX_COUNT >0 - mix_mult = array_to_xc_ptr((mix_mult_array,unsigned[])); -#ifndef FAST_MIXER - mix_map = array_to_xc_ptr((mix_map_array,unsigned[])); -#endif #endif for (int i=0;i 96000 ? 2 : MAX_MIX_COUNT; - for (int i=0;i 0 +#if (MAX_MIX_COUNT> 0) for (int i=0;i Date: Mon, 6 Feb 2023 21:05:48 +0000 Subject: [PATCH 20/26] - Fixed MIXER define usage in main - Fixed unsafe pointer usage when MAX_MIX_COUNT=0 - Fixed syntax error building mixer when no features enabled relating to empty switch statement --- lib_xua/src/core/main.xc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/main.xc b/lib_xua/src/core/main.xc index a79d3c26..046059eb 100755 --- a/lib_xua/src/core/main.xc +++ b/lib_xua/src/core/main.xc @@ -290,7 +290,7 @@ VENDOR_REQUESTS_PARAMS_DEC_ chan c_xud_in[ENDPOINT_COUNT_IN]; chan c_aud_ctl; -#if (MIXER) +#if (!MIXER) #define c_mix_ctl null #endif From 60040de58f95db24cbeab862857755c02056eeed Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 6 Feb 2023 21:08:47 +0000 Subject: [PATCH 21/26] Further build issue fixes and copyright comments --- lib_xua/api/xua_conf_default.h | 2 +- lib_xua/src/core/buffer/decouple/decouple.xc | 2 +- .../src/core/endpoint0/xua_ep0_descriptors.h | 2 +- lib_xua/src/core/main.xc | 2 +- lib_xua/src/core/mixer/mixer.xc | 51 ++++--------------- 5 files changed, 14 insertions(+), 45 deletions(-) diff --git a/lib_xua/api/xua_conf_default.h b/lib_xua/api/xua_conf_default.h index 24dd47e7..cd0dc98f 100644 --- a/lib_xua/api/xua_conf_default.h +++ b/lib_xua/api/xua_conf_default.h @@ -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. /* * @brief Defines relating to device configuration and customisation of lib_xua diff --git a/lib_xua/src/core/buffer/decouple/decouple.xc b/lib_xua/src/core/buffer/decouple/decouple.xc index 2b2a91b9..a387cddb 100644 --- a/lib_xua/src/core/buffer/decouple/decouple.xc +++ b/lib_xua/src/core/buffer/decouple/decouple.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" diff --git a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h index 2d5e21ea..91fd3b94 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h +++ b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h @@ -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. /** * @file xua_ep0_descriptors.h diff --git a/lib_xua/src/core/main.xc b/lib_xua/src/core/main.xc index 046059eb..d7a27d10 100755 --- a/lib_xua/src/core/main.xc +++ b/lib_xua/src/core/main.xc @@ -1,4 +1,4 @@ -// Copyright 2012-2022 XMOS LIMITED. +// Copyright 2012-2023 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include "xua.h" /* Device specific defines */ diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index 32f8ccca..178af474 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -180,7 +180,10 @@ static inline void GiveSamplesToHost(chanend c, volatile int * unsafe hostMap) sample = ptr_samples[hostMap[i]]; } #else - sample = ptr_sample[i + NUM_USB_CHAN_OUT]; + unsafe + { + sample = ptr_samples[i + NUM_USB_CHAN_OUT]; + } #endif #if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX) @@ -376,8 +379,9 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) /* Sync */ outuint(c_mixer2, 0); #endif - /* Between request to decouple and response ~ 400nS latency for interrupt to fire */ + +#if (MIX_MIX_COUNT > 0) || (IN_VOLUME_IN_MIXER) || (OUT_VOLUME_IN_MIXER) || defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) select { case inuint_byref(c_mix_ctl, cmd): @@ -448,6 +452,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) } break; #endif /* if MAX_MIX_COUNT > 0 */ + #if (IN_VOLUME_IN_MIXER) case SET_MIX_IN_VOL: index = inuint(c_mix_ctl); @@ -484,42 +489,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) outct(c_mix_ctl, XS1_CT_END); samples_from_host_streams[index] = 0; break; - case GET_INPUT_LEVELS: - index = inuint(c_mix_ctl); - chkct(c_mix_ctl, XS1_CT_END); -#ifdef LEVEL_METER_LEDS - /* Level LEDS process reseting samples_to_host_inputs - * Other side makes sure we don't miss a peak */ - //val = samples_to_host_inputs_buff[index]; - //samples_to_host_inputs_buff[index] = 0; - /* Access funcs used to avoid disjointness check */ - read_via_xc_ptr_indexed(val, samples_to_host_inputs_buff_ptr, index); - write_via_xc_ptr_indexed(samples_to_host_inputs_buff_ptr, index, 0); -#else - /* We dont have a level LEDs process, so reset ourselves */ - //val = samples_to_host_inputs[index]; - //samples_to_host_inputs[index] = 0; - /* Access funcs used to avoid disjointness check */ - read_via_xc_ptr_indexed(val, samples_to_host_inputs_ptr, index); - write_via_xc_ptr_indexed(samples_to_host_inputs_ptr, index, 0); -#endif - outuint(c_mix_ctl, val); - outct(c_mix_ctl, XS1_CT_END); - break; - -#if (MAX_MIX_COUNT > 0) - /* Peak samples of the mixer outputs */ - case GET_OUTPUT_LEVELS: - index = inuint(c_mix_ctl); - chkct(c_mix_ctl, XS1_CT_END); - read_via_xc_ptr_indexed(val, samples_mixer_outputs, index); - write_via_xc_ptr_indexed(samples_mixer_outputs, index, 0); - //val = samples_mixer_outputs[index]; - //samples_mixer_outputs[index] = 0; - outuint(c_mix_ctl, val); - outct(c_mix_ctl, XS1_CT_END); - break; -#endif #endif } break; @@ -527,8 +496,8 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) default: /* Select default */ break; - } - + } // select +#endif /* Get response from decouple */ if(testct(c_host)) @@ -654,7 +623,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) GiveSamplesToDevice(c_mixer2, samples_to_device_map); GetSamplesFromDevice(c_mixer2); GetSamplesFromHost(c_host); - GiveSamplesToHost(c_host, samples_to_host_map, multIn); + GiveSamplesToHost(c_host, samples_to_host_map); #endif } } From 6d8cf9913f0666c837475c7710613cf25e6c05ff Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 6 Feb 2023 23:42:33 +0000 Subject: [PATCH 22/26] Increase timeout cycles for test_mixer_routing_output --- tests/test_mixer_routing_output.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_mixer_routing_output.py b/tests/test_mixer_routing_output.py index a01e9c7a..d867c42e 100644 --- a/tests/test_mixer_routing_output.py +++ b/tests/test_mixer_routing_output.py @@ -15,7 +15,7 @@ def do_test(options, capfd, test_file, test_seed): tester = testers.ComparisonTester(open("pass.expect")) - max_cycles = 1500000 + max_cycles = 15000000 simargs = [ "--max-cycles", From 908099023453c373c9a3e560f1cbf4c6fffb84fe Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 6 Feb 2023 23:44:20 +0000 Subject: [PATCH 23/26] Fixed typo in define check --- lib_xua/src/core/mixer/mixer.xc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index 178af474..52a56921 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -381,7 +381,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #endif /* Between request to decouple and response ~ 400nS latency for interrupt to fire */ -#if (MIX_MIX_COUNT > 0) || (IN_VOLUME_IN_MIXER) || (OUT_VOLUME_IN_MIXER) || defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) +#if (MAX_MIX_COUNT > 0) || (IN_VOLUME_IN_MIXER) || (OUT_VOLUME_IN_MIXER) || defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) select { case inuint_byref(c_mix_ctl, cmd): From 71aa64425df0485feab89a1c1cdf9766f2346588 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 7 Feb 2023 12:14:19 +0000 Subject: [PATCH 24/26] Added missing bounds checking when setting host and device maps in the mixer --- lib_xua/src/core/mixer/mixer.xc | 81 ++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index 52a56921..f505bddb 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -391,24 +391,40 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) { #if (MAX_MIX_COUNT > 0) case SET_SAMPLES_TO_HOST_MAP: - index = inuint(c_mix_ctl); - val = inuint(c_mix_ctl); - inct(c_mix_ctl); - unsafe { - // TODO bounds checking - samples_to_host_map[index] = val; + int dst = inuint(c_mix_ctl); + int src = inuint(c_mix_ctl); + inct(c_mix_ctl); + + assert((dst < NUM_USB_CHAN_IN) && msg("Host map destination out of range")); + assert((src < SOURCE_COUNT) && msg("Host map source out of range")); + + if((dst < NUM_USB_CHAN_IN) && (src < SOURCE_COUNT)) + { + unsafe + { + samples_to_host_map[dst] = src; + } + } } break; case SET_SAMPLES_TO_DEVICE_MAP: - index = inuint(c_mix_ctl); - val = inuint(c_mix_ctl); - inct(c_mix_ctl); - unsafe { - // TODO bounds checking - samples_to_device_map[index] = val; + int dst = inuint(c_mix_ctl); + int src = inuint(c_mix_ctl); + inct(c_mix_ctl); + + assert((dst < NUM_USB_CHAN_OUT) && msg("Device map destination out of range")); + assert((src < SOURCE_COUNT) && msg("Device map source out of range")); + + if((dst < NUM_USB_CHAN_OUT) && (src < SOURCE_COUNT)) + { + unsafe + { + samples_to_device_map[dst] = src; + } + } } break; @@ -418,13 +434,16 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) val = inuint(c_mix_ctl); inct(c_mix_ctl); - if((index < MIX_INPUTS) && (mix < MAX_MIX_COUNT)) - unsafe { - mix_mult[(mix * MIX_INPUTS) + index] = val; - } - assert((mix < MAX_MIX_COUNT) && msg("Mix mult mix out of range")); assert((index < MIX_INPUTS) && msg("Mix mult index out of range")); + + if((index < MIX_INPUTS) && (mix < MAX_MIX_COUNT)) + { + unsafe + { + mix_mult[(mix * MIX_INPUTS) + index] = val; + } + } break; case SET_MIX_MAP: @@ -458,12 +477,16 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); inct(c_mix_ctl); - - if(index < NUM_USB_CHAN_IN+1) - unsafe{ - multIn[index] = val; - } + assert((index < (NUM_USB_CHAN_IN + 1)) && msg("In volume index out of range")); + + if(index < NUM_USB_CHAN_IN + 1) + { + unsafe + { + multIn[index] = val; + } + } break; #endif #if (OUT_VOLUME_IN_MIXER) @@ -471,12 +494,16 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) index = inuint(c_mix_ctl); val = inuint(c_mix_ctl); inct(c_mix_ctl); - - if(index < NUM_USB_CHAN_OUT+1) - unsafe{ - multOut[index] = val; - } + assert((index < (NUM_USB_CHAN_OUT + 1)) && msg("Out volume index out of range")); + + if(index < NUM_USB_CHAN_OUT + 1) + { + unsafe + { + multOut[index] = val; + } + } break; #endif From 15ca5ec28103615b28e710635c69188ca98fb843 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 7 Feb 2023 16:35:38 +0000 Subject: [PATCH 25/26] Fixed unused var warning --- lib_xua/src/core/mixer/mixer.xc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib_xua/src/core/mixer/mixer.xc b/lib_xua/src/core/mixer/mixer.xc index f505bddb..5a4176eb 100644 --- a/lib_xua/src/core/mixer/mixer.xc +++ b/lib_xua/src/core/mixer/mixer.xc @@ -364,7 +364,9 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #if (MAX_MIX_COUNT > 0) int mixed; #endif +#if (MAX_MIX_COUNT > 0) || (IN_VOLUME_IN_MIXER) || (OUT_VOLUME_IN_MIXER) || defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) unsigned cmd; +#endif unsigned request = 0; while (1) From 6c2e7e3042481430c156cd9619a6085e2837c40f Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Wed, 8 Feb 2023 10:02:32 +0000 Subject: [PATCH 26/26] Fixed issue setting mix maps (#308) --- lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc | 116 +++++++++--------- 1 file changed, 55 insertions(+), 61 deletions(-) diff --git a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc index e94e78fe..f0e440ec 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc +++ b/lib_xua/src/core/endpoint0/xua_ep0_uacreqs.xc @@ -659,72 +659,67 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c #if ((MIXER) && (MAX_MIX_COUNT > 0)) case ID_XU_OUT: - { - if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */ { - unsigned volume = 0; - int c = sp.wValue & 0xff; - - - if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY) + int dst = sp.wValue & 0xff; + + if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */ { - return result; - } - - channelMapAud[c] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8; - - if (!isnull(c_mix_ctl)) - { - if (c < NUM_USB_CHAN_OUT) + if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY) { - UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP, c, channelMapAud[c]); - - /* Send 0 Length as status stage */ - return XUD_DoSetRequestStatus(ep0_in); + return result; } + + if (dst < NUM_USB_CHAN_OUT) + { + channelMapAud[dst] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8; + + if (!isnull(c_mix_ctl)) + { + UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP, dst, channelMapAud[dst]); + } + } + + /* Send 0 Length as status stage */ + return XUD_DoSetRequestStatus(ep0_in); + } + else + { + (buffer, unsigned char[])[0] = channelMapAud[dst]; + (buffer, unsigned char[])[1] = 0; + return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength); } - } - else - { - (buffer, unsigned char[])[0] = channelMapAud[sp.wValue & 0xff]; - (buffer, unsigned char[])[1] = 0; - - return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength); - } - - } break; case ID_XU_IN: - if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */ { - unsigned volume = 0; - int c = sp.wValue & 0xff; - - if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY) + int dst = sp.wValue & 0xff; + + if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */ { - return result; - } - - channelMapUsb[c] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8; - - if (c < NUM_USB_CHAN_IN) - { - if (!isnull(c_mix_ctl)) + if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY) { - UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP, c, channelMapUsb[c]); - - return XUD_DoSetRequestStatus(ep0_in); + return result; } + + if (dst < NUM_USB_CHAN_IN) + { + channelMapUsb[dst] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8; + + if (!isnull(c_mix_ctl)) + { + UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP, dst, channelMapUsb[dst]); + } + } + return XUD_DoSetRequestStatus(ep0_in); + } + else + { + /* Direction: Device-to-host */ + (buffer, unsigned char[])[0] = channelMapUsb[dst]; + (buffer, unsigned char[])[1] = 0; + return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength); } - } - else - { - /* Direction: Device-to-host */ - (buffer, unsigned char[])[0] = channelMapUsb[sp.wValue & 0xff]; - (buffer, unsigned char[])[1] = 0; - return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength); } break; @@ -751,14 +746,12 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c /* cs now contains mix number */ if(cs < (MAX_MIX_COUNT + 1)) { + int source = (buffer, unsigned char[])[0]; + /* Check for "off" - update local state */ - if((buffer, unsigned char[])[0] == 0xFF) + if(source == 0xFF) { - mixSel[cs][cn] = (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT); - } - else - { - mixSel[cs][cn] = (buffer, unsigned char[])[0]; + source = (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT); } if(cs == 0) @@ -768,14 +761,15 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c { /* i : Mix bus */ /* cn: Mixer input */ - /* mixSel[i][cn]): Source */ - UpdateMixMap(c_mix_ctl, i, cn, (int) mixSel[cn]); + mixSel[i][cn] = source; + UpdateMixMap(c_mix_ctl, i, cn, mixSel[i][cn]); } } else { /* Update relevant mix map */ - UpdateMixMap(c_mix_ctl, cs-1, cn, (int) mixSel[cs][cn]); + mixSel[cn-1][cn] = source; + UpdateMixMap(c_mix_ctl, cs-1, cn, mixSel[cs-1][cn]); } return XUD_DoSetRequestStatus(ep0_in);