Added mixer control unit tests (#316)

* Added test_mixer_routing_output_ctrl
* Added test_mixer_routing_input_ctrl 
* Some minor mixer test and code improvements
* Update lib_xud dep version requirement
This commit is contained in:
Ross Owen
2023-03-08 10:53:33 +00:00
committed by GitHub
parent 3fe4593b52
commit 208491fe51
19 changed files with 754 additions and 80 deletions

View File

@@ -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) -DXUD_WEAK_API=1
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

View File

@@ -0,0 +1,221 @@
// Copyright 2022-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/* This tests checks the parsing of control requests to endpoint 0 cause the correct changes in mixer output routing */
#include <stdint.h>
#include <stddef.h>
#include "platform.h"
#include "xua.h"
#include "debug_print.h"
#include "assert.h"
#include "xud.h"
#include "usbaudio20.h"
#include "random.h"
#ifndef TEST_ITERATIONS
#define TEST_ITERATIONS (100)
#endif
#include "./../test_mixer_routing_output/src/mixer_test_shared.h"
/* Device channel mapping */
extern unsigned char channelMapAud[NUM_USB_CHAN_OUT];
extern unsigned char channelMapUsb[NUM_USB_CHAN_IN];
/* From xua_ep0_uacreqs.xc */
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend ?c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl);
/* From xua_endpoint0.c */
void InitLocalMixerState();
int g_src = 0;
/* Override func in lib_xud/src/user/client/XUD_EpFunctions.c for testing purposes */
XUD_Result_t XUD_GetBuffer(XUD_ep ep_out, unsigned char buffer[], REFERENCE_PARAM(unsigned, length))
{
buffer[0] = g_src;
return XUD_RES_OKAY;
}
XUD_Result_t XUD_DoSetRequestStatus(XUD_ep ep_in)
{
return XUD_RES_OKAY;
}
XUD_Result_t XUD_SetBuffer_EpMax(XUD_ep ep_in, unsigned char buffer[], unsigned datalength, unsigned epMax)
{
assert(g_src == buffer[0]);
assert(datalength == 1);
return XUD_RES_OKAY;
}
unsafe
{
extern int volatile * const unsafe samples_to_device_map;
extern int volatile * const unsafe samples_to_host_map;
}
void Fake_Endpoint0(chanend c_mix_ctl)
{
XUD_ep ep0_out; /* Never initialised but not used */
XUD_ep ep0_in; /* Never initialised but not used */
unsigned unitIds[] = {ID_XU_OUT, ID_XU_IN};
USB_SetupPacket_t sp;
random_generator_t rg = random_create_generator_from_seed(TEST_SEED);
InitLocalMixerState();
sp.bmRequestType.Type = USB_BM_REQTYPE_TYPE_CLASS; // Note, parsing of this won't be tested since we call AudioClassRequests directly
sp.bmRequestType.Recipient = USB_BM_REQTYPE_RECIP_INTER; // Note, parsing of this won't be tested since we call AudioClassRequests directly
for(int testIter = 0; testIter < TEST_ITERATIONS; testIter++)
{
int unitId = unitIds[random_get_random_number(rg) % (sizeof(unitIds)/sizeof(unitIds[0]))];
unsigned dst = random_get_random_number(rg);
/* Note, we don't currently support a mix input derived from another mix
* This is not trivial to test since the current mixer implementation only allows for one
* config update per "trigger"
*/
int src = random_get_random_number(rg) % NUM_USB_CHAN_IN + NUM_USB_CHAN_OUT;
switch(unitId)
{
case ID_XU_OUT:
dst %= CHANNEL_MAP_AUD_SIZE;
debug_printf("Mapping output to AudioIF: %d", dst);
debug_printf(" from %d", src);
PrintSourceString(src);
debug_printf("\n");
break;
case ID_XU_IN:
dst %= CHANNEL_MAP_USB_SIZE;
debug_printf("Mapping output to Host : %d", dst);
debug_printf(" from %d", src);
PrintSourceString(src);
debug_printf("\n");
break;
default:
printstr("ERROR: Bad cmd in stim(): ");
printintln(unitId);
break;
}
/* Create Control request data for routing change */
sp.bmRequestType.Direction = USB_BM_REQTYPE_DIRECTION_H2D;
sp.bRequest = CUR;
sp.wValue = dst & 0xff;
sp.wIndex = (unitId << 8);
sp.wLength = 1;
g_src = src; /* This will get picked up by out implementation of XUD_GetBuffer */
/* Call the function used by Endpoint0() to parse the control data and update the mixer output routing */
AudioClassRequests_2(ep0_out, ep0_in, sp, null, c_mix_ctl, null);
/* Note, there is a race risk here. This could be resolved by adding a handshake to UpdateMixerOutputRouting() etc */
/* Now check the mixer setting have been modified as expected. To do this we inspect "internal"
* mixer and endpoint 0 state.
*
* Going forward we might wish to enhance the mixer API such that it can be tested as a black box.
* This would require the addition of "GET" API over it's ctrl channel
*/
switch(unitId)
{
case ID_XU_OUT:
assert(g_src == channelMapAud[dst]);
unsafe
{
assert(g_src == samples_to_device_map[dst]);
}
break;
case ID_XU_IN:
assert(g_src == channelMapUsb[dst]);
unsafe
{
assert(g_src == samples_to_host_map[dst]);
}
break;
default:
assert(0);
break;
}
/* Test read back. Note, the checking is our overridden implementation of XUD_SetBuffer_EpMax*/
sp.bmRequestType.Direction = USB_BM_REQTYPE_DIRECTION_D2H;
AudioClassRequests_2(ep0_out, ep0_in, sp, null, c_mix_ctl, null);
}
printstrln("PASS");
exit(0);
}
void Fake_XUA_AudioHub_CtrlTest(chanend c_mix_aud)
{
int readBuffNo = 0;
unsigned underflowWord = 0;
/* Continually send/receive samples to/from mixer, no checking of samples since this is purely a control test */
while(1)
{
unsigned command = DoSampleTransfer(c_mix_aud, readBuffNo, underflowWord);
}
}
void Fake_XUA_Buffer_Decouple_CtrlTest(chanend c_dec_mix)
{
unsigned samplesIn[NUM_USB_CHAN_IN];
unsigned underflowSample;
/* Continually send/receive samples to/from mixer, no checking of samples since this is purely a control test */
while(1)
{
select
{
case inuint_byref(c_dec_mix, underflowSample):
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{
outuint(c_dec_mix, 0);
}
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{
samplesIn[i] = inuint(c_dec_mix);
}
break;
}
}
}
int main()
{
chan c_dec_mix;
chan c_mix_aud;
chan c_mix_ctl;
par
{
/* We need "fake" versions of the AudioHub and Decouple to keep the mixer running and taking updates via
* it's control channel */
Fake_XUA_Buffer_Decouple_CtrlTest(c_dec_mix);
Fake_XUA_AudioHub_CtrlTest(c_mix_aud);
/* Mixer from lib_xua */
mixer(c_dec_mix, c_mix_aud, c_mix_ctl);
Fake_Endpoint0(c_mix_ctl);
}
/* TODO to hit this we need to fully close down i.e. kill mixer */
return 0;
}

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
<Declarations>
<Declaration>tileref tile[2]</Declaration>
</Declarations>
<Packages>
<Package id="0" Type="XS3-UnA-1024-FB265">
<Nodes>
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" ReferenceFrequency="100MHz">
<Tile Number="0" Reference="tile[0]"/>
<Tile Number="1" Reference="tile[1]"/>
</Node>
</Nodes>
</Package>
</Packages>
<JTAGChain>
<JTAGDevice NodeId="0"/>
</JTAGChain>
</Network>

View File

@@ -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