diff --git a/examples/xua_lite_example/Makefile b/examples/xua_lite_example/Makefile deleted file mode 100644 index daa7dc5f..00000000 --- a/examples/xua_lite_example/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -APP_NAME = - -TARGET = RPI_HAT_60QFN.xn - -# The flags passed to xcc when building the application -XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -Os -report \ - -g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES -DUSB_TILE=tile[1] \ - -D MIC_ARRAY_CH0=PIN0 -D MIC_ARRAY_CH1=PIN4 - -# The USED_MODULES variable lists other module used by the application. These -# modules will extend the SOURCE_DIRS, INCLUDE_DIRS and LIB_DIRS variables. -# Modules are expected to be in the directory above the BASE_DIR directory. -USED_MODULES = lib_xua lib_i2s lib_xud lib_i2c lib_mic_array - -#============================================================================= -# The following part of the Makefile includes the common build infrastructure -# for compiling XMOS applications. You should not need to edit below here. - -XMOS_MAKE_PATH ?= ../.. -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common - diff --git a/examples/xua_lite_example/config.xscope b/examples/xua_lite_example/config.xscope deleted file mode 100644 index f336ddac..00000000 --- a/examples/xua_lite_example/config.xscope +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/examples/xua_lite_example/config/RPI_HAT_60QFN.xn b/examples/xua_lite_example/config/RPI_HAT_60QFN.xn deleted file mode 100644 index c0c3f85c..00000000 --- a/examples/xua_lite_example/config/RPI_HAT_60QFN.xn +++ /dev/null @@ -1,66 +0,0 @@ - - - Device - XVF3510 Device - - - tileref tile[2] - tileref usb_tile - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/xua_lite_example/config/xua_conf.h b/examples/xua_lite_example/config/xua_conf.h deleted file mode 100644 index ae9de112..00000000 --- a/examples/xua_lite_example/config/xua_conf.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2017-2018, XMOS Ltd, All rights reserved - -#ifndef _XUA_CONF_H_ -#define _XUA_CONF_H_ - -#define NUM_USB_CHAN_OUT 2 /* Number of channels from host to device */ -#define NUM_USB_CHAN_IN 2 /* Number of channels from device to host */ -#define I2S_CHANS_DAC 2 /* Number of I2S channels out of xCORE */ -#define I2S_CHANS_ADC 2 /* Number of I2S channels in to xCORE */ -#define MCLK_441 (512 * 44100) /* 44.1kHz family master clock frequency */ -#define MCLK_48 (512 * 48000) /* 48kHz family master clock frequency */ -#define MIN_FREQ 48000 /* Minimum sample rate */ -#define MAX_FREQ 48000 /* Maximum sample rate */ - -#define EXCLUDE_USB_AUDIO_MAIN - -#define VENDOR_STR "XMOS" -#define VENDOR_ID 0x20B1 -#define PRODUCT_STR_A2 "XUA Lite Class 2" -#define PRODUCT_STR_A1 "XUA Lite Class 1" -#define PID_AUDIO_1 1 -#define PID_AUDIO_2 2 -#define XUA_DFU_EN 0 /* Disable DFU (for simplicity of example) */ - -#define INPUT_FORMAT_COUNT 1 -#define STREAM_FORMAT_INPUT_1_RESOLUTION_BITS 16 -#define OUTPUT_FORMAT_COUNT 1 -#define STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS 16 - -#define OUTPUT_VOLUME_CONTROL 0 -#define INPUT_VOLUME_CONTROL 0 - -#define UAC_FORCE_FEEDBACK_EP 0 -#define XUA_ADAPTIVE 1 -#define XUA_LITE 1 // Use simple/optimised USB buffer tasks -#define AUDIO_CLASS 1 - -#define XUA_NUM_PDM_MICS 4 // It's actually 2 but we run 4ch and ignore 2 -#define PDM_MAX_DECIMATION (96000/(MIN_FREQ)) - -#endif diff --git a/examples/xua_lite_example/config/xud_conf.h b/examples/xua_lite_example/config/xud_conf.h deleted file mode 100644 index c14d64a8..00000000 --- a/examples/xua_lite_example/config/xud_conf.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2017-2018, XMOS Ltd, All rights reserved - -#include "xua_conf.h" - -/* TODO */ -#define XUD_UAC_NUM_USB_CHAN_OUT NUM_USB_CHAN_OUT -#define XUD_UAC_NUM_USB_CHAN_IN NUM_USB_CHAN_IN diff --git a/examples/xua_lite_example/plot_fill_level.sh b/examples/xua_lite_example/plot_fill_level.sh deleted file mode 100644 index bb2ad5a3..00000000 --- a/examples/xua_lite_example/plot_fill_level.sh +++ /dev/null @@ -1 +0,0 @@ -grep pid: dump.txt | grep -Eo "\-?\d+" > proc.txt && gnuplot -p -e 'set term png; plot "proc.txt" with lines' > plot.png && open plot.png \ No newline at end of file diff --git a/examples/xua_lite_example/src/app_xua_lite.xc b/examples/xua_lite_example/src/app_xua_lite.xc deleted file mode 100644 index 64830667..00000000 --- a/examples/xua_lite_example/src/app_xua_lite.xc +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) 2017-2018, XMOS Ltd, All rights reserved - -// A very simple *example* of a USB audio application (and as such is un-verified for production) -#include - -#include -#include - -#include "xua.h" -#include "xud.h" -#include "i2s.h" -#include "i2c.h" -#include "mic_array.h" -#include "xua_buffer_lite.h" -#include "xua_ep0_wrapper.h" -#include "pdm_mic.h" -#include "audio_config.h" -#include "audio_hub.h" - -#define DEBUG_UNIT XUA_APP -#define DEBUG_PRINT_ENABLE_XUA_APP 1 -#include "debug_print.h" - -// Port declarations. Note, the defines come from the xn file -on tile[0]: buffered out port:32 p_i2s_dac[] = {XS1_PORT_1N}; //DAC -on tile[0]: buffered in port:32 p_i2s_adc[] = {XS1_PORT_1F}; //Unused currently -on tile[0]: buffered out port:32 p_lrclk = XS1_PORT_1O; //I2S Bit-clock -on tile[0]: out port p_bclk = XS1_PORT_1P; //I2S L/R-clock - -// Master clock for the audio IO tile -on tile[0]: in port p_mclk_in = XS1_PORT_1K; - -// [0] : DAC_RESET_N -// [1] : I2C_INTERRUPT_N -// [2] : MUTE_EN -// [3] : LED -on tile[0]: out port p_gpio = XS1_PORT_4D; - -on tile[1]: port p_scl = XS1_PORT_1C; -on tile[1]: port p_sda = XS1_PORT_1D; -on tile[1]: in port p_mclk_in_usb = XS1_PORT_1A; -on tile[1]: in port p_for_mclk_count= XS1_PORT_16A; // Extra port for counting master clock ticks -on tile[1]: clock clk_usb_mclk = XS1_CLKBLK_3; // Master clock - -// Clock-block declarations -on tile[0]: clock clk_audio_bclk = XS1_CLKBLK_2; // Bit clock -on tile[0]: clock clk_audio_mclk = XS1_CLKBLK_3; // Master clock -//XUD uses XS1_CLKBLK_4, XS1_CLKBLK_5 on tile[1] - -//Mic array resources -on tile[0]: out port p_pdm_clk = XS1_PORT_1L; -on tile[0]: in buffered port:32 p_pdm_mics = XS1_PORT_4E; - -on tile[0]: clock pdmclk = XS1_CLKBLK_4; -on tile[0]: clock pdmclk6 = XS1_CLKBLK_5; - - -// Endpoint type tables - informs XUD what the transfer types for each Endpoint in use and also -// if the endpoint wishes to be informed of USB bus resets - -XUD_EpType epTypeTableOut[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_ISO}; -XUD_EpType epTypeTableIn[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_ISO, XUD_EPTYPE_ISO}; - -void burn_normal_priority(void){ - while(1); -} - -void burn_high_priority(void){ - set_core_high_priority_on(); - while(1); -} - -int main() -{ - // Channels for lib_xud - chan c_ep_out[XUA_ENDPOINT_COUNT_OUT]; - chan c_ep_in[XUA_ENDPOINT_COUNT_IN]; - - // Channel for communicating SOF notifications from XUD to the Buffering cores - chan c_sof; - - interface i2s_frame_callback_if i_i2s; - interface i2c_master_if i_i2c[1]; - - streaming chan c_audio; //We use the channel buffering (48B across switch each way) - streaming chan c_ds_output[1]; - - interface ep0_control_if i_ep0_ctl; - - par - { - on tile[0]: { - //Set the GPIOs needed for audio (reset and mute) - setup_audio_gpio(p_gpio); - c_audio <: 0; //Signal that we can now do i2c setup - c_audio :> int _; //Now wait until i2c has finished mclk setup - - const unsigned micDiv = MCLK_48/3072000; - mic_array_setup_ddr(pdmclk, pdmclk6, p_mclk_in, p_pdm_clk, p_pdm_mics, micDiv); - - par { - i2s_frame_master(i_i2s, p_i2s_dac, 1, p_i2s_adc, 1, p_bclk, p_lrclk, p_mclk_in, clk_audio_bclk); - [[distribute]] AudioHub(i_i2s, c_audio, c_ds_output); - pdm_mic(c_ds_output[0], p_pdm_mics); - - par (int i = 0; i < 5; i++) burn_normal_priority(); - par (int i = 0; i < 0; i++) burn_high_priority(); - } - } - on tile[1]:unsafe{ - // Connect master-clock input clock-block to clock-block pin for asnch feedback calculation - set_clock_src(clk_usb_mclk, p_mclk_in_usb); // Clock clock-block from mclk pin - set_port_clock(p_for_mclk_count, clk_usb_mclk); // Clock the "count" port from the clock block - start_clock(clk_usb_mclk); // Set the clock off running - - //Setup DAC over i2c and then return so we do not use a thread - c_audio :> int _; //Wait for reset to be asserted/deasserted by other tile - par{ - i2c_master(i_i2c, 1, p_scl, p_sda, 100); - AudioHwConfigure(DEFAULT_FREQ, i_i2c[0]); - } - c_audio <: 0; //Signal to tile[0] that mclk is now good - - par { - // Low level USB device layer core - XUD_Main(c_ep_out, XUA_ENDPOINT_COUNT_OUT, c_ep_in, XUA_ENDPOINT_COUNT_IN, - c_sof, epTypeTableOut, epTypeTableIn, - null, null, -1 , - (AUDIO_CLASS == 1) ? XUD_SPEED_FS : XUD_SPEED_HS, XUD_PWR_BUS); - - // // Buffering core - handles audio and control data to/from EP's and gives/gets data to/from the audio I/O core - // XUA_Buffer_lite(c_ep_out[0], - // c_ep_in[0], - // c_ep_out[1], - // null, //c_ep_in[XUA_ENDPOINT_COUNT_IN - 2],/*feedback*/ - // c_ep_in[XUA_ENDPOINT_COUNT_IN - 1], - // c_sof, p_for_mclk_count, c_audio); - - //[[combine]] - par{ - XUA_Buffer_lite2(i_ep0_ctl, - c_ep_out[1], - null, //c_ep_in[XUA_ENDPOINT_COUNT_IN - 2],/*feedback*/ - c_ep_in[XUA_ENDPOINT_COUNT_IN - 1], - c_sof, p_for_mclk_count, c_audio); - XUA_Endpoint0_select(c_ep_out[0], c_ep_in[0], i_ep0_ctl, null VENDOR_REQUESTS_PARAMS_DEC_); - } - par (int i = 0; i < 3; i++) burn_normal_priority(); - par (int i = 0; i < 2; i++) burn_high_priority(); - } - }//Tile[1] par - }//Top level par - - return 0; -} - - diff --git a/examples/xua_lite_example/src/audio_config.h b/examples/xua_lite_example/src/audio_config.h deleted file mode 100755 index 6b7c079b..00000000 --- a/examples/xua_lite_example/src/audio_config.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _AUDIO_CONFIG_ -#define _AUDIO_CONFIG_ - -void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c); -void pll_nudge(int nudge); -void setup_audio_gpio(out port p_gpio); - -#endif diff --git a/examples/xua_lite_example/src/audio_config.xc b/examples/xua_lite_example/src/audio_config.xc deleted file mode 100755 index 3235387d..00000000 --- a/examples/xua_lite_example/src/audio_config.xc +++ /dev/null @@ -1,279 +0,0 @@ -#include -#include -#include -#include -#include -#include "i2c.h" -#include "xua.h" -#define DEBUG_UNIT AUDIO_CFG -#define DEBUG_PRINT_ENABLE_AUDIO_CFG 1 -#include "debug_print.h" - - -// TLV320DAC3101 Device I2C Address -#define DAC3101_I2C_DEVICE_ADDR 0x18 - -// TLV320DAC3101 Register Addresses -// Page 0 -#define DAC3101_PAGE_CTRL 0x00 // Register 0 - Page Control -#define DAC3101_SW_RST 0x01 // Register 1 - Software Reset -#define DAC3101_CLK_GEN_MUX 0x04 // Register 4 - Clock-Gen Muxing -#define DAC3101_PLL_P_R 0x05 // Register 5 - PLL P and R Values -#define DAC3101_PLL_J 0x06 // Register 6 - PLL J Value -#define DAC3101_PLL_D_MSB 0x07 // Register 7 - PLL D Value (MSB) -#define DAC3101_PLL_D_LSB 0x08 // Register 8 - PLL D Value (LSB) -#define DAC3101_NDAC_VAL 0x0B // Register 11 - NDAC Divider Value -#define DAC3101_MDAC_VAL 0x0C // Register 12 - MDAC Divider Value -#define DAC3101_DOSR_VAL_LSB 0x0E // Register 14 - DOSR Divider Value (LS Byte) -#define DAC3101_CLKOUT_MUX 0x19 // Register 25 - CLKOUT MUX -#define DAC3101_CLKOUT_M_VAL 0x1A // Register 26 - CLKOUT M_VAL -#define DAC3101_CODEC_IF 0x1B // Register 27 - CODEC Interface Control -#define DAC3101_DAC_DAT_PATH 0x3F // Register 63 - DAC Data Path Setup -#define DAC3101_DAC_VOL 0x40 // Register 64 - DAC Vol Control -#define DAC3101_DACL_VOL_D 0x41 // Register 65 - DAC Left Digital Vol Control -#define DAC3101_DACR_VOL_D 0x42 // Register 66 - DAC Right Digital Vol Control -#define DAC3101_GPIO1_IO 0x33 // Register 51 - GPIO1 In/Out Pin Control -// Page 1 -#define DAC3101_HP_DRVR 0x1F // Register 31 - Headphone Drivers -#define DAC3101_SPK_AMP 0x20 // Register 32 - Class-D Speaker Amp -#define DAC3101_HP_DEPOP 0x21 // Register 33 - Headphone Driver De-pop -#define DAC3101_DAC_OP_MIX 0x23 // Register 35 - DAC_L and DAC_R Output Mixer Routing -#define DAC3101_HPL_VOL_A 0x24 // Register 36 - Analog Volume to HPL -#define DAC3101_HPR_VOL_A 0x25 // Register 37 - Analog Volume to HPR -#define DAC3101_SPKL_VOL_A 0x26 // Register 38 - Analog Volume to Left Speaker -#define DAC3101_SPKR_VOL_A 0x27 // Register 39 - Analog Volume to Right Speaker -#define DAC3101_HPL_DRVR 0x28 // Register 40 - Headphone Left Driver -#define DAC3101_HPR_DRVR 0x29 // Register 41 - Headphone Right Driver -#define DAC3101_SPKL_DRVR 0x2A // Register 42 - Left Class-D Speaker Driver -#define DAC3101_SPKR_DRVR 0x2B // Register 43 - Right Class-D Speaker Driver - -// TLV320DAC3101 easy register access defines -#define DAC3101_REGWRITE(reg, val) {i_i2c.write_reg(DAC3101_I2C_DEVICE_ADDR, reg, val);} - - -// Nominal setting is ref div = 25, fb_div = 1024, op_div = 2 -// PCF Freq 0.96MHz - -enum clock_nudge{ - PLL_SLOWER = -1, - PLL_NOMINAL = 0, - PLL_FASTER = 1 -}; - -//These steps provide just under +-0.1% frequency jumps -#define PLL_LOW 0xC003FE18 // This is 3.069MHz -#define PLL_NOM 0xC003FF18 // This is 3.072MHz -#define PLL_HIGH 0xC0040018 // This is 3.075MHz - -on tile[0]: out port p_leds = XS1_PORT_4F; - -//Note use of no_ack write to prevent backpressure. There is enough buffering to -//store both writes so we can move on without blocking -void pll_nudge(int nudge) { - if (nudge > 0){ - write_sswitch_reg_no_ack(get_tile_id(tile[0]), XS1_SSWITCH_PLL_CTL_NUM, PLL_HIGH); - p_leds <: 0x02; //LED B - } - else if (nudge < 0){ - write_sswitch_reg_no_ack(get_tile_id(tile[0]), XS1_SSWITCH_PLL_CTL_NUM, PLL_LOW); - p_leds <: 0x01; //LED A - - } - else { - p_leds <: 0x0; - } - write_sswitch_reg_no_ack(get_tile_id(tile[0]), XS1_SSWITCH_PLL_CTL_NUM, PLL_NOM); -} - -void setup_audio_gpio(out port p_gpio){ - // Reset DAC and disable MUTE - p_gpio <: 0x0; - delay_milliseconds(1); - p_gpio <: 0x1; - delay_milliseconds(1); -} - -void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c) -{ - - // Wait for 2ms because we apply reset for 1ms from other tile - delay_milliseconds(2); - - // Set register page to 0 - DAC3101_REGWRITE(DAC3101_PAGE_CTRL, 0x00); - // Initiate SW reset (PLL is powered off as part of reset) - DAC3101_REGWRITE(DAC3101_SW_RST, 0x01); - - // so I've got 24MHz in to PLL, I want 24.576MHz or 22.5792MHz out. - - // I will always be using fractional-N (D != 0) so we must set R = 1 - // PLL_CLKIN/P must be between 10 and 20MHz so we must set P = 2 - - // PLL_CLK = CLKIN * ((RxJ.D)/P) - // We know R = 1, P = 2. - // PLL_CLK = CLKIN * (J.D / 2) - - // For 24.576MHz: - // J = 8 - // D = 1920 - // So PLL_CLK = 24 * (8.192/2) = 24 x 4.096 = 98.304MHz - // Then: - // NDAC = 4 - // MDAC = 4 - // DOSR = 128 - // So: - // DAC_CLK = PLL_CLK / 4 = 24.576MHz. - // DAC_MOD_CLK = DAC_CLK / 4 = 6.144MHz. - // DAC_FS = DAC_MOD_CLK / 128 = 48kHz. - - // For 22.5792MHz: - // J = 7 - // D = 5264 - // So PLL_CLK = 24 * (7.5264/2) = 24 x 3.7632 = 90.3168MHz - // Then: - // NDAC = 4 - // MDAC = 4 - // DOSR = 128 - // So: - // DAC_CLK = PLL_CLK / 4 = 22.5792MHz. - // DAC_MOD_CLK = DAC_CLK / 4 = 5.6448MHz. - // DAC_FS = DAC_MOD_CLK / 128 = 44.1kHz. - -#if XUA_ADAPTIVE - //Set nominal clock speed on PLL - write_sswitch_reg(get_tile_id(tile[0]), XS1_SSWITCH_PLL_CTL_NUM, PLL_NOM); - - // We are assuming 48kHz family only and we generate MCLK in the DAC from BLCK supplied by XCORE - // Set PLL J Value to 8 - DAC3101_REGWRITE(DAC3101_PLL_J, 0x08); - // Set PLL D to 0 ... - // Set PLL D MSB Value to 0x00 - DAC3101_REGWRITE(DAC3101_PLL_D_MSB, 0x00); - // Set PLL D LSB Value to 0x00 - DAC3101_REGWRITE(DAC3101_PLL_D_LSB, 0x00); - - delay_milliseconds(1); - - // Set PLL_CLKIN = BCLK (device pin), CODEC_CLKIN = PLL_CLK (generated on-chip) - DAC3101_REGWRITE(DAC3101_CLK_GEN_MUX, 0x07); - - // Set PLL P=1 and R=4 values and power up. - DAC3101_REGWRITE(DAC3101_PLL_P_R, 0x94); - // Set NDAC clock divider to 4 and power up. - DAC3101_REGWRITE(DAC3101_NDAC_VAL, 0x84); - // Set MDAC clock divider to 4 and power up. - DAC3101_REGWRITE(DAC3101_MDAC_VAL, 0x84); - // Set OSR clock divider to 128. - DAC3101_REGWRITE(DAC3101_DOSR_VAL_LSB, 0x80); - -#else - /* Sample frequency dependent register settings */ - if ((samFreq % 11025) == 0) - { - // MCLK = 22.5792MHz (44.1,88.2,176.4kHz) - // Set PLL J Value to 7 - DAC3101_REGWRITE(DAC3101_PLL_J, 0x07); - // Set PLL D to 5264 ... (0x1490) - // Set PLL D MSB Value to 0x14 - DAC3101_REGWRITE(DAC3101_PLL_D_MSB, 0x14); - // Set PLL D LSB Value to 0x90 - DAC3101_REGWRITE(DAC3101_PLL_D_LSB, 0x90); - - } - else if ((samFreq % 8000) == 0) - { - // MCLK = 24.576MHz (48,96,192kHz) - // Set PLL J Value to 8 - DAC3101_REGWRITE(DAC3101_PLL_J, 0x08); - // Set PLL D to 1920 ... (0x780) - // Set PLL D MSB Value to 0x07 - DAC3101_REGWRITE(DAC3101_PLL_D_MSB, 0x07); - // Set PLL D LSB Value to 0x80 - DAC3101_REGWRITE(DAC3101_PLL_D_LSB, 0x80); - } - else - { - //debug_printf("Unrecognised sample freq of %d in ConfigCodec\n", samFreq); - } - - delay_milliseconds(1); - - // Set PLL_CLKIN = MCLK (device pin), CODEC_CLKIN = PLL_CLK (generated on-chip) - DAC3101_REGWRITE(DAC3101_CLK_GEN_MUX, 0x03); - - // Set PLL P and R values and power up. - DAC3101_REGWRITE(DAC3101_PLL_P_R, 0xA1); - // Set NDAC clock divider to 4 and power up. - DAC3101_REGWRITE(DAC3101_NDAC_VAL, 0x84); - // Set MDAC clock divider to 4 and power up. - DAC3101_REGWRITE(DAC3101_MDAC_VAL, 0x84); - // Set OSR clock divider to 128. - DAC3101_REGWRITE(DAC3101_DOSR_VAL_LSB, 0x80); - -#endif - - // Set CLKOUT Mux to DAC_CLK - DAC3101_REGWRITE(DAC3101_CLKOUT_MUX, 0x04); - // Set CLKOUT M divider to 1 and power up. - DAC3101_REGWRITE(DAC3101_CLKOUT_M_VAL, 0x81); - // Set GPIO1 output to come from CLKOUT output. - DAC3101_REGWRITE(DAC3101_GPIO1_IO, 0x10); - - // Set CODEC interface mode: I2S, 24 bit, slave mode (BCLK, WCLK both inputs). - DAC3101_REGWRITE(DAC3101_CODEC_IF, 0x20); - // Set register page to 1 - DAC3101_REGWRITE(DAC3101_PAGE_CTRL, 0x01); - // Program common-mode voltage to mid scale 1.65V. - DAC3101_REGWRITE(DAC3101_HP_DRVR, 0x14); - // Program headphone-specific depop settings. - // De-pop, Power on = 800 ms, Step time = 4 ms - DAC3101_REGWRITE(DAC3101_HP_DEPOP, 0x4E); - // Program routing of DAC output to the output amplifier (headphone/lineout or speaker) - // LDAC routed to left channel mixer amp, RDAC routed to right channel mixer amp - DAC3101_REGWRITE(DAC3101_DAC_OP_MIX, 0x44); - // Unmute and set gain of output driver - // Unmute HPL, set gain = 0 db - DAC3101_REGWRITE(DAC3101_HPL_DRVR, 0x06); - // Unmute HPR, set gain = 0 dB - DAC3101_REGWRITE(DAC3101_HPR_DRVR, 0x06); - // Unmute Left Class-D, set gain = 12 dB - DAC3101_REGWRITE(DAC3101_SPKL_DRVR, 0x0C); - // Unmute Right Class-D, set gain = 12 dB - DAC3101_REGWRITE(DAC3101_SPKR_DRVR, 0x0C); - // Power up output drivers - // HPL and HPR powered up - DAC3101_REGWRITE(DAC3101_HP_DRVR, 0xD4); - // Power-up L and R Class-D drivers - DAC3101_REGWRITE(DAC3101_SPK_AMP, 0xC6); - // Enable HPL output analog volume, set = -9 dB - DAC3101_REGWRITE(DAC3101_HPL_VOL_A, 0x92); - // Enable HPR output analog volume, set = -9 dB - DAC3101_REGWRITE(DAC3101_HPR_VOL_A, 0x92); - // Enable Left Class-D output analog volume, set = -9 dB - DAC3101_REGWRITE(DAC3101_SPKL_VOL_A, 0x92); - // Enable Right Class-D output analog volume, set = -9 dB - DAC3101_REGWRITE(DAC3101_SPKR_VOL_A, 0x92); - - delay_milliseconds(100); - - // Power up DAC - // Set register page to 0 - DAC3101_REGWRITE(DAC3101_PAGE_CTRL, 0x00); - // Power up DAC channels and set digital gain - // Powerup DAC left and right channels (soft step enabled) - DAC3101_REGWRITE(DAC3101_DAC_DAT_PATH, 0xD4); - // DAC Left gain = 0dB - DAC3101_REGWRITE(DAC3101_DACL_VOL_D, 0x00); - // DAC Right gain = 0dB - DAC3101_REGWRITE(DAC3101_DACR_VOL_D, 0x00); - // Unmute digital volume control - // Unmute DAC left and right channels - DAC3101_REGWRITE(DAC3101_DAC_VOL, 0x00); - - i_i2c.shutdown(); -} - - -//These are here just to silence compiler warnings about unimplemented xua callbacks (not needed in xua lite) -void AudioHwInit(){} -void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC){} diff --git a/examples/xua_lite_example/src/audio_hub.h b/examples/xua_lite_example/src/audio_hub.h deleted file mode 100644 index b7f1b7f9..00000000 --- a/examples/xua_lite_example/src/audio_hub.h +++ /dev/null @@ -1,4 +0,0 @@ -#include "i2s.h" - -[[distributable]] -void AudioHub(server i2s_frame_callback_if i2s, streaming chanend c_audio, streaming chanend (&?c_ds_output)[1]); \ No newline at end of file diff --git a/examples/xua_lite_example/src/audio_hub.xc b/examples/xua_lite_example/src/audio_hub.xc deleted file mode 100644 index bec765a1..00000000 --- a/examples/xua_lite_example/src/audio_hub.xc +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include "i2s.h" -#include "i2c.h" -#include "xua.h" -#define DEBUG_UNIT XUA_AUDIO_HUB -#define DEBUG_PRINT_ENABLE_XUA_AUDIO_HUB 1 -#include "debug_print.h" -#include "mic_array.h" -#include "audio_config.h" -#include "pdm_mic.h" -#include "xua_buffer_lite.h" - -//Globally declared for 64b alignment -int mic_decimator_fir_data_array[8][THIRD_STAGE_COEFS_PER_STAGE * PDM_MAX_DECIMATION] = {{0}}; -mic_array_frame_time_domain mic_audio_frame[2]; - -[[distributable]] -void AudioHub(server i2s_frame_callback_if i2s, - streaming chanend c_audio, - streaming chanend (&?c_ds_output)[1]) -{ - int32_t samples_out[NUM_USB_CHAN_OUT] = {0}; - int32_t samples_in[NUM_USB_CHAN_IN] = {0}; - - int32_t clock_nudge = 0; - - //PDM mic and decimator - unsigned buffer; - int raw_mics[XUA_NUM_PDM_MICS] = {0}; - const unsigned decimatorCount = 1; // Supports up to 4 mics - mic_array_decimator_conf_common_t dcc; - mic_array_decimator_config_t dc[1]; - mic_array_frame_time_domain * unsafe current; - - mic_array_decimator_set_samprate(DEFAULT_FREQ, mic_decimator_fir_data_array[0], &dcc, dc); - mic_array_decimator_configure(c_ds_output, decimatorCount, dc); - mic_array_init_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio_frame, dc); - - // Used for debug - //int saw = 0; - - while (1) { - select { - case i2s.init(i2s_config_t &?i2s_config, tdm_config_t &?tdm_config): - i2s_config.mode = I2S_MODE_I2S; - i2s_config.mclk_bclk_ratio = (MCLK_48/DEFAULT_FREQ)/64; - debug_printf("I2S init\n"); - delay_milliseconds(500); //Work around to ensure I2S does not start until enumeration complete so timing does not break for exchange - //This should be ideally done by set config by the host (via xua_buffer) to know we are enumerated - break; - - case i2s.receive(size_t n_chans, int32_t in_samps[n_chans]): - for (int i = 0; i < n_chans; i++) samples_in[i] = in_samps[i]; - break; - - case i2s.send(size_t n_chans, int32_t out_samps[n_chans]): - for (int i = 0; i < n_chans; i++) out_samps[i] = samples_out[i]; - break; - - //Exchange samples with mics & host - case i2s.restart_check() -> i2s_restart_t restart: - restart = I2S_NO_RESTART; // Keep on looping - timer tmr; int t0, t1; tmr :> t0; - - XUA_transfer_samples(c_audio, (unsigned *) samples_out, (unsigned *) raw_mics, (clock_nudge, int)); - - //Grab mics. Takes about 200 ticks currently - current = mic_array_get_next_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio_frame, dc); - //50 ticks - unsafe { - for (int i = 0; i < XUA_NUM_PDM_MICS; i++) raw_mics[i] = current->data[i][0]; - } - - //memset(raw_mics, saw, sizeof(int) * XUA_NUM_PDM_MICS); - //saw += 500; - - //Taking about 160 ticks when adjusting, 100 when not - tmr :> t0; - pll_nudge(clock_nudge); - tmr :> t1; - if (t1-t0 > 500) debug_printf("*%d\n", t1 - t0); - //delay_microseconds(10); //Test backpressure tolerance - break; - } - } -} diff --git a/examples/xua_lite_example/src/pdm_mic.h b/examples/xua_lite_example/src/pdm_mic.h deleted file mode 100644 index 04b13c3f..00000000 --- a/examples/xua_lite_example/src/pdm_mic.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _PDM_MIC_H_ -#define _PDM_MIC_H_ - -#include "mic_array.h" - -void mic_array_decimator_set_samprate(const unsigned samplerate, int mic_decimator_fir_data_array[], mic_array_decimator_conf_common_t *dcc, mic_array_decimator_config_t dc[]); -void pdm_mic(streaming chanend c_ds_output, in buffered port:32 p_pdm_mics); -void mic_array_setup_ddr(clock pdmclk, clock pdmclk6, in port p_mclk, - out port p_pdm_clk, buffered in port:32 p_pdm_data, - int divide); - -#endif diff --git a/examples/xua_lite_example/src/pdm_mic.xc b/examples/xua_lite_example/src/pdm_mic.xc deleted file mode 100644 index 59d506be..00000000 --- a/examples/xua_lite_example/src/pdm_mic.xc +++ /dev/null @@ -1,112 +0,0 @@ -#include "xua.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mic_array.h" - - -void mic_array_decimator_set_samprate(const unsigned samplerate, int mic_decimator_fir_data_array[], mic_array_decimator_conf_common_t *dcc, mic_array_decimator_config_t dc[]) -{ - unsigned decimationfactor = 96000/samplerate; - int fir_gain_compen[7]; - int * unsafe fir_coefs[7]; - unsafe - { - fir_gain_compen[0] = 0; - fir_gain_compen[1] = FIR_COMPENSATOR_DIV_2; //48kHz - fir_gain_compen[2] = FIR_COMPENSATOR_DIV_4; - fir_gain_compen[3] = FIR_COMPENSATOR_DIV_6; //16kHz - fir_gain_compen[4] = FIR_COMPENSATOR_DIV_8; - fir_gain_compen[5] = 0; - fir_gain_compen[6] = FIR_COMPENSATOR_DIV_12; - - fir_coefs[0] = 0; - fir_coefs[1] = (int * unsafe)g_third_stage_div_2_fir; - fir_coefs[2] = (int * unsafe)g_third_stage_div_4_fir; - fir_coefs[3] = (int * unsafe)g_third_stage_div_6_fir; - fir_coefs[4] = (int * unsafe)g_third_stage_div_8_fir; - fir_coefs[5] = 0; - fir_coefs[6] = (int * unsafe)g_third_stage_div_12_fir; - - //dcc = {MIC_ARRAY_MAX_FRAME_SIZE_LOG2, 1, 0, 0, decimationfactor, fir_coefs[decimationfactor/2], 0, 0, DECIMATOR_NO_FRAME_OVERLAP, 2}; - dcc->len = MIC_ARRAY_MAX_FRAME_SIZE_LOG2; - dcc->apply_dc_offset_removal = 1; - dcc->index_bit_reversal = 0; - dcc->windowing_function = null; - dcc->output_decimation_factor = decimationfactor; - dcc->coefs = fir_coefs[decimationfactor/2]; - dcc->apply_mic_gain_compensation = 0; - dcc->fir_gain_compensation = fir_gain_compen[decimationfactor/2]; - dcc->buffering_type = DECIMATOR_NO_FRAME_OVERLAP; - dcc->number_of_frame_buffers = 2; - - //dc[0] = {&dcc, mic_decimator_fir_data[0], {0, 0, 0, 0}, 4}; - dc[0].dcc = dcc; - dc[0].data = mic_decimator_fir_data_array; - dc[0].mic_gain_compensation[0]=0; - dc[0].mic_gain_compensation[1]=0; - dc[0].mic_gain_compensation[2]=0; - dc[0].mic_gain_compensation[3]=0; - dc[0].channel_count = 4; - } -} - -#if MAX_FREQ > 48000 -#error MAX_FREQ > 48000 NOT CURRENTLY SUPPORTED -#endif - -void pdm_mic(streaming chanend c_ds_output, in buffered port:32 p_pdm_mics) -{ - streaming chan c_4x_pdm_mic_0; - assert((MCLK_48 / 3072000) == (MCLK_441 / 2822400)); //Make sure mic clock is achievable from MCLK - par - { - mic_array_pdm_rx(p_pdm_mics, c_4x_pdm_mic_0, null); - mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_0, c_ds_output, MIC_ARRAY_NO_INTERNAL_CHANS); - - } -} - -void mic_array_setup_ddr(clock pdmclk, - clock pdmclk6, - in port p_mclk, /*used only in I2S slave case*/ - out port p_pdm_clk, - buffered in port:32 p_pdm_data, - int divide) { - - -#if !XUA_ADAPTIVE //i2s slave - //p_mclk coming from the Pi is 24.576 MHz - configure_clock_src_divide(pdmclk, p_mclk, 4); //3.072 = 24.576 / 8 - configure_clock_src_divide(pdmclk6, p_mclk, 2); //6.144 = 24.576 / 4 - -#else - configure_clock_xcore(pdmclk, 80); // 3.072 - configure_clock_xcore(pdmclk6, 40); // 6.144 -#endif - - configure_port_clock_output(p_pdm_clk, pdmclk); - configure_in_port(p_pdm_data, pdmclk6); - - /* start the faster capture clock */ - start_clock(pdmclk6); - /* wait for a rising edge on the capture clock */ - partin(p_pdm_data, 4); - /* start the slower output clock */ - start_clock(pdmclk); - - /* - * this results in the rising edge of the capture clock - * leading the rising edge of the output clock by one period - * of p_mclk, which is about 40.7 ns for the typical frequency - * of 24.576 megahertz. - * This should fall within the data valid window. - */ - -} diff --git a/examples/xua_lite_example/test/Makefile b/examples/xua_lite_example/test/Makefile deleted file mode 100644 index b3bbbe69..00000000 --- a/examples/xua_lite_example/test/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2018, XMOS Ltd, All rights reserved - -#Note no xcommon included - we are going bareback here because xcommon not good -#at dealing excluding/including source directories out of normal structure. -#We want to have a test app here using some source files from sw_vocalfusion (delay estimator) - - -BUILD_FLAGS = -O3 -g -XCC_FLAGS = $(BUILD_FLAGS) - -INCLUDE_DIRS = \ - -I ../src/ \ - -I . \ - -COMMON = \ - -O2 -g -report \ - -target=XCORE-200-EXPLORER \ - -SOURCES = \ - ./test_fifo.xc \ - -BINARY=bin/test_fifo.xe \ - - -all: - mkdir -p bin; \ - mv test_fifoxc test_fifo.xc; \ - xcc $(SOURCES) $(COMMON) $(INCLUDE_DIRS) -D AUDIO_DELAY_SAMPLES=$$DELAY -o $(BINARY); \ - mv test_fifo.xc test_fifoxc; \ - -sim: - xsim $(BINARY) - -clean: - rm -rf bin/* diff --git a/examples/xua_lite_example/test/test_fifoxc b/examples/xua_lite_example/test/test_fifoxc deleted file mode 100644 index befb966b..00000000 --- a/examples/xua_lite_example/test/test_fifoxc +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include "fifo_impl.h" - -typedef enum test_t{ - FAIL=0, - PASS=1 -}test_t; - -#define FIFO_SIZE 4 - -unsafe test_t test_is_empty(mem_fifo_short_t * unsafe fifo){ - unsigned fill = fifo_get_fill_short(fifo); - short data[1]; - fifo_ret_t ret = fifo_block_pop_short(fifo, data, 1); - if (fill == 0 && ret == FIFO_EMPTY) return PASS; - return FAIL; -} - -unsafe test_t test_push_one(mem_fifo_short_t * unsafe fifo){ - unsigned fill_0 = fifo_get_fill_short(fifo); - short data[] = {123}; - fifo_ret_t ret = fifo_block_push_short(fifo, data, 1); - unsigned fill_1 = fifo_get_fill_short(fifo); - - if (ret != FIFO_SUCCESS || fill_0 + 1 != fill_1) return FAIL; - return PASS; -} - -unsafe test_t test_partial_fill(mem_fifo_short_t * unsafe fifo){ - unsigned fill_0 = fifo_get_fill_short(fifo); - short data[] = {80, 90, 100}; - fifo_ret_t ret = fifo_block_push_short(fifo, data, 3); - unsigned fill_1 = fifo_get_fill_short(fifo); - - if (ret != FIFO_SUCCESS || fill_0 != 0 || fill_1 != 3) return FAIL; - return PASS; -} - -unsafe test_t test_fill_level(mem_fifo_short_t * unsafe fifo){ - unsigned fill = fifo_get_fill_short(fifo); - if (fill != 3) return FAIL; - return PASS; -} - -unsafe test_t test_pop_one(mem_fifo_short_t * unsafe fifo, short expect){ - unsigned fill_0 = fifo_get_fill_short(fifo); - short data[1] = {0xffff}; - fifo_ret_t ret = fifo_block_pop_short(fifo, data, 1); - unsigned fill_1 = fifo_get_fill_short(fifo); - if (ret != FIFO_SUCCESS || fill_0 != fill_1 + 1 || data[0] != expect) { - printf("grr %d\n", data[0]); - return FAIL; - } - return PASS; -} - -unsafe test_t test_pop_three_fail(mem_fifo_short_t * unsafe fifo){ - unsigned fill_0 = fifo_get_fill_short(fifo); - short data[3] = {0xffff, 0xffff, 0xffff}; - fifo_ret_t ret = fifo_block_pop_short(fifo, data, 3); - unsigned fill_1 = fifo_get_fill_short(fifo); - if (ret == FIFO_SUCCESS || fill_0 != 2 || fill_1 != 2) return FAIL; - return PASS; -} - -unsafe test_t test_partial_fill_fast(mem_fifo_short_t * unsafe fifo){ - unsigned fill_0 = fifo_get_fill_short(fifo); - short data[] = {20, 30, 40}; - fifo_ret_t ret = fifo_block_push_short_fast(fifo, data, 3); - unsigned fill_1 = fifo_get_fill_short(fifo); - - if (ret != FIFO_SUCCESS || fill_0 != 0 || fill_1 != 3) return FAIL; - return PASS; -} - -unsafe test_t test_pop_block_fast(mem_fifo_short_t * unsafe fifo, short expect[], unsigned n){ - unsigned fill_0 = fifo_get_fill_short(fifo); - short data[10] = {0xffff}; - fifo_ret_t ret = fifo_block_pop_short_fast(fifo, data, n); - unsigned fill_1 = fifo_get_fill_short(fifo); - unsigned data_ok = memcmp(data, expect, n * sizeof(short)) == 0; - if (ret != FIFO_SUCCESS || fill_0 != fill_1 + n || !data_ok) return FAIL; - return PASS; -} - -unsafe void print_fifo(mem_fifo_short_t * unsafe fifo){ - for (int i = fifo->size - 1; i >= 0; i--){ - printf("FIFO[%d]: %hd %s %s\n", i, fifo->data_base_ptr[i], fifo->read_idx == i ? "RD" : "", fifo->write_idx == i ? "WR" : ""); - } -} - - -int main(void){ - unsafe{ - short test_fifo_storage[FIFO_SIZE]; - mem_fifo_short_t test_fifo = {sizeof(test_fifo_storage)/sizeof(test_fifo_storage[0]), test_fifo_storage, 0, 0}; - volatile mem_fifo_short_t * unsafe test_fifo_ptr = &test_fifo; - - // print_fifo(test_fifo_ptr); - printf("test_is_empty: %d\n", test_is_empty(test_fifo_ptr)); - printf("test_partial_fill: %d\n", test_partial_fill(test_fifo_ptr)); - // print_fifo(test_fifo_ptr); - - printf("test_fill_level: %d\n", test_fill_level(test_fifo_ptr)); - printf("test_pop_one: %d\n", test_pop_one(test_fifo_ptr, 80)); - printf("test_pop_three_fail: %d\n", test_pop_three_fail(test_fifo_ptr)); - printf("test_pop_one: %d\n", test_pop_one(test_fifo_ptr, 90)); - printf("test_pop_one: %d\n", test_pop_one(test_fifo_ptr, 100)); - printf("test_is_empty: %d\n", test_is_empty(test_fifo_ptr)); - - printf("test_partial_fill_fast: %d\n", test_partial_fill_fast(test_fifo_ptr)); - - printf("test_pop_one: %d\n", test_pop_one(test_fifo_ptr, 20)); - // print_fifo(test_fifo_ptr); - - short td[] = {30, 40}; - - printf("test_pop_block_fast: %d\n", test_pop_block_fast(test_fifo_ptr, td, 2)); //no wrap - - printf("test_is_empty: %d\n", test_is_empty(test_fifo_ptr)); - printf("test_push_one: %d\n", test_push_one(test_fifo_ptr)); - printf("test_push_one: %d\n", test_push_one(test_fifo_ptr)); - printf("test_pop_three_fail: %d\n", test_pop_three_fail(test_fifo_ptr)); - printf("test_pop_one: %d\n", test_pop_one(test_fifo_ptr, 123)); - printf("test_pop_one: %d\n", test_pop_one(test_fifo_ptr, 123)); - - printf("test_partial_fill_fast: %d\n", test_partial_fill_fast(test_fifo_ptr)); //no wrap - short te[] = {20, 30, 40}; - printf("test_pop_block_fast: %d\n", test_pop_block_fast(test_fifo_ptr, te, 3));// no wrap - printf("test_partial_fill_fast: %d\n", test_partial_fill_fast(test_fifo_ptr)); //wrap - printf("test_pop_block_fast: %d\n", test_pop_block_fast(test_fifo_ptr, te, 3));// wrap - // print_fifo(test_fifo_ptr); - - - - - return 0; - } -} \ No newline at end of file diff --git a/examples/xua_lite_example/todo.txt b/examples/xua_lite_example/todo.txt deleted file mode 100644 index 4d0ab456..00000000 --- a/examples/xua_lite_example/todo.txt +++ /dev/null @@ -1,22 +0,0 @@ -- Bring ep0 serivice into xua_buffer select (make control mem) (DONE) -- Tidy feedback endpoint (DONE) -- Input path + FIFO (DONE) -- Function prototypes into includes (DONE) -- Single input/ouput format (DONE) -- Get UAC1 / FS working (DONE) -- Optimised EP buffer (either triple block or block FIFO) (DONE) -- Fix output gain issue (IN PROGRESS) -- Add timer to xua_buffer to prepare for exchange with audio (remove backpressure to audio) (WONT DO - use port buffer and reduce case overhead) -- Adaptive endpoint EP and descriptors (DONE) -- Adpative clock control (IN PROGRESS) -- Proper control loop w/filtering (IN PROGRESS) -- Switchable MICS using define (WONT DO - separate app) -- DFU -- Combinable EP0 (DONE) -- Interrupt EP0 option -- Control processing -- Fix cast warning (DONE) -- Work out why no clock drift on Android / OSX (drift seen on Linux and Win) (DONE) -- Tidy/cut down EP0 handling -- Broader host testing (Android, W10, MAC) (IN PROGRESS) -- Peer review diff --git a/examples/xua_lite_example/wscript b/examples/xua_lite_example/wscript deleted file mode 100644 index 5d6de68c..00000000 --- a/examples/xua_lite_example/wscript +++ /dev/null @@ -1,26 +0,0 @@ -def options(ctx): - ctx.add_option('--target', action='store', default='xua_lite_example.xe') - ctx.add_option('--debug', action='store_true') - - -def configure(conf): - conf.load('xwaf.compiler_xcc') - conf.env.PROJECT_ROOT = '../../..' - -def build(bld): - target_path = 'bin/' + bld.options.target - bld.env.TARGET_ARCH ='config/RPI_HAT_60QFN.xn' - bld.env.XSCOPE = bld.path.find_resource('config.xscope') - depends_on = ['lib_xua','lib_i2s','lib_xud','lib_mic_array', 'lib_i2c'] - #bld.env.XCC_FLAGS = ['-O2', '-g', '-Wall', '-fcmdline-buffer-bytes=512', '-report', '-DDISABLE_STAGE_C'] - bld.env.XCC_FLAGS = ['-fcomment-asm','-Xmapper','--map','-Xmapper','MAPFILE', - '-Os','-report','-g','-Wno-unused-function','-Wno-timing', - '-DXUD_SERIES_SUPPORT=XUD_X200_SERIES','-DUSB_TILE=tile[1]', - '-DMIC_ARRAY_CH0=PIN0','-DMIC_ARRAY_CH1=PIN4', '-DDEBUG_PRINT_ENABLE=1'] - if bld.options.debug: - bld.env.XCC_FLAGS.append('-DDEBUG') - - source = bld.path.ant_glob(['src/**/*.xc', 'src/**/*.c', - 'xua_lite/**/*.xc', 'xua_lite/**/*.c']) - includes = ['config'] - bld.program(source=source, includes=includes, depends_on=depends_on,target=target_path) diff --git a/examples/xua_lite_example/xua_lite/rate_control/fifo_impl.h b/examples/xua_lite_example/xua_lite/rate_control/fifo_impl.h deleted file mode 100644 index 080f3c95..00000000 --- a/examples/xua_lite_example/xua_lite/rate_control/fifo_impl.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef __FIFO__ -#define __FIFO__ -#include //memcpy -#include "fifo_types.h" - -//Asynch FIFO implementaion -//Note these are in the include file to allow the compiler to inline for performance - -/////////////////////////////////////// -//Shared memory FIFO (sample by sample) -//Can be any size -/////////////////////////////////////// - - -static inline unsigned fifo_get_fill(volatile mem_fifo_t * unsafe fifo) { - unsafe{ - unsigned fifo_fill = 0; - if (fifo->write_idx >= fifo->read_idx){ - fifo_fill = fifo->write_idx - fifo->read_idx; - } - else{ - fifo_fill = (fifo->size + fifo->write_idx) - fifo->read_idx; - } - return fifo_fill; - } -} - -static inline unsigned fifo_get_fill_short(volatile mem_fifo_short_t * unsafe fifo) { - unsafe{ - unsigned fifo_fill = 0; - if (fifo->write_idx >= fifo->read_idx){ - fifo_fill = fifo->write_idx - fifo->read_idx; - } - else{ - fifo_fill = (fifo->size + fifo->write_idx) - fifo->read_idx; - } - return fifo_fill; - } -} - -static inline void fifo_init_short(volatile mem_fifo_short_t * unsafe fifo) { - unsafe{ - fifo->write_idx = 0; - fifo->read_idx = (fifo->size * 2) / 4; - memset(fifo->data_base_ptr , 0, fifo->size * sizeof(short)); - } -} - -#pragma unsafe arrays -static inline fifo_ret_t fifo_block_push(volatile mem_fifo_t * unsafe fifo, int data[], unsigned n) { - unsafe{ - //check there is a block of space large enough - unsigned space_remaining = fifo->size - fifo_get_fill(fifo) - 1; - if (n > space_remaining) { - return FIFO_FULL; - } - for (int i = 0; i < n; i++){ - unsigned next_idx = fifo->write_idx + 1; - if (next_idx == fifo->size) next_idx = 0; //Check for wrap - fifo->data_base_ptr[fifo->write_idx] = data[i]; - fifo->write_idx = next_idx; - } - return FIFO_SUCCESS; - } -} - -#pragma unsafe arrays -static inline fifo_ret_t fifo_block_push_short(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) { - unsafe{ - //check there is a block of space large enough - unsigned space_remaining = fifo->size - fifo_get_fill_short(fifo) - 1; - if (n > space_remaining) { - return FIFO_FULL; - } - for (int i = 0; i < n; i++){ - unsigned next_idx = fifo->write_idx + 1; - if (next_idx == fifo->size) next_idx = 0; //Check for wrap - fifo->data_base_ptr[fifo->write_idx] = data[i]; - fifo->write_idx = next_idx; - } - return FIFO_SUCCESS; - } -} - -#pragma unsafe arrays -static inline fifo_ret_t fifo_block_push_short_fast(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) { - unsafe{ - //check there is a block of space large enough - unsigned space_remaining = fifo->size - fifo_get_fill_short(fifo) - 1; - if (n > space_remaining) { - return FIFO_FULL; - } - //We will write either one or two blocks depending on wrap - unsigned first_block_size = 0; - unsigned second_block_size = 0; - - //See if we need to wrap during block writes - unsigned space_left_at_top = fifo->size - fifo->write_idx; - //printf("space_left_at_top %d\n", space_left_at_top); - //Yes, we do need to wrap - if (n > space_left_at_top){ - first_block_size = space_left_at_top; - second_block_size = n - space_left_at_top; - memcpy(&fifo->data_base_ptr[fifo->write_idx], &data[0], first_block_size * sizeof(short)); - memcpy(&fifo->data_base_ptr[0], &data[first_block_size], second_block_size * sizeof(short)); - fifo->write_idx = second_block_size; - } - //No wrap, do all in one go - else{ - first_block_size = n; - second_block_size = 0; - memcpy(&fifo->data_base_ptr[fifo->write_idx], &data[0], first_block_size * sizeof(short)); - fifo->write_idx += first_block_size; - } - - return FIFO_SUCCESS; - } -} - -#pragma unsafe arrays -static inline fifo_ret_t fifo_block_pop(volatile mem_fifo_t * unsafe fifo, int data[], unsigned n) { - unsafe{ - //Check we have a block big enough to send - if (n > fifo_get_fill(fifo)){ - return FIFO_EMPTY; - } - for (int i = 0; i < n; i++){ - data[i] = fifo->data_base_ptr[fifo->read_idx]; - fifo->read_idx++; - if (fifo->read_idx == fifo->size) fifo->read_idx = 0; //Check for wrap - } - return FIFO_SUCCESS; - } -} - -#pragma unsafe arrays -static inline fifo_ret_t fifo_block_pop_short(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) { - unsafe{ - //Check we have a block big enough to send - if (n > fifo_get_fill_short(fifo)){ - return FIFO_EMPTY; - } - for (int i = 0; i < n; i++){ - data[i] = fifo->data_base_ptr[fifo->read_idx]; - fifo->read_idx++; - if (fifo->read_idx == fifo->size) fifo->read_idx = 0; //Check for wrap - } - return FIFO_SUCCESS; - } -} - -#pragma unsafe arrays -static inline fifo_ret_t fifo_block_pop_short_fast(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) { - unsafe{ - //Check we have a block big enough to send - if (n > fifo_get_fill_short(fifo)){ - return FIFO_EMPTY; - } - //We will read either one or two blocks depending on wrap - unsigned first_block_size = 0; - unsigned second_block_size = 0; - - //See if we need to wrap during block read - unsigned num_read_at_top = fifo->size - fifo->read_idx; - // printf("num_read_at_top %d\n", num_read_at_top); - //Yes, we do need to wrap - if (n > num_read_at_top){ - first_block_size = num_read_at_top; - second_block_size = n - num_read_at_top; - memcpy(&data[0], &fifo->data_base_ptr[fifo->read_idx], first_block_size * sizeof(short)); - memcpy( &data[first_block_size], &fifo->data_base_ptr[0], second_block_size * sizeof(short)); - fifo->read_idx = second_block_size; - // printf("wrap\n"); - } - //No wrap, do all in one go - else{ - first_block_size = n; - second_block_size = 0; - memcpy(&data[0], &fifo->data_base_ptr[fifo->read_idx], first_block_size * sizeof(short)); - fifo->read_idx += first_block_size; - // printf("no wrap\n"); - - } - - return FIFO_SUCCESS; - } -} - -//Version of above that returns fill level relative to half full -static inline int fifo_get_fill_relative_half(volatile mem_fifo_t * unsafe fifo){ - unsafe{ - int fifo_fill = (int)fifo_get_fill(fifo); - fifo_fill -= (fifo->size / 2); - return fifo_fill; - } -} - -//Version of above that returns fill level relative to half full -static inline int fifo_get_fill_relative_half_short(volatile mem_fifo_short_t * unsafe fifo){ - unsafe{ - int fifo_fill = (int)fifo_get_fill_short(fifo); - fifo_fill -= (fifo->size / 2); - return fifo_fill; - } -} -#endif diff --git a/examples/xua_lite_example/xua_lite/rate_control/fifo_types.h b/examples/xua_lite_example/xua_lite/rate_control/fifo_types.h deleted file mode 100644 index af7994e7..00000000 --- a/examples/xua_lite_example/xua_lite/rate_control/fifo_types.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __ASRC_FIFO_TYPES__ -#define __ASRC_FIFO_TYPES__ -#include - -//Shared FIFO return types -typedef enum fifo_ret_t { - FIFO_SUCCESS = 0, - FIFO_FULL, - FIFO_EMPTY -} fifo_ret_t; - -///////////////////////////////////////////////////////////////////////// -//Shared memory FIFO (sample by sample or block) -//Can be any size -// -//Note that the actual storage for the FIFO is declared externally -//and a reference to the base address of the storage is passed in along -//with the size of the storage. This way, multiple instances may be -//different sizes. -// -///////////////////////////////////////////////////////////////////////// - -typedef struct mem_fifo_t { - const unsigned size; //Size in INTs - int * const unsafe data_base_ptr; //Base of the data array - declared externally so we can have differnt sized FIFOs - unsigned write_idx; - unsigned read_idx; -} mem_fifo_t; - -typedef struct mem_fifo_short_t { - const unsigned size; //Size in SHORTs - short * const unsafe data_base_ptr; //Base of the data array - declared externally so we can have differnt sized FIFOs - unsigned write_idx; - unsigned read_idx; -} mem_fifo_short_t; - -#endif diff --git a/examples/xua_lite_example/xua_lite/rate_control/rate_controller.h b/examples/xua_lite_example/xua_lite/rate_control/rate_controller.h deleted file mode 100644 index 8dee3f75..00000000 --- a/examples/xua_lite_example/xua_lite/rate_control/rate_controller.h +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - -typedef int32_t xua_lite_fixed_point_t; - -typedef struct pid_state_t{ - xua_lite_fixed_point_t fifo_level_filtered_old; - xua_lite_fixed_point_t fifo_level_accum; -} pid_state_t; - - -//USB Adaptive mode helper -xua_lite_fixed_point_t do_rate_control(int fill_level, pid_state_t *pid_state); - -//PDM modulator for clock control -void do_clock_nudge_pdm(xua_lite_fixed_point_t controller_out, int *clock_nudge); - - -//USB Asynch mode helper -void do_feedback_calculation(unsigned &sof_count, const unsigned mclk_hz, unsigned mclk_port_counter,unsigned &mclk_port_counter_old - ,long long &feedback_value, unsigned &mod_from_last_time, unsigned fb_clocks[1]); \ No newline at end of file diff --git a/examples/xua_lite_example/xua_lite/rate_control/rate_controller.xc b/examples/xua_lite_example/xua_lite/rate_control/rate_controller.xc deleted file mode 100644 index 58fddf48..00000000 --- a/examples/xua_lite_example/xua_lite/rate_control/rate_controller.xc +++ /dev/null @@ -1,201 +0,0 @@ -#include -#include "xua_buffer_lite.h" -#include "rate_controller.h" -#define DEBUG_UNIT XUA_RATE_CONTROL -#define DEBUG_PRINT_ENABLE_XUA_RATE_CONTROL 1 -#include "debug_print.h" - -#define XUA_LIGHT_FIXED_POINT_Q_BITS 10 //Including sign bit. 10b gets us to +511.999999 to -512.000000 -#define XUA_LIGHT_FIXED_POINT_TOTAL_BITS (sizeof(xua_lite_fixed_point_t) * 8) -#define XUA_LIGHT_FIXED_POINT_FRAC_BITS (XUA_LIGHT_FIXED_POINT_TOTAL_BITS - XUA_LIGHT_FIXED_POINT_Q_BITS) -#define XUA_LIGHT_FIXED_POINT_ONE (1 << XUA_LIGHT_FIXED_POINT_FRAC_BITS) -#define XUA_LIGHT_FIXED_POINT_MINUS_ONE (-XUA_LIGHT_FIXED_POINT_ONE) - -#define FIFO_LEVEL_EMA_COEFF 0.939 //Proportion of signal from y[-1]. - //0.939 gives ~10Hz 3db cutoff low pass filter for filter rate of 1kHz - //dsp.stackexchange.com/questions/40462/exponential-moving-average-cut-off-frequency/40465 -#define FIFO_LEVEL_A_COEFF ((int32_t)(INT_MAX * FIFO_LEVEL_EMA_COEFF)) //Scale to signed 1.31 format -#define FIFO_LEVEL_B_COEFF (INT_MAX - FIFO_LEVEL_A_COEFF) - -#define RANDOMISATION_PERCENT 20 //How much radnom noise to inject in percent of existing signal amplitude -#define RANDOMISATION_COEFF_A ((INT_MAX / 100) * RANDOMISATION_PERCENT) - -#define PID_CALC_OVERHEAD_BITS 2 //Allow large P,I or D constants, up to 2^(this number) - - -#define PID_CONTROL_P_TERM 10.0 -#define PID_CONTROL_I_TERM 150.0 -#define PID_CONTROL_D_TERM 1.0 - -#define PID_RATE_MULTIPLIER SOF_FREQ_HZ - -#define PID_CONTROL_P_TERM_COEFF ((xua_lite_fixed_point_t)((XUA_LIGHT_FIXED_POINT_ONE >> PID_CALC_OVERHEAD_BITS) * (float)PID_CONTROL_P_TERM)) //scale to fixed point -#define PID_CONTROL_I_TERM_COEFF ((xua_lite_fixed_point_t)((XUA_LIGHT_FIXED_POINT_ONE >> PID_CALC_OVERHEAD_BITS) * (float)PID_CONTROL_I_TERM / PID_RATE_MULTIPLIER)) //scale to fixed point -#define PID_CONTROL_D_TERM_COEFF ((xua_lite_fixed_point_t)((XUA_LIGHT_FIXED_POINT_ONE >> PID_CALC_OVERHEAD_BITS) * (float)PID_CONTROL_D_TERM * PID_RATE_MULTIPLIER)) //scale to fixed point - - -static inline xua_lite_fixed_point_t do_fifo_depth_lowpass_filter(xua_lite_fixed_point_t old, int fifo_depth){ - //we grow from 32b to 64b for intermediate - int64_t intermediate = ((int64_t)(fifo_depth << XUA_LIGHT_FIXED_POINT_FRAC_BITS) * (int64_t)FIFO_LEVEL_B_COEFF) + ((int64_t)old * (int64_t)FIFO_LEVEL_A_COEFF); - xua_lite_fixed_point_t new_fifo_depth = (xua_lite_fixed_point_t)( intermediate >> (64 - XUA_LIGHT_FIXED_POINT_TOTAL_BITS - 1)); //-1 because signed int - return new_fifo_depth; -} - -static inline int32_t get_random_number(void) -{ - static const unsigned random_poly = 0xEDB88320; - static unsigned random = 0x12345678; - crc32(random, -1, random_poly); - return (int32_t) random; -} - -static inline xua_lite_fixed_point_t add_noise(xua_lite_fixed_point_t input){ - //Note the input number cannot be bigger than 2 ^ (FIXED_POINT_Q_BITS - 1) * (1 + PERCENT) else we could oveflow - //Eg. if Q bits = 10 then biggest input value is 255.9999 - int32_t random = get_random_number(); - int32_t input_fraction = ((int64_t)input * (int64_t)RANDOMISATION_COEFF_A) >> (XUA_LIGHT_FIXED_POINT_TOTAL_BITS - 1); - int64_t output_64 = ((int64_t)input << (XUA_LIGHT_FIXED_POINT_TOTAL_BITS - 1)) + ((int64_t)input_fraction * (int64_t)random); - return (xua_lite_fixed_point_t)( output_64 >> (64 - XUA_LIGHT_FIXED_POINT_TOTAL_BITS - 1)); -} - -//Convert the control input into a pdm output (dither) with optional noise -void do_clock_nudge_pdm(xua_lite_fixed_point_t controller_out, int *clock_nudge){ - - //Randomise - add a proportion of rectangular probability distribution noise to spread the spectrum - controller_out = add_noise(controller_out); - - //Convert to pulse density modulation (sigma-delta) - static xua_lite_fixed_point_t nudge_accumulator = 0; - nudge_accumulator += controller_out; //Note no overflow check as if we reach XUA_LIGHT_FIXED_POINT_Q_BITS - //something is very wrong - //printf("co: %d ratio: %f \n", controller_out, (float)controller_out/XUA_LIGHT_FIXED_POINT_ONE); - if (nudge_accumulator >= XUA_LIGHT_FIXED_POINT_ONE){ - *clock_nudge = 1; - nudge_accumulator -= XUA_LIGHT_FIXED_POINT_ONE; - } - else if (nudge_accumulator <= XUA_LIGHT_FIXED_POINT_MINUS_ONE){ - nudge_accumulator -= XUA_LIGHT_FIXED_POINT_MINUS_ONE; - *clock_nudge = -1; - } - else{ - *clock_nudge = 0; - } -} - - -//Do PI control and modulation for adaptive USB audio -xua_lite_fixed_point_t do_rate_control(int fill_level, pid_state_t *pid_state){ - - //We always check the FIFO level after USB has produced a block, and total FIFO size is 2x max, so half full is at 3/4 - const int half_full = ((MAX_OUT_SAMPLES_PER_SOF_PERIOD * 2) * 3) / 4; - int fill_level_wrt_half = fill_level - half_full; //Will be +ve for more than half full and negative for less than half full - - //Low pass filter fill level and get error w.r.t. to set point which is depth = 0 (relative to half full) - xua_lite_fixed_point_t fifo_level_filtered = do_fifo_depth_lowpass_filter(pid_state->fifo_level_filtered_old , fill_level_wrt_half); - //printf("old fill_level: %f fill_level: %f\n", (float)pid_state->fifo_level_filtered_old/(1<fifo_level_accum + fifo_level_filtered; - - //clip the I term (which can wind up) to maximum fixed point representation. Check to see if overflow (which will change sign) - if (fifo_level_filtered >= 0){ //If it was positive before, ensure it still is else clip to positive - if (i_term_pre_clip >= pid_state->fifo_level_accum){ - //debug_printf("grow %d %d\n", (int32_t)i_term_pre_clip, (int32_t)pid_state->fifo_level_accum); - pid_state->fifo_level_accum = i_term_pre_clip; - } - else{ - pid_state->fifo_level_accum = INT_MAX; - //debug_printf("clip+ %d\n", pid_state->fifo_level_accum); - } - } - else{ //Value was negative so ensure it still is else clip negative - if (i_term_pre_clip <= pid_state->fifo_level_accum){ - pid_state->fifo_level_accum = i_term_pre_clip; - } - else{ - pid_state->fifo_level_accum = INT_MIN; - //debug_printf("clip- %d %d\n", pid_state->fifo_level_accum, fifo_level_filtered); - } - } - - //Calculate D term. No clipping required because it can never be larger than the D term, - //which is already scaled to fit within the fixed point representation - xua_lite_fixed_point_t fifo_level_delta = fifo_level_filtered - pid_state->fifo_level_filtered_old; - - //Save to struct for next iteration - pid_state->fifo_level_filtered_old = fifo_level_filtered; - - //Do PID calculation. Note there is an implicit cast back to xua_lite_fixed_point_t before assignment - xua_lite_fixed_point_t p_term = (((int64_t) fifo_level_filtered * (int64_t)PID_CONTROL_P_TERM_COEFF)) >> XUA_LIGHT_FIXED_POINT_FRAC_BITS; - xua_lite_fixed_point_t i_term = (((int64_t) pid_state->fifo_level_accum * (int64_t)PID_CONTROL_I_TERM_COEFF)) >> XUA_LIGHT_FIXED_POINT_FRAC_BITS; - xua_lite_fixed_point_t d_term = (((int64_t) fifo_level_delta * (int64_t)PID_CONTROL_D_TERM_COEFF)) >> XUA_LIGHT_FIXED_POINT_FRAC_BITS; - - //debug_printf("p: %d i: %d f: %d\n", p_term >> XUA_LIGHT_FIXED_POINT_Q_BITS, i_term >> XUA_LIGHT_FIXED_POINT_Q_BITS, fifo_level_filtered >> (XUA_LIGHT_FIXED_POINT_FRAC_BITS - 10)); - //printf("p: %f i: %f d: %f filtered: %f integrated: %f\n", (float)p_term / (1<<(XUA_LIGHT_FIXED_POINT_FRAC_BITS-PID_CALC_OVERHEAD_BITS)), (float)i_term / (1<<(XUA_LIGHT_FIXED_POINT_FRAC_BITS-PID_CALC_OVERHEAD_BITS)), (float)d_term / (1<<(XUA_LIGHT_FIXED_POINT_FRAC_BITS-PID_CALC_OVERHEAD_BITS)), (float)fifo_level_filtered/(1<fifo_level_accum/(1<> (XUA_LIGHT_FIXED_POINT_Q_BITS - 1 - PID_CALC_OVERHEAD_BITS); - - - //debug_printf("filtered: %d raw: %d\n", fifo_level_filtered >> 22, fill_level_wrt_half); - - //static unsigned counter; counter++; if (counter>100){counter = 0; debug_printf("pid: %d\n",i_term >> (XUA_LIGHT_FIXED_POINT_FRAC_BITS - 10));} - debug_printf("co: %d\n", controller_out >> XUA_LIGHT_FIXED_POINT_FRAC_BITS); - return controller_out; -} - - -//Calculate feedback for asynchronous USB audio -void do_feedback_calculation(unsigned &sof_count - ,const unsigned mclk_hz - ,unsigned mclk_port_counter - ,unsigned &mclk_port_counter_old - ,long long &feedback_value - ,unsigned &mod_from_last_time - ,unsigned fb_clocks[1]){ - // Assuming 48kHz from a 24.576 master clock (0.0407uS period) - // MCLK ticks per SOF = 125uS / 0.0407 = 3072 MCLK ticks per SOF. - // expected Feedback is 48000/8000 = 6 samples. so 0x60000 in 16:16 format. - // Average over 128 SOFs - 128 x 3072 = 0x60000. - - unsigned long long feedbackMul = 64ULL; - if(AUDIO_CLASS == 1) feedbackMul = 8ULL; // TODO Use 4 instead of 8 to avoid windows LSB issues? - - // Number of MCLK ticks in this SOF period (E.g = 125 * 24.576 = 3072) - int mclk_ticks_this_sof_period = (int) ((short)(mclk_port_counter - mclk_port_counter_old)); - unsigned long long full_result = mclk_ticks_this_sof_period * feedbackMul * DEFAULT_FREQ; - feedback_value += full_result; - - // Store MCLK for next time around... - mclk_port_counter_old = mclk_port_counter; - - // Reset counts based on SOF counting. Expect 16ms (128 HS SOFs/16 FS SOFS) per feedback poll - // We always count 128 SOFs, so 16ms @ HS, 128ms @ FS - if(sof_count == 128){ - //debug_printf("fb\n"); - sof_count = 0; - - feedback_value += mod_from_last_time; - unsigned clocks = feedback_value / mclk_hz; - mod_from_last_time = feedback_value % mclk_hz; - feedback_value = 0; - - //Scale for working out number of samps to take from device for input - if(AUDIO_CLASS == 2){ - clocks <<= 3; - } - else{ - clocks <<= 6; - } - asm volatile("stw %0, dp[g_speed]"::"r"(clocks)); // g_speed = clocks - - //Write to feedback EP buffer - if (AUDIO_CLASS == 2){ - fb_clocks[0] = clocks; - } - else{ - fb_clocks[0] = clocks >> 2; - } - } -} - diff --git a/examples/xua_lite_example/xua_lite/xua_buffer_lite.h b/examples/xua_lite_example/xua_lite/xua_buffer_lite.h deleted file mode 100644 index 8ac52765..00000000 --- a/examples/xua_lite_example/xua_lite/xua_buffer_lite.h +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include "xua_ep0_wrapper.h" -#include "xua.h" - -//Currently only single frequency supported -#define NOMINAL_SR_DEVICE DEFAULT_FREQ -#define NOMINAL_SR_HOST DEFAULT_FREQ - -#define DIV_ROUND_UP(n, d) (n / d + 1) //Always rounds up to the next integer. Needed for 48001Hz case etc. -#define BIGGEST(a, b) (a > b ? a : b) - -#define SOF_FREQ_HZ (8000 - ((2 - AUDIO_CLASS) * 7000) ) //1000 for FS or 8000 for HS - -//Defines for endpoint buffer sizes. Samples is total number of samples across all channels -#define MAX_OUT_SAMPLES_PER_SOF_PERIOD (DIV_ROUND_UP(MAX_FREQ, SOF_FREQ_HZ) * NUM_USB_CHAN_OUT) -#define MAX_IN_SAMPLES_PER_SOF_PERIOD (DIV_ROUND_UP(MAX_FREQ, SOF_FREQ_HZ) * NUM_USB_CHAN_IN) -#define MAX_OUTPUT_SLOT_SIZE 4 -#define MAX_INPUT_SLOT_SIZE 4 - -#define OUT_AUDIO_BUFFER_SIZE_BYTES (MAX_OUT_SAMPLES_PER_SOF_PERIOD * MAX_OUTPUT_SLOT_SIZE) -#define IN_AUDIO_BUFFER_SIZE_BYTES (MAX_IN_SAMPLES_PER_SOF_PERIOD * MAX_INPUT_SLOT_SIZE) - -unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub); -[[combinable]] -unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub); - -/** Transfer samples to/from XUA. Should be called at the current USB rate. - * This function is non-blocking. - * - * \param[in,out] c_audio Channel to XUA. - * - * \param[out] sampsFromUsbToAudio Samples sent from host to device. - * - * \param[in] sampsFromAudioToUsb Samples to send from device to host. - * - * \param[out] clock_nudge Notification that the device is running - * too slowly/quickly. Only used when in - * adaptive endpoint mode. - */ -static inline void XUA_transfer_samples(streaming chanend c_audio, - unsigned sampsFromUsbToAudio[], - unsigned sampsFromAudioToUsb[], - int &clock_nudge) { - //Transfer samples. Takes about 25 ticks - for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio :> sampsFromUsbToAudio[i]; - if (XUA_ADAPTIVE) c_audio :> clock_nudge; - for (int i = 0; i < NUM_USB_CHAN_IN; i++) c_audio <: sampsFromAudioToUsb[i]; -} diff --git a/examples/xua_lite_example/xua_lite/xua_buffer_lite.xc b/examples/xua_lite_example/xua_lite/xua_buffer_lite.xc deleted file mode 100644 index 597cb938..00000000 --- a/examples/xua_lite_example/xua_lite/xua_buffer_lite.xc +++ /dev/null @@ -1,384 +0,0 @@ -#include -#include -#include - -#include "xua_commands.h" -#include "xud.h" -#include "testct_byref.h" -#define DEBUG_UNIT XUA_LITE_BUFFER -#define DEBUG_PRINT_ENABLE_XUA_LITE_BUFFER 1 -#include "debug_print.h" -#include "xua.h" -#include "fifo_impl.h" -#include "xua_ep0_wrapper.h" -#include "rate_controller.h" -#include "xua_buffer_lite.h" - - -extern "C"{ -void XUA_Endpoint0_lite_init(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, - chanend ?c_mix_ctl, chanend ?c_clk_ctl, chanend ?c_EANativeTransport_ctrl, CLIENT_INTERFACE(i_dfu, ?dfuInterface) VENDOR_REQUESTS_PARAMS_DEC_); -void XUA_Endpoint0_lite_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, - chanend ?c_mix_ctl, chanend ?c_clk_ctl, chanend ?c_EANativeTransport_ctrl, CLIENT_INTERFACE(i_dfu, ?dfuInterface) VENDOR_REQUESTS_PARAMS_DEC_, unsigned *input_interface_num, unsigned *output_interface_num); -} -#pragma select handler -void XUD_GetSetupData_Select(chanend c, XUD_ep e_out, unsigned &length, XUD_Result_t &result); - -extern XUD_ep ep0_out; -extern XUD_ep ep0_in; - -#if 0 -//Unsafe to allow us to use fifo API without local unsafe scope -unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub) { - - debug_printf("%d\n", MAX_OUT_SAMPLES_PER_SOF_PERIOD); - - //These buffers are unions so we can access them as different types - union buffer_aud_out{ - unsigned char bytes[OUT_AUDIO_BUFFER_SIZE_BYTES]; - short short_words[OUT_AUDIO_BUFFER_SIZE_BYTES / 2]; - long long_words[OUT_AUDIO_BUFFER_SIZE_BYTES / 4]; - }buffer_aud_out; - union buffer_aud_in{ - unsigned char bytes[IN_AUDIO_BUFFER_SIZE_BYTES]; - short short_words[IN_AUDIO_BUFFER_SIZE_BYTES / 2]; - unsigned long long_words[IN_AUDIO_BUFFER_SIZE_BYTES / 4]; - }buffer_aud_in; - - unsigned in_subslot_size = (AUDIO_CLASS == 1) ? FS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES : HS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES; - unsigned out_subslot_size = (AUDIO_CLASS == 1) ? FS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES : HS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES; - - //Asynch feedback calculation - unsigned sof_count = 0; - unsigned mclk_port_counter_old = 0; - long long feedback_value = 0; - unsigned mod_from_last_time = 0; - const unsigned mclk_hz = MCLK_48; - unsigned int fb_clocks[1] = {0}; - - //Adapative device clock control - int clock_nudge = 0; - pid_state_t pid_state = {0, 0}; - - //Endpoints - XUD_ep ep_aud_out = XUD_InitEp(c_aud_out); - XUD_ep ep_aud_in = XUD_InitEp(c_aud_in); - XUD_ep ep_feedback = 0; - if (!isnull(c_feedback)) ep_feedback = XUD_InitEp(c_feedback); - - unsigned num_samples_received_from_host = 0; - unsigned num_samples_to_send_to_host = 0; - - short samples_in_short[NUM_USB_CHAN_IN] = {0}; - short samples_out_short[NUM_USB_CHAN_OUT] = {0}; - - #define c_audioControl null - #define dfuInterface null - XUA_Endpoint0_lite_init(c_ep0_out, c_ep0_in, c_audioControl, null, null, null, dfuInterface); - unsigned char sbuffer[120]; //Raw buffer for EP0 data - USB_SetupPacket_t sp; //Parsed setup packet from EP0 - - unsigned input_interface_num = 0; - unsigned output_interface_num = 0; - - //Enable all EPs - XUD_SetReady_OutPtr(ep_aud_out, (unsigned)buffer_aud_out.long_words); - XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, num_samples_to_send_to_host); - XUD_SetReady_Out(ep0_out, sbuffer); - if (!isnull(c_feedback)) XUD_SetReady_InPtr(ep_feedback, (unsigned)fb_clocks, (AUDIO_CLASS == 2) ? 4 : 3); - - - //Send initial samples so audiohub is not blocked - for (int i = 0; i < 2 * (NUM_USB_CHAN_OUT + (XUA_ADAPTIVE != 0 ? 1 : 0)); i++) c_audio_hub <: 0; - - //FIFOs from EP buffers to audio - short host_to_device_fifo_storage[MAX_OUT_SAMPLES_PER_SOF_PERIOD * 2]; - short device_to_host_fifo_storage[MAX_IN_SAMPLES_PER_SOF_PERIOD * 2]; - mem_fifo_short_t host_to_device_fifo = {sizeof(host_to_device_fifo_storage)/sizeof(host_to_device_fifo_storage[0]), host_to_device_fifo_storage, 0, 0}; - mem_fifo_short_t device_to_host_fifo = {sizeof(device_to_host_fifo_storage)/sizeof(device_to_host_fifo_storage[0]), device_to_host_fifo_storage, 0, 0}; - volatile mem_fifo_short_t * unsafe host_to_device_fifo_ptr = &host_to_device_fifo; - volatile mem_fifo_short_t * unsafe device_to_host_fifo_ptr = &device_to_host_fifo; - - //XUD transaction variables passed in by reference - XUD_Result_t result; - unsigned length = 0; - unsigned u_tmp; //For select channel input by ref on EP0 - int s_tmp; //For select on channel from audiohub - while(1){ - #pragma ordered - select{ - //Handle EP0 requests - case XUD_GetSetupData_Select(c_ep0_out, ep0_out, length, result): - timer tmr; int t0, t1; tmr :> t0; - - debug_printf("ep0, result: %d, length: %d\n", result, length); //-1 reset, 0 ok, 1 error - USB_ParseSetupPacket(sbuffer, sp); //Parse data buffer end populate SetupPacket struct - - XUA_Endpoint0_lite_loop(result, sp, c_ep0_out, c_ep0_in, c_audioControl, null/*mix*/, null/*clk*/, null/*EA*/, dfuInterface, &input_interface_num, &output_interface_num); - XUD_SetReady_Out(ep0_out, sbuffer); - tmr :> t1; debug_printf("c%d\n", t1 - t0); - - break; - - //SOF handling - case inuint_byref(c_sof, u_tmp): - timer tmr; int t0, t1; tmr :> t0; - unsigned mclk_port_counter = 0; - asm volatile(" getts %0, res[%1]" : "=r" (mclk_port_counter) : "r" (p_for_mclk_count)); - if (!isnull(c_feedback)) do_feedback_calculation(sof_count, mclk_hz, mclk_port_counter, mclk_port_counter_old, feedback_value, mod_from_last_time, fb_clocks); - sof_count++; - tmr :> t1; debug_printf("s%d\n", t1 - t0); - - break; - - //Receive samples from host - case XUD_GetData_Select(c_aud_out, ep_aud_out, length, result): - timer tmr; int t0, t1; tmr :> t0; - - num_samples_received_from_host = length / out_subslot_size; - - fifo_ret_t ret = fifo_block_push_short(host_to_device_fifo_ptr, buffer_aud_out.short_words, num_samples_received_from_host); - if (ret != FIFO_SUCCESS) debug_printf("h2d full\n"); - num_samples_to_send_to_host = num_samples_received_from_host; - - int fill_level = fifo_get_fill_short(host_to_device_fifo_ptr); - if (isnull(c_feedback)) do_clock_nudge_pdm(do_rate_control(fill_level, &pid_state), &clock_nudge); - - //Mark EP as ready for next frame from host - XUD_SetReady_OutPtr(ep_aud_out, (unsigned)buffer_aud_out.long_words); - tmr :> t1; debug_printf("o%d\n", t1 - t0); - break; - - //Send asynch explicit feedback value, but only if enabled - case !isnull(c_feedback) => XUD_SetData_Select(c_feedback, ep_feedback, result): - timer tmr; int t0, t1; tmr :> t0; - - XUD_SetReady_In(ep_feedback, (fb_clocks, unsigned char[]), (AUDIO_CLASS == 2) ? 4 : 3); - //debug_printf("0x%x\n", fb_clocks[0]); - tmr :> t1; debug_printf("f%d\n", t1 - t0); - - break; - - //Send samples to host - case XUD_SetData_Select(c_aud_in, ep_aud_in, result): - timer tmr; int t0, t1; tmr :> t0; - - if (output_interface_num == 0) num_samples_to_send_to_host = (DEFAULT_FREQ / SOF_FREQ_HZ) * NUM_USB_CHAN_IN; - - fifo_ret_t ret = fifo_block_pop_short(device_to_host_fifo_ptr, buffer_aud_in.short_words, num_samples_received_from_host); - if (ret != FIFO_SUCCESS) debug_printf("d2h empty\n"); - - //Populate the input buffer ready for the next read - //pack_samples_to_buff(loopback_samples, num_samples_to_send_to_host, in_subslot_size, buffer_aud_in); - //Use the number of samples we received last time so we are always balanced (assumes same in/out count) - - unsigned input_buffer_size = num_samples_to_send_to_host * in_subslot_size; - XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, input_buffer_size); //loopback - num_samples_to_send_to_host = 0; - tmr :> t1; debug_printf("i%d\n", t1 - t0); - - break; - - //Exchange samples with audiohub. Note we are using channel buffering here to act as a FIFO - case c_audio_hub :> s_tmp: - timer tmr; int t0, t1; tmr :> t0; - samples_in_short[0] = s_tmp >> 16; - for (int i = 1; i < NUM_USB_CHAN_IN; i++){ - c_audio_hub :> s_tmp; - samples_in_short[i] = s_tmp >> 16; - } - fifo_ret_t ret = fifo_block_pop_short(host_to_device_fifo_ptr, samples_out_short, NUM_USB_CHAN_OUT); - if (ret != FIFO_SUCCESS && output_interface_num != 0) debug_printf("h2d empty\n"); - for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio_hub <: (int)samples_out_short[i] << 16; - if (XUA_ADAPTIVE) c_audio_hub <: clock_nudge; - ret = fifo_block_push_short(device_to_host_fifo_ptr, samples_in_short, NUM_USB_CHAN_IN); - if (ret != FIFO_SUCCESS && input_interface_num != 0) debug_printf("d2h full\n"); - tmr :> t1; debug_printf("a%d\n", t1 - t0); - break; - } - } -} -#endif -extern port p_sda; - -[[combinable]] -//Unsafe to allow us to use fifo API without local unsafe scope -unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub) { - - debug_printf("%d\n", MAX_OUT_SAMPLES_PER_SOF_PERIOD); - - //These buffers are unions so we can access them as different types - union buffer_aud_out{ - unsigned char bytes[OUT_AUDIO_BUFFER_SIZE_BYTES]; - short short_words[OUT_AUDIO_BUFFER_SIZE_BYTES / 2]; - long long_words[OUT_AUDIO_BUFFER_SIZE_BYTES / 4]; - }buffer_aud_out; - union buffer_aud_in{ - unsigned char bytes[IN_AUDIO_BUFFER_SIZE_BYTES]; - short short_words[IN_AUDIO_BUFFER_SIZE_BYTES / 2]; - unsigned long long_words[IN_AUDIO_BUFFER_SIZE_BYTES / 4]; - }buffer_aud_in; - - unsigned in_subslot_size = (AUDIO_CLASS == 1) ? FS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES : HS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES; - unsigned out_subslot_size = (AUDIO_CLASS == 1) ? FS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES : HS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES; - - //Asynch feedback calculation - unsigned sof_count = 0; - unsigned mclk_port_counter_old = 0; - long long feedback_value = 0; - unsigned mod_from_last_time = 0; - const unsigned mclk_hz = MCLK_48; - unsigned int fb_clocks[1] = {0}; - - //Adapative device clock control - int clock_nudge = 0; - pid_state_t pid_state = {0, 0}; - - - //Endpoints - XUD_ep ep_aud_out = XUD_InitEp(c_aud_out); - XUD_ep ep_aud_in = XUD_InitEp(c_aud_in); - XUD_ep ep_feedback = 0; - if (!isnull(c_feedback)) ep_feedback = XUD_InitEp(c_feedback); - - unsigned num_samples_received_from_host = 0; - unsigned num_samples_to_send_to_host = 0; - - unsigned input_interface_num = 0; - unsigned output_interface_num = 0; - - //Enable all EPs - XUD_SetReady_OutPtr(ep_aud_out, (unsigned)buffer_aud_out.long_words); - XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, num_samples_to_send_to_host); - if (!isnull(c_feedback)) XUD_SetReady_InPtr(ep_feedback, (unsigned)fb_clocks, (AUDIO_CLASS == 2) ? 4 : 3); - - short samples_in_short[NUM_USB_CHAN_IN] = {0}; - short samples_out_short[NUM_USB_CHAN_OUT] = {0}; - - - //Send initial samples so audiohub is not blocked - const unsigned n_sample_periods_to_preload = 2; - for (int i = 0; i < n_sample_periods_to_preload * (NUM_USB_CHAN_OUT + (XUA_ADAPTIVE != 0 ? 1 : 0)); i++) c_audio_hub <: 0; - - //FIFOs from EP buffers to audio - short host_to_device_fifo_storage[MAX_OUT_SAMPLES_PER_SOF_PERIOD * 2]; - short device_to_host_fifo_storage[MAX_IN_SAMPLES_PER_SOF_PERIOD * 2]; - mem_fifo_short_t host_to_device_fifo = {sizeof(host_to_device_fifo_storage)/sizeof(host_to_device_fifo_storage[0]), host_to_device_fifo_storage, 0, 0}; - mem_fifo_short_t device_to_host_fifo = {sizeof(device_to_host_fifo_storage)/sizeof(device_to_host_fifo_storage[0]), device_to_host_fifo_storage, 0, 0}; - volatile mem_fifo_short_t * unsafe host_to_device_fifo_ptr = &host_to_device_fifo; - volatile mem_fifo_short_t * unsafe device_to_host_fifo_ptr = &device_to_host_fifo; - - //XUD transaction variables passed in by reference - XUD_Result_t result; - unsigned length = 0; - unsigned u_tmp; //For select channel input by ref on EP0 - int s_tmp; //For select on channel from audiohub - while(1){ - select{ - //Handle EP0 requests - case i_ep0_ctl.set_output_interface(unsigned num): - //Reset output FIFO if moving from idle to streaming - if (num != 0 && output_interface_num == 0) fifo_init_short(host_to_device_fifo_ptr); - output_interface_num = num; - debug_printf("output_interface_num: %d\n", num); - break; - - case i_ep0_ctl.set_input_interface(unsigned num): - input_interface_num = num; - debug_printf("input_interface_num: %d\n", num); - break; - - case i_ep0_ctl.set_host_active(unsigned active): - break; - - //SOF handling - case inuint_byref(c_sof, u_tmp): - timer tmr; int t0, t1; tmr :> t0; - unsigned mclk_port_counter = 0; - asm volatile(" getts %0, res[%1]" : "=r" (mclk_port_counter) : "r" (p_for_mclk_count)); - if (!isnull(c_feedback)) do_feedback_calculation(sof_count, mclk_hz, mclk_port_counter, mclk_port_counter_old, feedback_value, mod_from_last_time, fb_clocks); - sof_count++; - //tmr :> t1; debug_printf("s%d\n", t1 - t0); - uint16_t port_counter; - p_sda <: 1 @ port_counter; - p_sda @ port_counter + 100 <: 0; - break; - - //Receive samples from host - case XUD_GetData_Select(c_aud_out, ep_aud_out, length, result): - timer tmr; int t0, t1; tmr :> t0; - - num_samples_received_from_host = length / out_subslot_size; - - if (num_samples_received_from_host != 96) debug_printf("hs: %d\n", num_samples_received_from_host); - - fifo_ret_t ret = fifo_block_push_short_fast(host_to_device_fifo_ptr, buffer_aud_out.short_words, num_samples_received_from_host); - if (ret != FIFO_SUCCESS) debug_printf("h2d full\n"); - num_samples_to_send_to_host = num_samples_received_from_host; - - int fill_level = fifo_get_fill_short(host_to_device_fifo_ptr); - if (isnull(c_feedback)) do_clock_nudge_pdm(do_rate_control(fill_level, &pid_state), &clock_nudge); - - //Mark EP as ready for next frame from host - XUD_SetReady_OutPtr(ep_aud_out, (unsigned)buffer_aud_out.long_words); - //tmr :> t1; debug_printf("o%d\n", t1 - t0); - break; - - //Send asynch explicit feedback value, but only if enabled - case !isnull(c_feedback) => XUD_SetData_Select(c_feedback, ep_feedback, result): - timer tmr; int t0, t1; tmr :> t0; - - XUD_SetReady_In(ep_feedback, (fb_clocks, unsigned char[]), (AUDIO_CLASS == 2) ? 4 : 3); - //debug_printf("0x%x\n", fb_clocks[0]); - //tmr :> t1; debug_printf("f%d\n", t1 - t0); - break; - - //Send samples to host - case XUD_SetData_Select(c_aud_in, ep_aud_in, result): - timer tmr; int t0, t1; tmr :> t0; - - //If host is not streaming out, then send a fixed number of samples to host - if (output_interface_num == 0) { - num_samples_to_send_to_host = (DEFAULT_FREQ / SOF_FREQ_HZ) * NUM_USB_CHAN_IN; - int fill_level = fifo_get_fill_short(device_to_host_fifo_ptr); - if (isnull(c_feedback)) do_clock_nudge_pdm(-do_rate_control(fill_level, &pid_state), &clock_nudge); - } - - fifo_ret_t ret = fifo_block_pop_short_fast(device_to_host_fifo_ptr, buffer_aud_in.short_words, num_samples_received_from_host); - if (ret != FIFO_SUCCESS) { - memset(buffer_aud_in.short_words, 0, sizeof(buffer_aud_in.short_words)); - debug_printf("d2h empty\n"); - } - - //Populate the input buffer ready for the next read - //pack_samples_to_buff(loopback_samples, num_samples_to_send_to_host, in_subslot_size, buffer_aud_in); - //Use the number of samples we received last time so we are always balanced (assumes same in/out count) - - unsigned input_buffer_size = num_samples_to_send_to_host * in_subslot_size; - XUD_SetReady_InPtr(ep_aud_in, (unsigned) buffer_aud_in.long_words, input_buffer_size); //loopback - num_samples_to_send_to_host = 0; - //tmr :> t1; debug_printf("i%d\n", t1 - t0); - break; - - //Exchange samples with audiohub. Note we are using channel buffering here to act as a FIFO - case c_audio_hub :> s_tmp: - timer tmr; int t0, t1; tmr :> t0; - samples_in_short[0] = s_tmp >> 16; - for (int i = 1; i < NUM_USB_CHAN_IN; i++){ - c_audio_hub :> s_tmp; - samples_in_short[i] = s_tmp >> 16; - } - fifo_ret_t ret = fifo_block_pop_short(host_to_device_fifo_ptr, samples_out_short, NUM_USB_CHAN_OUT); - if (ret != FIFO_SUCCESS && output_interface_num != 0) { - memset(samples_out_short, 0, sizeof(samples_out_short)); - debug_printf("h2d empty\n"); - } - for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio_hub <: (int)samples_out_short[i] << 16; - if (XUA_ADAPTIVE) c_audio_hub <: clock_nudge; - ret = fifo_block_push_short(device_to_host_fifo_ptr, samples_in_short, NUM_USB_CHAN_IN); - if (ret != FIFO_SUCCESS && input_interface_num != 0) debug_printf("d2h full\n"); - //tmr :> t1; debug_printf("a%d\n", t1 - t0); - break; - } - } -} diff --git a/examples/xua_lite_example/xua_lite/xua_buffer_pack.h b/examples/xua_lite_example/xua_lite/xua_buffer_pack.h deleted file mode 100644 index 36fc2f33..00000000 --- a/examples/xua_lite_example/xua_lite/xua_buffer_pack.h +++ /dev/null @@ -1,65 +0,0 @@ -//Helper to disassemble USB packets into 32b left aligned audio samples -#pragma unsafe arrays -static inline void unpack_buff_to_samples(unsigned char input[], const unsigned n_samples, const unsigned slot_size, int output[]){ - switch(slot_size){ - case 4: - for (int i = 0; i < n_samples; i++){ - unsigned base = i * 4; - output[i] = (input[base + 3] << 24) | (input[base + 2] << 16) | (input[base + 1] << 8) | input[base + 0]; - } - break; - case 3: - for (int i = 0; i < n_samples; i++){ - unsigned base = i * 3; - output[i] = (input[base + 2] << 24) | (input[base + 1] << 16) | (input[base + 0] << 8); - } - break; - case 2: - for (int i = 0; i < n_samples; i++){ - unsigned base = i * 2; - output[i] = (input[base + 1] << 24) | (input[base + 0] << 16); - } - break; - default: - debug_printf("Invalid slot_size\n"); - break; - } -} - -//Helper to assemble USB packets from 32b left aligned audio samples -#pragma unsafe arrays -static inline void pack_samples_to_buff(int input[], const unsigned n_samples, const unsigned slot_size, unsigned char output[]){ - switch(slot_size){ - case 4: - for (int i = 0; i < n_samples; i++){ - unsigned base = i * 4; - unsigned in_word = (unsigned)input[i]; - output[base + 0] = in_word & 0xff; - output[base + 1] = (in_word & 0xff00) >> 8; - output[base + 2] = (in_word & 0xff0000) >> 16; - output[base + 3] = (in_word) >> 24; - } - break; - case 3: - for (int i = 0; i < n_samples; i++){ - unsigned base = i * 3; - unsigned in_word = (unsigned)input[i]; - output[base + 0] = (in_word & 0xff00) >> 8; - output[base + 1] = (in_word & 0xff0000) >> 16; - output[base + 2] = (in_word) >> 24; - } - break; - case 2: - for (int i = 0; i < n_samples; i++){ - unsigned base = i * 2; - unsigned in_word = (unsigned)input[i]; - output[base + 0] = (in_word & 0xff0000) >> 16; - output[base + 1] = (in_word) >> 24; - } - break; - default: - debug_printf("Invalid slot_size\n"); - break; - } -} -