merge testing branch and osx updates into branch
This commit is contained in:
55
.gitignore
vendored
55
.gitignore
vendored
@@ -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/*
|
||||
|
||||
@@ -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
|
||||
-----
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
all:
|
||||
g++ -g -o xmos_mixer OSX/usb_mixer.cpp mixer_app.cpp -I. -IOSX OSX/libusb-1.0.0.dylib -arch x86_64
|
||||
|
||||
@@ -140,33 +140,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)
|
||||
@@ -253,7 +253,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);
|
||||
}
|
||||
|
||||
@@ -436,8 +436,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];
|
||||
}
|
||||
|
||||
@@ -783,25 +792,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)
|
||||
@@ -811,13 +822,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]);
|
||||
}
|
||||
|
||||
@@ -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],...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -176,7 +176,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)
|
||||
{
|
||||
@@ -191,7 +190,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);
|
||||
}
|
||||
}
|
||||
@@ -565,27 +564,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;
|
||||
}
|
||||
@@ -593,8 +591,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)
|
||||
|
||||
@@ -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)
|
||||
@@ -1,9 +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.
|
||||
#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_
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// 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_
|
||||
|
||||
#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<<XUA_MIXER_MULT_FRAC_BITS) /* i.e. multiply by 0 */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,9 +3,9 @@ VERSION = 3.3.1
|
||||
DEBUG ?= 0
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
DEBUG_FLAGS = -g -DXASSERT_ENABLE_ASSERTIONS_DECOUPLE=1
|
||||
DEBUG_FLAGS = -g -DXASSERT_ENABLE_ASSERTIONS=1 -DXASSERT_ENABLE_DEBUG=1 -DXASSERT_ENABLE_LINE_NUMBERS=1
|
||||
else
|
||||
DEBUG_FLAGS = -DXASSERT_DISABLE_ASSERTIONS_DECOUPLE=1
|
||||
DEBUG_FLAGS = -DXASSERT_ENABLE_ASSERTIONS=0 -DXASSERT_ENABLE_DEBUG=0 -DXASSERT_ENABLE_LINE_NUMBERS=0
|
||||
endif
|
||||
|
||||
DEPENDENT_MODULES = lib_locks(>=2.1.0) \
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -89,69 +89,7 @@ unsigned dsdMode = DSD_MODE_OFF;
|
||||
#if (XUA_ADAT_TX_EN)
|
||||
#include "audiohub_adat.h"
|
||||
#endif
|
||||
|
||||
#pragma unsafe arrays
|
||||
static 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;
|
||||
}
|
||||
#include "xua_audiohub_st.h"
|
||||
|
||||
static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:32 p_lrclk)
|
||||
{
|
||||
|
||||
66
lib_xua/src/core/audiohub/xua_audiohub_st.h
Normal file
66
lib_xua/src/core/audiohub/xua_audiohub_st.h
Normal file
@@ -0,0 +1,66 @@
|
||||
// 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
@@ -106,13 +106,17 @@ 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
|
||||
unsigned char mixer1Crossbar[18];
|
||||
short mixer1Weights[18*8];
|
||||
#if (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
|
||||
|
||||
@@ -425,14 +429,15 @@ 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 < 18*8; 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;
|
||||
@@ -457,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++)
|
||||
|
||||
@@ -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
|
||||
@@ -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): */
|
||||
|
||||
@@ -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
|
||||
@@ -31,8 +31,7 @@ extern int volsIn[];
|
||||
extern unsigned int mutesIn[];
|
||||
|
||||
/* Mixer settings */
|
||||
#ifdef MIXER
|
||||
extern unsigned char mixer1Crossbar[];
|
||||
#if (MIXER)
|
||||
extern short mixer1Weights[];
|
||||
|
||||
/* Device channel mapping */
|
||||
@@ -133,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)
|
||||
@@ -153,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);
|
||||
@@ -179,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);
|
||||
@@ -202,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 */
|
||||
@@ -226,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);
|
||||
@@ -244,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);
|
||||
@@ -266,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
|
||||
@@ -632,78 +657,69 @@ 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 */
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
/* 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)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
|
||||
@@ -730,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)
|
||||
@@ -745,21 +759,17 @@ 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, mixSel[i][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 */
|
||||
mixSel[cn-1][cn] = source;
|
||||
UpdateMixMap(c_mix_ctl, cs-1, cn, mixSel[cs-1][cn]);
|
||||
}
|
||||
|
||||
return XUD_DoSetRequestStatus(ep0_in);
|
||||
@@ -807,15 +817,16 @@ 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))
|
||||
{
|
||||
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 */
|
||||
@@ -957,7 +968,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);
|
||||
@@ -977,7 +988,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;
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -1,25 +1,40 @@
|
||||
// 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 <xs1.h>
|
||||
#include <print.h>
|
||||
#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)
|
||||
@@ -35,35 +50,38 @@ 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" */
|
||||
xc_ptr samples;
|
||||
static int samples_to_host_map_array[NUM_USB_CHAN_IN];
|
||||
static 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 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;
|
||||
|
||||
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;
|
||||
#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;
|
||||
@@ -77,19 +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 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)
|
||||
{
|
||||
int x;
|
||||
@@ -108,22 +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(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(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(xc_ptr 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;
|
||||
@@ -131,19 +136,18 @@ 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<MIX_INPUTS; i++)
|
||||
{
|
||||
int sample;
|
||||
int index;
|
||||
int m;
|
||||
read_via_xc_ptr_indexed(index, ptr, i);
|
||||
read_via_xc_ptr_indexed(sample,samples,index);
|
||||
read_via_xc_ptr_indexed(m, mult, i);
|
||||
{h,l} = macs(sample, m, h, l);
|
||||
unsafe{
|
||||
int sample;
|
||||
int source;
|
||||
int weight;
|
||||
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);
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* Perform saturation */
|
||||
l = sext(h, 25);
|
||||
l = sext(h, XUA_MIXER_MULT_FRAC_BITS);
|
||||
|
||||
if(l != h)
|
||||
{
|
||||
@@ -152,15 +156,14 @@ static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult)
|
||||
else
|
||||
h = (0x7fffff00>>7);
|
||||
}
|
||||
#endif
|
||||
return h<<7;
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma unsafe arrays
|
||||
static inline void GiveSamplesToHost(chanend c, xc_ptr ptr, 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;
|
||||
@@ -170,25 +173,28 @@ static inline void GiveSamplesToHost(chanend c, xc_ptr ptr, xc_ptr multIn)
|
||||
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||
{
|
||||
int sample;
|
||||
int index;
|
||||
|
||||
#if MAX_MIX_COUNT > 0
|
||||
read_via_xc_ptr_indexed(index,ptr,i);
|
||||
#else
|
||||
index = i + NUM_USB_CHAN_OUT;
|
||||
#endif
|
||||
#if (MAX_MIX_COUNT > 0)
|
||||
unsafe
|
||||
{
|
||||
//read_via_xc_ptr_indexed(sample,samples,index);
|
||||
sample = ptr_samples[index];
|
||||
sample = ptr_samples[hostMap[i]];
|
||||
}
|
||||
#else
|
||||
unsafe
|
||||
{
|
||||
sample = ptr_samples[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);
|
||||
@@ -209,7 +215,7 @@ static inline void GetSamplesFromHost(chanend c)
|
||||
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||
unsafe {
|
||||
int sample, x;
|
||||
#if defined(OUT_VOLUME_IN_MIXER) && !defined(OUT_VOLUME_AFTER_MIX)
|
||||
#if (OUT_VOLUME_IN_MIXER && OUT_VOLUME_AFTER_MIX)
|
||||
int mult;
|
||||
int h;
|
||||
unsigned l;
|
||||
@@ -226,16 +232,15 @@ static inline void GetSamplesFromHost(chanend c)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OUT_VOLUME_IN_MIXER) && !defined(OUT_VOLUME_AFTER_MIX)
|
||||
#if (OUT_VOLUME_IN_MIXER && OUT_VOLUME_AFTER_MIX)
|
||||
#warning OUT Vols in mixer, BEFORE mix & map
|
||||
read_via_xc_ptr_indexed(mult, multOut, i);
|
||||
mult = multOut[i];
|
||||
{h, l} = macs(mult, sample, 0, 0);
|
||||
h<<=3;
|
||||
#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
|
||||
write_via_xc_ptr_indexed(multOut, index, val);
|
||||
write_via_xc_ptr_indexed(samples_array, i, h);
|
||||
#else
|
||||
ptr_samples[i] = sample;
|
||||
@@ -246,30 +251,29 @@ 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)
|
||||
{
|
||||
#if(NUM_USB_CHAN_OUT == 0)
|
||||
#if (NUM_USB_CHAN_OUT == 0)
|
||||
outuint(c, 0);
|
||||
#else
|
||||
#pragma loop unroll
|
||||
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||
{
|
||||
int sample, x;
|
||||
#if defined(OUT_VOLUME_IN_MIXER) && defined(OUT_VOLUME_AFTER_MIX)
|
||||
#if (OUT_VOLUME_IN_MIXER && OUT_VOLUME_AFTER_MIX)
|
||||
int mult;
|
||||
int h;
|
||||
unsigned l;
|
||||
#endif
|
||||
int index;
|
||||
|
||||
#if MAX_MIX_COUNT > 0
|
||||
#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 */
|
||||
read_via_xc_ptr_indexed(sample, samples, index);
|
||||
unsafe
|
||||
{
|
||||
/* Read index to sample from the map then Read the actual sample value */
|
||||
sample = ptr_samples[deviceMap[i]];
|
||||
}
|
||||
#else
|
||||
unsafe
|
||||
{
|
||||
@@ -278,16 +282,19 @@ static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut)
|
||||
}
|
||||
#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
|
||||
#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
|
||||
// Note: We need all 32bits for Native DSD
|
||||
#endif
|
||||
outuint(c, h);
|
||||
#else
|
||||
@@ -300,14 +307,14 @@ static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut)
|
||||
#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;
|
||||
#endif
|
||||
|
||||
#pragma loop unroll
|
||||
for (int i=0;i<NUM_USB_CHAN_IN;i++)
|
||||
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||
{
|
||||
int sample;
|
||||
int x;
|
||||
@@ -327,19 +334,23 @@ 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);
|
||||
h <<=3;
|
||||
write_via_xc_ptr_indexed(samples_array, NUM_USB_CHAN_OUT+i, h);
|
||||
write_via_xc_ptr_indexed(samples_array, XUA_MIXER_OFFSET_IN+i, h);
|
||||
#else
|
||||
/* No volume processing */
|
||||
unsafe
|
||||
{
|
||||
ptr_samples[NUM_USB_CHAN_OUT + i] = sample;
|
||||
assert((XUA_MIXER_OFFSET_IN + i) < (NUM_USB_CHAN_IN + NUM_USB_CHAN_OUT));
|
||||
ptr_samples[XUA_MIXER_OFFSET_IN + i] = sample;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -353,12 +364,13 @@ 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)
|
||||
{
|
||||
#pragma xta endpoint "mixer1_req"
|
||||
/* Request from audio()/mixer2() */
|
||||
request = inuint(c_mixer2);
|
||||
|
||||
@@ -369,8 +381,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 (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):
|
||||
@@ -378,19 +391,43 @@ 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);
|
||||
inct(c_mix_ctl);
|
||||
write_via_xc_ptr_indexed(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);
|
||||
write_via_xc_ptr_indexed(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;
|
||||
|
||||
case SET_MIX_MULT:
|
||||
@@ -399,40 +436,80 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
||||
val = inuint(c_mix_ctl);
|
||||
inct(c_mix_ctl);
|
||||
|
||||
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"));
|
||||
|
||||
if((index < MIX_INPUTS) && (mix < MAX_MIX_COUNT))
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
mix_mult[(mix * MIX_INPUTS) + index] = val;
|
||||
}
|
||||
}
|
||||
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);
|
||||
#ifdef FAST_MIXER
|
||||
setPtr(index, val, mix);
|
||||
{
|
||||
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))
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
setPtr(input, source, mix);
|
||||
#else
|
||||
write_word_to_mix_map(mix, index, val);
|
||||
#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);
|
||||
|
||||
assert((index < (NUM_USB_CHAN_IN + 1)) && msg("In volume index out of range"));
|
||||
|
||||
write_via_xc_ptr_indexed(multIn, index, val);
|
||||
if(index < NUM_USB_CHAN_IN + 1)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
multIn[index] = val;
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
assert((index < (NUM_USB_CHAN_OUT + 1)) && msg("Out volume index out of range"));
|
||||
|
||||
write_via_xc_ptr_indexed(multOut, index, val);
|
||||
if(index < NUM_USB_CHAN_OUT + 1)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
multOut[index] = val;
|
||||
}
|
||||
}
|
||||
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);
|
||||
@@ -441,42 +518,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
|
||||
}
|
||||
break;
|
||||
@@ -484,14 +525,13 @@ 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))
|
||||
{
|
||||
int sampFreq;
|
||||
#pragma xta endpoint "mixer1_rate_change"
|
||||
unsigned command = inct(c_host);
|
||||
|
||||
switch(command)
|
||||
@@ -520,9 +560,8 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
||||
|
||||
#pragma loop unroll
|
||||
/* Reset the mix values back to 0 */
|
||||
for (int i=0;i<MAX_MIX_COUNT;i++)
|
||||
for (int i=0; i<MAX_MIX_COUNT; i++)
|
||||
{
|
||||
//write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i), 0);
|
||||
unsafe
|
||||
{
|
||||
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i] = 0;
|
||||
@@ -535,21 +574,24 @@ 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(samples, mix_mult_slice(0));
|
||||
unsafe
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
mixed = doMix0(ptr_samples, slice(mix_mult, 0));
|
||||
#else
|
||||
mixed = doMix(samples, mix_map_slice(0),mix_mult_slice(0));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 0), slice(mix_mult, 0));
|
||||
#endif
|
||||
write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 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);
|
||||
@@ -560,40 +602,46 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
||||
#endif
|
||||
{
|
||||
|
||||
#if MAX_MIX_COUNT > 2
|
||||
#ifdef FAST_MIXER
|
||||
mixed = doMix2(samples, mix_mult_slice(2));
|
||||
#if (MAX_MIX_COUNT > 2)
|
||||
unsafe
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
mixed = doMix2(ptr_samples, slice(mix_mult, 2));
|
||||
#else
|
||||
mixed = doMix(samples, mix_map_slice(2),mix_mult_slice(2));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 2), slice(mix_mult, 2));
|
||||
#endif
|
||||
write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 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
|
||||
#endif
|
||||
|
||||
#if MAX_MIX_COUNT > 4
|
||||
#ifdef FAST_MIXER
|
||||
mixed = doMix4(samples, mix_mult_slice(4));
|
||||
#if (MAX_MIX_COUNT > 4)
|
||||
unsafe
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
mixed = doMix4(ptr_samples, slice(mix_mult, 4));
|
||||
#else
|
||||
mixed = doMix(samples, mix_map_slice(4),mix_mult_slice(4));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 4), slice(mix_mult, 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
|
||||
#ifdef FAST_MIXER
|
||||
mixed = doMix6(samples, mix_mult_slice(6));
|
||||
#if (MAX_MIX_COUNT > 6)
|
||||
unsafe
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
mixed = doMix6(ptr_samples, slice(mix_mult, 6));
|
||||
#else
|
||||
mixed = doMix(samples, mix_map_slice(6),mix_mult_slice(6));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 6), slice(mix_mult, 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
|
||||
@@ -601,10 +649,10 @@ 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);
|
||||
GiveSamplesToHost(c_host, samples_to_host_map);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -621,7 +669,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 */
|
||||
@@ -633,7 +680,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)
|
||||
@@ -660,8 +706,8 @@ static void mixer2(chanend c_mixer1, chanend c_audio)
|
||||
}
|
||||
|
||||
for (int i=0;i<MAX_MIX_COUNT;i++)
|
||||
{
|
||||
write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i), 0);
|
||||
unsafe{
|
||||
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i] = 0;
|
||||
}
|
||||
|
||||
/* Wait for handshake and pass on */
|
||||
@@ -670,7 +716,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) */
|
||||
@@ -678,61 +724,67 @@ static void mixer2(chanend c_mixer1, chanend c_audio)
|
||||
outuint(c_mixer1, 0);
|
||||
|
||||
/* Do the mixing */
|
||||
#if MAX_MIX_COUNT > 1
|
||||
#ifdef FAST_MIXER
|
||||
mixed = doMix1(samples, mix_mult_slice(1));
|
||||
#if (MAX_MIX_COUNT > 1)
|
||||
unsafe
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
mixed = doMix1(ptr_samples, slice(mix_mult, 1));
|
||||
#else
|
||||
mixed = doMix(samples, mix_map_slice(1),mix_mult_slice(1));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 1), slice(mix_mult, 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
|
||||
#ifdef FAST_MIXER
|
||||
mixed = doMix3(samples, mix_mult_slice(3));
|
||||
#if (MAX_MIX_COUNT > 3)
|
||||
unsafe
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
mixed = doMix3(ptr_samples, slice(mix_mult, 3));
|
||||
#else
|
||||
mixed = doMix(samples, mix_map_slice(3),mix_mult_slice(3));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 3), slice(mix_mult, 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
|
||||
#ifdef FAST_MIXER
|
||||
mixed = doMix5(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(samples, mix_map_slice(5),mix_mult_slice(5));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 5), slice(mix_mult, 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
|
||||
#ifdef FAST_MIXER
|
||||
mixed = doMix7(samples, mix_mult_slice(7));
|
||||
#if (MAX_MIX_COUNT > 7)
|
||||
unsafe
|
||||
{
|
||||
#if (FAST_MIXER)
|
||||
mixed = doMix7(ptr_samples, slice(mix_mult, 7));
|
||||
#else
|
||||
mixed = doMix(samples, mix_map_slice(7),mix_mult_slice(7));
|
||||
mixed = doMix(ptr_samples, slice(mix_map, 7), slice(mix_mult, 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
|
||||
@@ -748,68 +800,52 @@ 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[]));
|
||||
|
||||
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[]));
|
||||
|
||||
#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<NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT;i++)
|
||||
unsafe {
|
||||
//write_via_xc_ptr_indexed(samples,i,0);
|
||||
ptr_samples[i] = 0;
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||
{
|
||||
int num_mixes = DEFAULT_FREQ > 96000 ? 2 : MAX_MIX_COUNT;
|
||||
for (int i=0;i<NUM_USB_CHAN_OUT;i++)
|
||||
{
|
||||
//samples_to_device_map_array[i] = i;
|
||||
asm("stw %0, %1[%2]":: "r"(i), "r"(samples_to_device_map), "r"(i));
|
||||
}
|
||||
samples_to_device_map_array[i] = i;
|
||||
}
|
||||
|
||||
#ifdef OUT_VOLUME_IN_MIXER
|
||||
for (int i=0;i<NUM_USB_CHAN_OUT;i++)
|
||||
{
|
||||
write_via_xc_ptr_indexed(multOut, i, MAX_VOL);
|
||||
#if (OUT_VOLUME_IN_MIXER)
|
||||
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||
unsafe{
|
||||
multOut[i] = MAX_VOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IN_VOLUME_IN_MIXER
|
||||
for (int i=0;i<NUM_USB_CHAN_IN;i++)
|
||||
{
|
||||
write_via_xc_ptr_indexed(multIn, i, MAX_VOL);
|
||||
#if (IN_VOLUME_IN_MIXER)
|
||||
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||
unsafe{
|
||||
multIn[i] = MAX_VOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i=0;i<NUM_USB_CHAN_IN;i++)
|
||||
{
|
||||
write_via_xc_ptr_indexed(samples_to_host_map, i, NUM_USB_CHAN_OUT + i);
|
||||
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||
unsafe{
|
||||
samples_to_host_map[i] = XUA_MIXER_OFFSET_IN + i;
|
||||
}
|
||||
|
||||
#if MAX_MIX_COUNT> 0
|
||||
#if (MAX_MIX_COUNT> 0)
|
||||
for (int i=0;i<MAX_MIX_COUNT;i++)
|
||||
for (int j=0;j<MIX_INPUTS;j++)
|
||||
{
|
||||
#ifndef FAST_MIXER
|
||||
write_word_to_mix_map(i,j, j < 16 ? j : j + 2);
|
||||
unsafe{
|
||||
#if (FAST_MIXER == 0)
|
||||
mix_map[i * MIX_INPUTS + j] = (j < 16 ? j : j + 2);
|
||||
#endif
|
||||
write_word_to_mix_mult(i,j, i==j ? db_to_mult(0, 8, 25) : 0);
|
||||
mix_mult[i * MIX_INPUTS + j] = (i==j ? db_to_mult(0, XUA_MIXER_DB_FRAC_BITS, XUA_MIXER_MULT_FRAC_BITS) : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
# 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
|
||||
|
||||
|
||||
@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):
|
||||
|
||||
45
tests/test_mixer_routing_input.py
Normal file
45
tests/test_mixer_routing_input.py
Normal file
@@ -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
|
||||
19
tests/test_mixer_routing_input/Makefile
Normal file
19
tests/test_mixer_routing_input/Makefile
Normal 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)
|
||||
|
||||
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
|
||||
243
tests/test_mixer_routing_input/src/main.xc
Normal file
243
tests/test_mixer_routing_input/src/main.xc
Normal file
@@ -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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#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<NUM_USB_CHAN_OUT; i++)
|
||||
{
|
||||
int src = modelMixer.deviceMap[i];
|
||||
modelOut[i] = CreateSample(modelMixer.mixOutput, src);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i<NUM_USB_CHAN_IN; i++)
|
||||
{
|
||||
int src = modelMixer.hostMap[i];
|
||||
modelIn[i] = CreateSample(modelMixer.mixOutput, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MapMixerInput(int mix, int input, int src, struct ModelMixer &modelMixer, chanend c_mix_ctl,
|
||||
chanend c_stim_ah, chanend c_stim_de, uint32_t modelIn[], uint32_t modelOut[])
|
||||
{
|
||||
debug_printf("Mapping mix %d input %d", mix, input);
|
||||
debug_printf(" from %d", src);
|
||||
PrintSourceString(src);
|
||||
debug_printf("\n");
|
||||
|
||||
/* This test only allows for one input to travel "untouched" to the mix output - since this test doesn't model the actual mixing.
|
||||
* Because of this we must also mod the mixer weights, not just the mixer input map.
|
||||
* If we simply just apply an update to the mixer input mapping it would not produce an observable difference on the mixer output
|
||||
*/
|
||||
|
||||
/* Set previously "activated" input weight to 0 */
|
||||
debug_printf("Setting mix %d, weight %d to 0\n", mix, modelMixer.mixMap_input[mix]);
|
||||
SendTrigger(c_stim_ah, 1);
|
||||
UpdateMixerWeight(c_mix_ctl, mix, modelMixer.mixMap_input[mix], 0);
|
||||
|
||||
/* Set new "activated" input wright to max (i.e. x1) */
|
||||
debug_printf("Setting mix %d, weight %d to %x\n", mix, input, XUA_MIXER_MAX_MULT);
|
||||
SendTrigger(c_stim_ah, 1);
|
||||
UpdateMixerWeight(c_mix_ctl, mix, input, XUA_MIXER_MAX_MULT);
|
||||
|
||||
/* Update mixer input in model */
|
||||
modelMixer.mixMap_src[mix] = src;
|
||||
modelMixer.mixMap_input[mix] = input;
|
||||
|
||||
/* Run twice to allow mix inputs derived from mix outputs to propagate */
|
||||
GenExpectedSamples(modelMixer, modelOut, modelIn);
|
||||
|
||||
/* Finally update the acutal mixer input map */
|
||||
SendTrigger(c_stim_ah, 1);
|
||||
UpdateMixMap(c_mix_ctl, mix, input, src);
|
||||
|
||||
SendTrigger(c_stim_ah, 1);
|
||||
|
||||
SendExpected(c_stim_ah, c_stim_de, modelOut, modelIn);
|
||||
}
|
||||
|
||||
|
||||
/* 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[NUM_USB_CHAN_OUT];
|
||||
uint32_t modelIn[NUM_USB_CHAN_IN];
|
||||
|
||||
random_generator_t rg = random_create_generator_from_seed(TEST_SEED);
|
||||
|
||||
struct ModelMixer modelMixer;
|
||||
|
||||
InitModel(modelMixer);
|
||||
|
||||
GenExpectedSamples(modelMixer, modelOut, modelIn);
|
||||
|
||||
/* There is single sample delay between the two mixer cores, so trigger twice to flush though a block
|
||||
* of zero samples */
|
||||
SendTrigger(c_stim_ah, 2);
|
||||
|
||||
/* Send expected samples to AH and DE and run checks */
|
||||
SendExpected(c_stim_ah, c_stim_de, modelOut, modelIn);
|
||||
|
||||
/* Firstly route mixer outputs to the audio interfaces (we could have chosen host)
|
||||
* such that we can observe and check the outputs from the mixer
|
||||
*/
|
||||
for(size_t i = 0; i < MAX_MIX_COUNT; i++)
|
||||
{
|
||||
int map = SET_SAMPLES_TO_DEVICE_MAP;
|
||||
assert(i < NUM_USB_CHAN_OUT);
|
||||
int dst = i;
|
||||
int src = NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN+i; // mix0, mix1..
|
||||
debug_printf("Mapping output to AudioIF: %d ", dst);
|
||||
|
||||
PrintDestString(map, dst);
|
||||
debug_printf(" from %d", src);
|
||||
PrintSourceString(src);
|
||||
debug_printf("\n");
|
||||
|
||||
SendTrigger(c_stim_ah, 1);
|
||||
|
||||
/* Update the mixer */
|
||||
UpdateMixerOutputRouting(c_mix_ctl, map, dst, src);
|
||||
|
||||
/* Update the model */
|
||||
modelMixer.deviceMap[dst] = src;
|
||||
}
|
||||
|
||||
/* Send expected samples to fake AudioHub and Decouple for checking */
|
||||
SendExpected(c_stim_ah, c_stim_de, modelOut, modelIn);
|
||||
|
||||
for(int testIter = 0; testIter < TEST_ITERATIONS; testIter++)
|
||||
{
|
||||
/* Make a random update to the routing - route a random source to a random mix input */
|
||||
unsigned mix = random_get_random_number(rg) % MAX_MIX_COUNT;
|
||||
unsigned input = random_get_random_number(rg) % MIX_INPUTS;
|
||||
|
||||
/* Note, we don't currently support a mix input dervived from another mix
|
||||
* This is not trivial to test since the current mixer implementation only allows for one
|
||||
* config update per "trigger"
|
||||
*/
|
||||
unsigned src = random_get_random_number(rg) % NUM_USB_CHAN_IN + NUM_USB_CHAN_OUT;
|
||||
|
||||
debug_printf("Iteration: %d\n", testIter);
|
||||
MapMixerInput(mix, input, src, modelMixer, c_mix_ctl, c_stim_ah, c_stim_de, modelIn, modelOut);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
24
tests/test_mixer_routing_input/src/test_xs3_600.xn
Normal file
24
tests/test_mixer_routing_input/src/test_xs3_600.xn
Normal 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>
|
||||
45
tests/test_mixer_routing_input/src/xua_conf.h
Normal file
45
tests/test_mixer_routing_input/src/xua_conf.h
Normal 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
|
||||
45
tests/test_mixer_routing_output.py
Normal file
45
tests/test_mixer_routing_output.py
Normal file
@@ -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_output(options, capfd, test_file, test_seed):
|
||||
|
||||
result = do_test(options, capfd, test_file, test_seed)
|
||||
|
||||
assert result
|
||||
19
tests/test_mixer_routing_output/Makefile
Normal file
19
tests/test_mixer_routing_output/Makefile
Normal 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)
|
||||
|
||||
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
|
||||
224
tests/test_mixer_routing_output/src/main.xc
Normal file
224
tests/test_mixer_routing_output/src/main.xc
Normal file
@@ -0,0 +1,224 @@
|
||||
// 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
|
||||
*
|
||||
* "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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "platform.h"
|
||||
#include "xua.h"
|
||||
#include "debug_print.h"
|
||||
#include "assert.h"
|
||||
#include "random.h"
|
||||
|
||||
#ifndef TEST_ITERATIONS
|
||||
#define TEST_ITERATIONS (100)
|
||||
#endif
|
||||
|
||||
#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)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Check default routing */
|
||||
/* Send expected to AudioHub */
|
||||
SendTrigger(c_stim_ah, 2);
|
||||
SendExpected(c_stim_ah, c_stim_de, modelOut, modelIn);
|
||||
|
||||
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 */
|
||||
SendTrigger(c_stim_ah, 1);
|
||||
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 */
|
||||
SendTrigger(c_stim_ah, 1);
|
||||
UpdateMixerOutputRouting(c_mix_ctl, map, dst, src);
|
||||
break;
|
||||
|
||||
default:
|
||||
printstr("ERROR: Bad cmd in stim(): ");
|
||||
printintln(map);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update the model */
|
||||
UpdateModel(modelOut, modelMixerOut, modelIn, map, dst, src);
|
||||
|
||||
SendExpected(c_stim_ah, c_stim_de, modelOut, modelIn);
|
||||
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
323
tests/test_mixer_routing_output/src/mixer_test_shared.h
Normal file
323
tests/test_mixer_routing_output/src/mixer_test_shared.h
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
24
tests/test_mixer_routing_output/src/test_xs3_600.xn
Normal file
24
tests/test_mixer_routing_output/src/test_xs3_600.xn
Normal 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>
|
||||
45
tests/test_mixer_routing_output/src/xua_conf.h
Normal file
45
tests/test_mixer_routing_output/src/xua_conf.h
Normal 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
|
||||
Reference in New Issue
Block a user