diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 434daeba..22ede8f6 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -22,9 +22,13 @@ #include "commands.h" #include "xc_ptr.h" -unsigned testsamples[100]; -int p = 0; -unsigned lastSample = 0; + +static unsigned samplesOut[NUM_USB_CHAN_OUT]; + +/* Two buffers for ADC data to allow for DAC and ADC ports being offset */ +static unsigned samplesIn_0[NUM_USB_CHAN_IN]; +static unsigned samplesIn_1[I2S_CHANS_ADC]; + #if (DSD_CHANS_DAC != 0) extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC]; extern buffered out port:32 p_dsd_clk; @@ -32,11 +36,18 @@ extern buffered out port:32 p_dsd_clk; unsigned g_adcVal = 0; -//#pragma xta command "analyse path i2s_output_l i2s_output_r" -//#pragma xta command "set required - 2000 ns" +#ifdef XTA_TIMING_AUDIO +#pragma xta command "add exclusion received_command" +#pragma xta command "analyse path i2s_output_l i2s_output_r" +#pragma xta command "set required - 2000 ns" -//#pragma xta command "analyse path i2s_output_r i2s_output_l" -//#pragma xta command "set required - 2000 ns" +#pragma xta command "add exclusion received_command" +#pragma xta command "add exclusion received_underflow" +#pragma xta command "add exclusion divide_1" +#pragma xta command "add exclusion deliver_return" +#pragma xta command "analyse path i2s_output_r i2s_output_l" +#pragma xta command "set required - 2000 ns" +#endif /* I2S Data I/O*/ #if (I2S_CHANS_DAC != 0) @@ -142,249 +153,13 @@ static inline void doI2SClocks(unsigned divide) } #endif -/* I2S delivery thread */ #pragma unsafe arrays -unsigned static deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, unsigned curSamFreq, -#if(defined(SPDIF_RX) || defined(ADAT_RX)) -chanend c_dig_rx, -#endif -chanend ?c_adc) +static inline unsigned DoSampleTransfer(chanend c_out, int readBuffNo, unsigned underflowWord) { -#if (I2S_CHANS_ADC != 0) || defined(SPDIF) - unsigned sample; -#endif - unsigned underflow = 0; -#if NUM_USB_CHAN_OUT > 0 - unsigned samplesOut[NUM_USB_CHAN_OUT]; -#endif -#if NUM_USB_CHAN_IN > 0 - unsigned samplesIn[NUM_USB_CHAN_IN]; - unsigned samplesInPrev[NUM_USB_CHAN_IN]; -#endif - unsigned tmp; -#if (I2S_CHANS_ADC != 0) - unsigned index; -#endif -#ifdef RAMP_CHECK - unsigned prev=0; - int started = 0; -#endif + unsigned command; + unsigned underflow; -#if (DSD_CHANS_DAC != 0) - unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */ - int dsdCount = 0; - int everyOther = 1; - unsigned dsdSample_l = 0x96960000; - unsigned dsdSample_r = 0x96960000; -#endif - unsigned underflowWord = 0; - -#if NUM_USB_CHAN_IN > 0 - for (int i=0;i 0) - if(dsdMode == DSD_MODE_DOP) - dsdMode = DSD_MODE_OFF; -#endif - return command; - } - else - { - underflow = inuint(c_out); -#ifndef MIXER // Interfaces straight to decouple() - -#if NUM_USB_CHAN_IN > 0 -#pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_IN; i++) - { - outuint(c_out, samplesIn[i]); - } -#endif - -#if NUM_USB_CHAN_OUT > 0 - if(underflow) - { -#pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - samplesOut[i] = underflowWord; - } - } - else - { -#pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - samplesOut[i] = inuint(c_out); - } - } -#endif -#else /* ifndef MIXER */ - -#if NUM_USB_CHAN_OUT > 0 - if(underflow) - { - #pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - samplesOut[i] = underflowWord; - } - } - else - { -#pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - int tmp = inuint(c_out); - samplesOut[i] = tmp; - } - } -#endif - -#if NUM_USB_CHAN_IN > 0 -#pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_IN; i++) - { - outuint(c_out, samplesIn[i]); - } -#endif -#endif - } - -#ifndef CODEC_MASTER -#if (DSD_CHANS_DAC > 0) - if(dsdMode == DSD_MODE_OFF) - { -#endif - /* b_clk must start high */ - p_bclk <: 0x80000000; - sync(p_bclk); - /* Clear I2S port buffers */ - clearbuf(p_lrclk); - -#if (I2S_CHANS_DAC != 0) - for(int i = 0; i < I2S_WIRES_DAC; i++) - { - clearbuf(p_i2s_dac[i]); - } -#endif - -#if (I2S_CHANS_ADC != 0) - for(int i = 0; i < I2S_WIRES_ADC; i++) - { - clearbuf(p_i2s_adc[i]); - } -#endif - if(divide == 1) - { - p_lrclk <: 0 @ tmp; - tmp += 100; - - /* Since BCLK is free-running, setup outputs/inputs at a known point in the future */ -#if (I2S_CHANS_DAC != 0) -#pragma loop unroll - for(int i = 0; i < I2S_WIRES_DAC; i++) - { - p_i2s_dac[i] @ tmp <: 0; - } -#endif - - p_lrclk @ tmp <: 0x7FFFFFFF; - - -#if (I2S_CHANS_ADC != 0) - for(int i = 0; i < I2S_WIRES_ADC; i++) - { - asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1)); - } -#endif - } - else - { - clearbuf(p_bclk); - -#if (I2S_CHANS_DAC != 0) - /* Prefill the ports so data is input in advance */ - for(int i = 0; i < I2S_WIRES_DAC; i++) - { - p_i2s_dac[i] <: 0; - } -#endif - p_lrclk <: 0x7FFFFFFF; - doI2SClocks(divide); - - } -#if (DSD_CHANS_DAC > 0) - } /* if (!dsdMode) */ - else - { - /* p_dsd_clk must start high */ - p_dsd_clk <: 0x80000000; - } -#endif -#else /* ifndef CODEC_MASTER */ - - /* Wait for LRCLK edge */ - p_lrclk when pinseq(0) :> void; - p_lrclk when pinseq(1) :> void; - p_lrclk when pinseq(0) :> void; - p_lrclk when pinseq(1) :> void; - p_lrclk when pinseq(0) :> void @ tmp; - tmp+=97; -#if (I2S_CHANS_DAC != 0) -#pragma loop unroll - for(int i = 0; i < I2S_WIRES_DAC; i++) - { - p_i2s_dac[i] @ tmp <: 0; - } -#endif - -#if (I2S_CHANS_ADC != 0) -#pragma loop unroll - for(int i = 0; i < I2S_WIRES_ADC; i++) - { - asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp+31)); - } -#endif - - /* TODO In master mode, the i/o loop assumes L/RCLK = 32bit clocks. We should check this every interation - * and resync if we got a bclk glitch */ - -#endif - - /* Main Audio I/O loop */ - while (1) - { - outuint(c_out, 0); + outuint(c_out, 0); /* Check for sample freq change (or other command) or new samples from mixer*/ if(testct(c_out)) @@ -403,6 +178,7 @@ chanend ?c_adc) if(dsdMode == DSD_MODE_DOP) dsdMode = DSD_MODE_OFF; #endif +#pragma xta endpoint "received_command" return command; } @@ -457,17 +233,197 @@ chanend ?c_adc) #endif #if NUM_USB_CHAN_IN > 0 #pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_IN; i++) + for(int i = 0; i < I2S_CHANS_ADC; i++) { - outuint(c_out, samplesIn[i]); + if(readBuffNo) + outuint(c_out, samplesIn_1[i]); + else + outuint(c_out, samplesIn_0[i]); + } + /* Send over the digi channels - no odd buffering required */ +#pragma loop unroll + for(int i = I2S_CHANS_ADC; i < NUM_USB_CHAN_IN; i++) + { + outuint(c_out, samplesIn_0[i]); } #endif #endif } + return 0; + +} + +static inline void InitPorts(unsigned divide) +{ + unsigned tmp; +#ifndef CODEC_MASTER +#if (DSD_CHANS_DAC > 0) + if(dsdMode == DSD_MODE_OFF) + { +#endif + /* b_clk must start high */ + p_bclk <: 0x80000000; + sync(p_bclk); + /* Clear I2S port buffers */ + clearbuf(p_lrclk); + +#if (I2S_CHANS_DAC != 0) + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + clearbuf(p_i2s_dac[i]); + } +#endif + +#if (I2S_CHANS_ADC != 0) + for(int i = 0; i < I2S_WIRES_ADC; i++) + { + clearbuf(p_i2s_adc[i]); + } +#endif + if(divide == 1) + { +#pragma xta endpoint "divide_1" + p_lrclk <: 0 @ tmp; + tmp += 100; + + /* Since BCLK is free-running, setup outputs/inputs at a known point in the future */ +#if (I2S_CHANS_DAC != 0) +#pragma loop unroll + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] @ tmp <: 0; + } +#endif + + p_lrclk @ tmp <: 0x7FFFFFFF; - tmp = 0; +#if (I2S_CHANS_ADC != 0) + for(int i = 0; i < I2S_WIRES_ADC; i++) + { + asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1)); + } +#endif + } + else /* Divide != 1 */ + { +#if (I2S_CHANS_DAC != 0) + /* Pre-fill the DAC ports */ + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] <: 0; + } +#endif + /* Pre-fill the LR clock output port */ + p_lrclk <: 0x0; + + doI2SClocks(divide); + + } +#if (DSD_CHANS_DAC > 0) + } /* if (!dsdMode) */ + else + { + /* p_dsd_clk must start high */ + p_dsd_clk <: 0x80000000; + } +#endif +#else /* ifndef CODEC_MASTER */ + + /* Wait for LRCLK edge */ + p_lrclk when pinseq(0) :> void; + p_lrclk when pinseq(1) :> void; + p_lrclk when pinseq(0) :> void; + p_lrclk when pinseq(1) :> void; + p_lrclk when pinseq(0) :> void @ tmp; + tmp+=97; +#if (I2S_CHANS_DAC != 0) +#pragma loop unroll + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] @ tmp <: 0; + } +#endif + +#if (I2S_CHANS_ADC != 0) +#pragma loop unroll + for(int i = 0; i < I2S_WIRES_ADC; i++) + { + asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp+31)); + } +#endif +#endif +} + + + +/* I2S delivery thread */ +#pragma unsafe arrays +unsigned static deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, unsigned curSamFreq, +#if(defined(SPDIF_RX) || defined(ADAT_RX)) +chanend c_dig_rx, +#endif +chanend ?c_adc) +{ +#if (I2S_CHANS_ADC != 0) || defined(SPDIF) + unsigned sample; +#endif + unsigned underflow = 0; +#if NUM_USB_CHAN_OUT > 0 +#endif +//#if NUM_USB_CHAN_IN > 0 + /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ + unsigned readBuffNo = 0; +//#endif + unsigned tmp; + unsigned index; + +#ifdef RAMP_CHECK + unsigned prev=0; + int started = 0; +#endif + +#if (DSD_CHANS_DAC != 0) + unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */ + int dsdCount = 0; + int everyOther = 1; + unsigned dsdSample_l = 0x96960000; + unsigned dsdSample_r = 0x96960000; +#endif + unsigned underflowWord = 0; + + unsigned frameCount = 0; + +#if(DSD_CHANS_DAC != 0) + if(dsdMode == DSD_MODE_DOP) + { + underflowWord = 0xFA969600; + } + else if(dsdMode == DSD_MODE_NATIVE) + { + underflowWord = 0x96969696; + } +#endif + +#if 1 + unsigned command = DoSampleTransfer(c_out, readBuffNo, underflowWord); + + if(command) + { + return command; + } +#endif + + InitPorts(divide); + + /* TODO In master mode, the i/o loop assumes L/RCLK = 32bit clocks. We should check this every interation + * and resync if we got a bclk glitch */ + + /* Main Audio I/O loop */ + while (1) + { + #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) if(dsdMode == DSD_MODE_NATIVE) { @@ -575,108 +531,132 @@ chanend ?c_adc) else #endif { - -#pragma xta endpoint "i2s_output_l" - -#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) -#pragma loop unroll - for(int i = 0; i < I2S_CHANS_DAC; i+=2) - { - p_i2s_dac[tmp++] <: bitrev(samplesOut[i]); /* Output LEFT sample to DAC */ - } -#endif - #ifndef CODEC_MASTER /* LR clock delayed by one clock, This is so MSB is output on the falling edge of BCLK * after the falling edge on which LRCLK was toggled. (see I2S spec) */ /* Generate clocks LR Clock low - LEFT */ +#ifdef I2S_MODE_TDM + p_lrclk <: 0x00000000; +#else p_lrclk <: 0x80000000; - doI2SClocks(divide); + +#endif #endif +#pragma xta endpoint "i2s_output_l" -#if (I2S_CHANS_ADC != 0) - /* Input prevous R sample into R in buffer */ +#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) index = 0; #pragma loop unroll - for(int i = 1; i < I2S_CHANS_ADC; i += 2) + /* Output "even" channel to DAC (i.e. left) */ + for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) + { + p_i2s_dac[index++] <: bitrev(samplesOut[(frameCount)+i]); + } +#endif + + /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */ + doI2SClocks(divide); + +#if (I2S_CHANS_ADC != 0) + /* Input previous L sample into L in buffer */ + index = 0; + /* First input (i.e. frameCoint == 0) we read last ADC channel of previous frame.. */ + unsigned buffIndex = frameCount ? !readBuffNo : readBuffNo; + +#pragma loop unroll + /* First time around we get channel 7 of TDM8 */ + for(int i = 0; i < I2S_CHANS_ADC; i+=I2S_CHANS_PER_FRAME) { // p_i2s_adc[index++] :> sample; // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); -#if NUM_USB_CHAN_IN > 0 - samplesIn[i] = bitrev(sample); - - /* Store the previous left in left */ - samplesIn[i-1] = samplesInPrev[i]; -#endif + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + /* Note the use of readBuffNo changes based on frameCount */ + if(buffIndex) + samplesIn_1[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line. + else + samplesIn_0[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line. } #endif + + if(frameCount == 0) + { + #if defined(SPDIF_RX) || defined(ADAT_RX) - /* Sync with clockgen */ - inuint(c_dig_rx); + /* Sync with clockgen */ + inuint(c_dig_rx); + + /* Note, digi-data we just store in samplesIn_0 - we only double buffer the I2S input data */ #endif #ifdef SPDIF_RX - asm("ldw %0, dp[g_digData]":"=r"(samplesIn[SPDIF_RX_INDEX + 0])); - asm("ldw %0, dp[g_digData+4]":"=r"(samplesIn[SPDIF_RX_INDEX + 1])); + asm("ldw %0, dp[g_digData]":"=r"(samplesIn_0[SPDIF_RX_INDEX + 0])); + asm("ldw %0, dp[g_digData+4]":"=r"(samplesIn_0[SPDIF_RX_INDEX + 1])); #endif #ifdef ADAT_RX - asm("ldw %0, dp[g_digData+8]":"=r"(samplesIn[ADAT_RX_INDEX])); - asm("ldw %0, dp[g_digData+12]":"=r"(samplesIn[ADAT_RX_INDEX + 1])); - asm("ldw %0, dp[g_digData+16]":"=r"(samplesIn[ADAT_RX_INDEX + 2])); - asm("ldw %0, dp[g_digData+20]":"=r"(samplesIn[ADAT_RX_INDEX + 3])); - asm("ldw %0, dp[g_digData+24]":"=r"(samplesIn[ADAT_RX_INDEX + 4])); - asm("ldw %0, dp[g_digData+28]":"=r"(samplesIn[ADAT_RX_INDEX + 5])); - asm("ldw %0, dp[g_digData+32]":"=r"(samplesIn[ADAT_RX_INDEX + 6])); - asm("ldw %0, dp[g_digData+36]":"=r"(samplesIn[ADAT_RX_INDEX + 7])); + asm("ldw %0, dp[g_digData+8]":"=r"(samplesIn_0[ADAT_RX_INDEX])); + asm("ldw %0, dp[g_digData+12]":"=r"(samplesIn_0[ADAT_RX_INDEX + 1])); + asm("ldw %0, dp[g_digData+16]":"=r"(samplesIn_0[ADAT_RX_INDEX + 2])); + asm("ldw %0, dp[g_digData+20]":"=r"(samplesIn_0[ADAT_RX_INDEX + 3])); + asm("ldw %0, dp[g_digData+24]":"=r"(samplesIn_0[ADAT_RX_INDEX + 4])); + asm("ldw %0, dp[g_digData+28]":"=r"(samplesIn_0[ADAT_RX_INDEX + 5])); + asm("ldw %0, dp[g_digData+32]":"=r"(samplesIn_0[ADAT_RX_INDEX + 6])); + asm("ldw %0, dp[g_digData+36]":"=r"(samplesIn_0[ADAT_RX_INDEX + 7])); #endif #if defined(SPDIF_RX) || defined(ADAT_RX) /* Request digital data (with prefill) */ - outuint(c_dig_rx, 0); + outuint(c_dig_rx, 0); #endif #if defined(SPDIF) && (NUM_USB_CHAN_OUT > 0) outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to S/PDIF Tx thread */ sample = samplesOut[SPDIF_TX_INDEX + 1]; outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ #endif - tmp = 0; + } + +#ifndef CODEC_MASTER +#ifdef I2S_MODE_TDM + if(frameCount == (I2S_CHANS_PER_FRAME-2)) + p_lrclk <: 0x80000000; + else + p_lrclk <: 0x00000000; +#else + p_lrclk <: 0x7FFFFFFF; +#endif +#endif + + index = 0; #pragma xta endpoint "i2s_output_r" #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) + /* Output "odd" channel to DAC (i.e. right) */ #pragma loop unroll - for(int i = 1; i < I2S_CHANS_DAC; i+=2) + for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) { - p_i2s_dac[tmp++] <: bitrev(samplesOut[i]); /* Output RIGHT sample to DAC */ + p_i2s_dac[index++] <: bitrev(samplesOut[frameCount+i]); } #endif -#ifndef CODEC_MASTER - /* Clock out data (and LR clock) */ - p_lrclk <: 0x7FFFFFFF; doI2SClocks(divide); -#endif - #if (I2S_CHANS_ADC != 0) - /* Input previous L ADC sample */ index = 0; + /* Channels 0, 2, 4.. on each line */ #pragma loop unroll - for(int i = 1; i < I2S_CHANS_ADC; i += 2) + for(int i = 0; i < I2S_CHANS_ADC; i += I2S_CHANS_PER_FRAME) { - // p_i2s_adc[index++] :> sample; - // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) + /* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */ asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - -#if NUM_USB_CHAN_IN > 0 - samplesInPrev[i] = bitrev(sample); -#endif + if(readBuffNo) + samplesIn_0[frameCount+i] = bitrev(sample); + else + samplesIn_1[frameCount+i] = bitrev(sample); } #ifdef SU1_ADC_ENABLE { unsigned x; - x = inuint(c_adc); inct(c_adc); asm volatile("stw %0, dp[g_adcVal]"::"r"(x)); @@ -730,7 +710,34 @@ chanend ?c_adc) } } #endif + +#ifdef I2S_MODE_TDM + /* Increase frameCount by 2 since we have output two channels (per data line) */ + frameCount+=2; + if(frameCount == I2S_CHANS_PER_FRAME) +#endif + { + /* Do samples transfer */ + /* The below looks a bit odd but forces the compiler to inline twice */ + unsigned command; + if(readBuffNo) + command = DoSampleTransfer(c_out, 1, underflowWord); + else + command = DoSampleTransfer(c_out, 0, underflowWord); + + + if(command) + { + return command; + } + + /* Reset frame counter and flip the ADC buffer */ + frameCount = 0; + readBuffNo = !readBuffNo; + } } + +#pragma xta endpoint "deliver_return" return 0; } @@ -786,7 +793,6 @@ unsigned static dummy_deliver(chanend c_out) #define NUMBER_WORDS ((NUMBER_SAMPLES * NUMBER_CHANNELS+1)/2) #define SAMPLES_PER_PRINT 1 - void audio(chanend c_mix_out, #if (defined(ADAT_RX) || defined(SPDIF_RX)) chanend c_dig_rx, @@ -873,8 +879,13 @@ chanend ?c_config, chanend ?c) /* Calculate master clock to bit clock (or DSD clock) divide for current sample freq * e.g. 11.289600 / (176400 * 64) = 1 */ { +#if I2S_MODE_TDM + /* I2S has 32 bits per sample. *8 as 8 channels */ + unsigned numBits = 256; +#else /* I2S has 32 bits per sample. *2 as 2 channels */ unsigned numBits = 64; +#endif #if (DSD_CHANS_DAC > 0) if(dsdMode == DSD_MODE_DOP) @@ -888,7 +899,7 @@ chanend ?c_config, chanend ?c) numBits = 32; } #endif - divide = mClk / ( curSamFreq * numBits ); + divide = mClk / ( curSamFreq * numBits); } diff --git a/module_usb_audio/devicedefines.h b/module_usb_audio/devicedefines.h index 60e71691..08012067 100644 --- a/module_usb_audio/devicedefines.h +++ b/module_usb_audio/devicedefines.h @@ -76,8 +76,13 @@ #error I2S_CHANS_DAC not defined #define I2S_CHANS_DAC 2 /* Define anyway for doxygen */ #else + +#ifdef I2S_MODE_TDM +#define I2S_WIRES_DAC (I2S_CHANS_DAC >> 3) +#else #define I2S_WIRES_DAC (I2S_CHANS_DAC >> 1) #endif +#endif /** * @brief Number of I2S channels from ADC/CODEC. Must be a multiple of 2. @@ -88,8 +93,27 @@ #error I2S_CHANS_ADC not defined #define I2S_CHANS_ADC 2 /* Define anyway for doxygen */ #else + +#ifdef I2S_MODE_TDM +#define I2S_WIRES_ADC (I2S_CHANS_ADC >> 3) +#else #define I2S_WIRES_ADC (I2S_CHANS_ADC >> 1) #endif +#endif + +/** + * @brief Channels per I2S frame. * + * + * Default: 2 i.e standard stereo I2S (8 if using TDM i.e. I2S_MODE_TDM). + * + **/ +#ifndef I2S_CHANS_PER_FRAME +#ifdef I2S_MODE_TDM +#define I2S_CHANS_PER_FRAME 8 +#else +#define I2S_CHANS_PER_FRAME 2 +#endif +#endif /** * @brief Max supported sample frequency for device (Hz). Default: 192000 @@ -975,7 +999,7 @@ #else #if defined(MIXER) // Enabled by default -#define OUT_VOLUME_IN_MIXER +//#define OUT_VOLUME_IN_MIXER #endif #endif @@ -995,7 +1019,7 @@ #else #if defined(MIXER) /* Enabled by default */ -#define IN_VOLUME_IN_MIXER +//#define IN_VOLUME_IN_MIXER #endif #endif diff --git a/module_usb_audio/endpoint0/descriptors.h b/module_usb_audio/endpoint0/descriptors.h index ca50bbf3..0ffe3c9b 100644 --- a/module_usb_audio/endpoint0/descriptors.h +++ b/module_usb_audio/endpoint0/descriptors.h @@ -115,7 +115,50 @@ typedef struct STR_TABLE_ENTRY(outputChanStr_18); #endif #if (NUM_USB_CHAN_OUT > 18) -#error NUM_USB_CHAN > 18 + STR_TABLE_ENTRY(outputChanStr_19); +#endif +#if (NUM_USB_CHAN_OUT > 19) + STR_TABLE_ENTRY(outputChanStr_20); +#endif +#if (NUM_USB_CHAN_OUT > 20) + STR_TABLE_ENTRY(outputChanStr_21); +#endif +#if (NUM_USB_CHAN_OUT > 21) + STR_TABLE_ENTRY(outputChanStr_22); +#endif +#if (NUM_USB_CHAN_OUT > 22) + STR_TABLE_ENTRY(outputChanStr_23); +#endif +#if (NUM_USB_CHAN_OUT > 23) + STR_TABLE_ENTRY(outputChanStr_24); +#endif +#if (NUM_USB_CHAN_OUT > 24) + STR_TABLE_ENTRY(outputChanStr_25); +#endif +#if (NUM_USB_CHAN_OUT > 25) + STR_TABLE_ENTRY(outputChanStr_26); +#endif +#if (NUM_USB_CHAN_OUT > 26) + STR_TABLE_ENTRY(outputChanStr_27); +#endif +#if (NUM_USB_CHAN_OUT > 27) + STR_TABLE_ENTRY(outputChanStr_28); +#endif +#if (NUM_USB_CHAN_OUT > 28) + STR_TABLE_ENTRY(outputChanStr_29); +#endif +#if (NUM_USB_CHAN_OUT > 29) + STR_TABLE_ENTRY(outputChanStr_30); +#endif +#if (NUM_USB_CHAN_OUT > 30) + STR_TABLE_ENTRY(outputChanStr_31); +#endif +#if (NUM_USB_CHAN_OUT > 31) + STR_TABLE_ENTRY(outputChanStr_32); +#endif + +#if (NUM_USB_CHAN_OUT > 32) +#error NUM_USB_CHAN > 32 #endif #if (NUM_USB_CHAN_IN > 0) @@ -173,7 +216,50 @@ typedef struct STR_TABLE_ENTRY(inputChanStr_18); #endif #if (NUM_USB_CHAN_IN > 18) -#error NUM_USB_CHAN > 18 + STR_TABLE_ENTRY(inputChanStr_19); +#endif +#if (NUM_USB_CHAN_IN > 19) + STR_TABLE_ENTRY(inputChanStr_20); +#endif +#if (NUM_USB_CHAN_IN > 20) + STR_TABLE_ENTRY(inputChanStr_21); +#endif +#if (NUM_USB_CHAN_IN > 21) + STR_TABLE_ENTRY(inputChanStr_22); +#endif +#if (NUM_USB_CHAN_IN > 22) + STR_TABLE_ENTRY(inputChanStr_23); +#endif +#if (NUM_USB_CHAN_IN > 23) + STR_TABLE_ENTRY(inputChanStr_24); +#endif +#if (NUM_USB_CHAN_IN > 24) + STR_TABLE_ENTRY(inputChanStr_25); +#endif +#if (NUM_USB_CHAN_IN > 25) + STR_TABLE_ENTRY(inputChanStr_26); +#endif +#if (NUM_USB_CHAN_IN > 26) + STR_TABLE_ENTRY(inputChanStr_27); +#endif +#if (NUM_USB_CHAN_IN > 27) + STR_TABLE_ENTRY(inputChanStr_28); +#endif +#if (NUM_USB_CHAN_IN > 28) + STR_TABLE_ENTRY(inputChanStr_29); +#endif +#if (NUM_USB_CHAN_IN > 29) + STR_TABLE_ENTRY(inputChanStr_30); +#endif +#if (NUM_USB_CHAN_IN > 30) + STR_TABLE_ENTRY(inputChanStr_31); +#endif +#if (NUM_USB_CHAN_IN > 31) + STR_TABLE_ENTRY(inputChanStr_32); +#endif + +#if (NUM_USB_CHAN_IN > 32) +#error NUM_USB_CHAN > 32 #endif #if defined(MIXER) && (MAX_MIX_COUNT > 0) @@ -557,7 +643,259 @@ StringDescTable_t g_strTable = #endif #if (NUM_USB_CHAN_OUT > 18) -#error NUM_USB_CHAN_OUT > 18 +#if defined(SPDIF) && (SPDIF_TX_INDEX == 18) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_19 = "Analogue 19/SPDIF 1", + #else + .outputChanStr_19 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 17) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_19 = "Analogue 19/SPDIF 2", + #else + .outputChanStr_19 = "S/PDIF 2", + #endif +#else + .outputChanStr_19 = "Analogue 19", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 19) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 19) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_20 = "Analogue 20/SPDIF 1", + #else + .outputChanStr_20 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 18) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_20 = "Analogue 20/SPDIF 2", + #else + .outputChanStr_20 = "S/PDIF 2", + #endif +#else + .outputChanStr_20 = "Analogue 20", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 20) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 20) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_21 = "Analogue 21/SPDIF 1", + #else + .outputChanStr_21 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 19) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_21 = "Analogue 21/SPDIF 2", + #else + .outputChanStr_21 = "S/PDIF 2", + #endif +#else + .outputChanStr_21 = "Analogue 21", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 21) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 21) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_22 = "Analogue 22/SPDIF 1", + #else + .outputChanStr_22 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 20) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_22 = "Analogue 22/SPDIF 2", + #else + .outputChanStr_22 = "S/PDIF 2", + #endif +#else + .outputChanStr_22 = "Analogue 22", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 22) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 22) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_23 = "Analogue 23/SPDIF 1", + #else + .outputChanStr_23 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 21) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_23 = "Analogue 23/SPDIF 2", + #else + .outputChanStr_23 = "S/PDIF 2", + #endif +#else + .outputChanStr_23 = "Analogue 23", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 23) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 23) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_24 = "Analogue 24/SPDIF 1", + #else + .outputChanStr_24 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 22) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_24 = "Analogue 24/SPDIF 2", + #else + .outputChanStr_24 = "S/PDIF 2", + #endif +#else + .outputChanStr_24 = "Analogue 24", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 24) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 24) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_25 = "Analogue 25/SPDIF 1", + #else + .outputChanStr_25 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 23) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_25 = "Analogue 25/SPDIF 2", + #else + .outputChanStr_25 = "S/PDIF 2", + #endif +#else + .outputChanStr_25 = "Analogue 25", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 25) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 25) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_26 = "Analogue 26/SPDIF 1", + #else + .outputChanStr_26 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 24) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_26 = "Analogue 26/SPDIF 2", + #else + .outputChanStr_26 = "S/PDIF 2", + #endif +#else + .outputChanStr_26 = "Analogue 26", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 26) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 26) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_27 = "Analogue 27/SPDIF 1", + #else + .outputChanStr_27 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 25) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_27 = "Analogue 27/SPDIF 2", + #else + .outputChanStr_27 = "S/PDIF 2", + #endif +#else + .outputChanStr_27 = "Analogue 27", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 27) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 28) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_28 = "Analogue 28/SPDIF 1", + #else + .outputChanStr_28 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 27) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_28 = "Analogue 28/SPDIF 2", + #else + .outputChanStr_28 = "S/PDIF 2", + #endif +#else + .outputChanStr_28 = "Analogue 28", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 28) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 29) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_29 = "Analogue 29/SPDIF 1", + #else + .outputChanStr_29 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 28) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_29 = "Analogue 29/SPDIF 2", + #else + .outputChanStr_29 = "S/PDIF 2", + #endif +#else + .outputChanStr_29 = "Analogue 29", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 29) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 30) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_30 = "Analogue 30/SPDIF 1", + #else + .outputChanStr_30 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 29) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_30 = "Analogue 30/SPDIF 2", + #else + .outputChanStr_30 = "S/PDIF 2", + #endif +#else + .outputChanStr_30 = "Analogue 30", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 30) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 31) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_31 = "Analogue 31/SPDIF 1", + #else + .outputChanStr_31 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 30) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_31 = "Analogue 31/SPDIF 2", + #else + .outputChanStr_31 = "S/PDIF 2", + #endif +#else + .outputChanStr_31 = "Analogue 31", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 31) +#if defined(SPDIF) && (SPDIF_TX_INDEX == 32) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_32 = "Analogue 32/SPDIF 1", + #else + .outputChanStr_32 = "S/PDIF 1", + #endif +#elif defined(SPDIF) && (SPDIF_TX_INDEX == 32) + #if(SPDIF_TX_INDEX < I2S_CHANS_DAC) + .outputChanStr_32 = "Analogue 32/SPDIF 2", + #else + .outputChanStr_32 = "S/PDIF 2", + #endif +#else + .outputChanStr_32 = "Analogue 32", +#endif +#endif + +#if (NUM_USB_CHAN_OUT > 32) +#error NUM_USB_CHAN > 32 #endif /*** INPUT CHANNEL STRINGS ***/ @@ -880,7 +1218,257 @@ StringDescTable_t g_strTable = #endif #if (NUM_USB_CHAN_IN > 18) -#error NUM_USB_CHAN_IN > 18 +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 18) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_19 = "Analogue 19/SPDIF 1", + #else + .inputChanStr_19 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 17) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_19 = "Analogue 19/SPDIF 2", + #else + .inputChanStr_19 = "S/PDIF 2", + #endif +#else + .inputChanStr_19 = "Analogue 19", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 19) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 19) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_20 = "Analogue 20/SPDIF 1", + #else + .inputChanStr_20 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 18) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_20 = "Analogue 20/SPDIF 2", + #else + .inputChanStr_20 = "S/PDIF 2", + #endif +#else + .inputChanStr_20 = "Analogue 20", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 20) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 20) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_21 = "Analogue 21/SPDIF 1", + #else + .inputChanStr_21 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 19) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_21 = "Analogue 21/SPDIF 2", + #else + .inputChanStr_21 = "S/PDIF 2", + #endif +#else + .inputChanStr_21 = "Analogue 21", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 21) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 21) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_22 = "Analogue 22/SPDIF 1", + #else + .inputChanStr_22 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 20) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_22 = "Analogue 22/SPDIF 2", + #else + .inputChanStr_22 = "S/PDIF 2", + #endif +#else + .inputChanStr_22 = "Analogue 22", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 22) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 22) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_23 = "Analogue 23/SPDIF 1", + #else + .inputChanStr_23 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 21) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_23 = "Analogue 23/SPDIF 2", + #else + .inputChanStr_23 = "S/PDIF 2", + #endif +#else + .inputChanStr_23 = "Analogue 23", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 23) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 23) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_24 = "Analogue 24/SPDIF 1", + #else + .inputChanStr_24 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 22) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_24 = "Analogue 24/SPDIF 2", + #else + .inputChanStr_24 = "S/PDIF 2", + #endif +#else + .inputChanStr_24 = "Analogue 24", +#endif +#endif +#if (NUM_USB_CHAN_IN > 24) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 24) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_25 = "Analogue 25/SPDIF 1", + #else + .inputChanStr_25 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 23) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_25 = "Analogue 25/SPDIF 2", + #else + .inputChanStr_25 = "S/PDIF 2", + #endif +#else + .inputChanStr_25 = "Analogue 25", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 25) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 25) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_26 = "Analogue 26/SPDIF 1", + #else + .inputChanStr_26 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 24) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_26 = "Analogue 26/SPDIF 2", + #else + .inputChanStr_26 = "S/PDIF 2", + #endif +#else + .inputChanStr_26 = "Analogue 26", +#endif +#endif +#if (NUM_USB_CHAN_IN > 26) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 26) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_27 = "Analogue 27/SPDIF 1", + #else + .inputChanStr_27 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 25) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_27 = "Analogue 27/SPDIF 2", + #else + .inputChanStr_27 = "S/PDIF 2", + #endif +#else + .inputChanStr_27 = "Analogue 27", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 27) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 27) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_28 = "Analogue 28/SPDIF 1", + #else + .inputChanStr_28 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 26) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_28 = "Analogue 28/SPDIF 2", + #else + .inputChanStr_28 = "S/PDIF 2", + #endif +#else + .inputChanStr_28 = "Analogue 28", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 28) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 28) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_29 = "Analogue 29/SPDIF 1", + #else + .inputChanStr_29 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 27) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_29 = "Analogue 29/SPDIF 2", + #else + .inputChanStr_29 = "S/PDIF 2", + #endif +#else + .inputChanStr_29 = "Analogue 29", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 29) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 29) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_30 = "Analogue 30/SPDIF 1", + #else + .inputChanStr_30 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 28) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_30 = "Analogue 30/SPDIF 2", + #else + .inputChanStr_30 = "S/PDIF 2", + #endif +#else + .inputChanStr_30 = "Analogue 30", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 30) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 30) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_31 = "Analogue 31/SPDIF 1", + #else + .inputChanStr_31 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 29) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_31 = "Analogue 31/SPDIF 2", + #else + .inputChanStr_31 = "S/PDIF 2", + #endif +#else + .inputChanStr_31 = "Analogue 31", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 31) +#if defined(SPDIF_RX) && (SPDIF_RX_INDEX == 31) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_32 = "Analogue 32/SPDIF 1", + #else + .inputChanStr_32 = "S/PDIF 1", + #endif +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 30) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_32 = "Analogue 32/SPDIF 2", + #else + .inputChanStr_32 = "S/PDIF 2", + #endif +#else + .inputChanStr_32 = "Analogue 32", +#endif +#endif + +#if (NUM_USB_CHAN_IN > 32) +#error NUM_USB_CHAN_IN > 32 #endif #if defined(MIXER) && (MAX_MIX_COUNT > 0) @@ -1600,7 +2188,50 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= 0x0000000F, /* bmaControls(18) */ #endif #if (NUM_USB_CHAN_OUT > 18) -#error NUM_USB_CHAN_OUT > 18 + 0x0000000F, /* bmaControls(19) */ +#endif +#if (NUM_USB_CHAN_OUT > 19) + 0x0000000F, /* bmaControls(20) */ +#endif +#if (NUM_USB_CHAN_OUT > 20) + 0x0000000F, /* bmaControls(21) */ +#endif +#if (NUM_USB_CHAN_OUT > 21) + 0x0000000F, /* bmaControls(22) */ +#endif +#if (NUM_USB_CHAN_OUT > 22) + 0x0000000F, /* bmaControls(23) */ +#endif +#if (NUM_USB_CHAN_OUT > 23) + 0x0000000F, /* bmaControls(24) */ +#endif +#if (NUM_USB_CHAN_OUT > 24) + 0x0000000F, /* bmaControls(25) */ +#endif +#if (NUM_USB_CHAN_OUT > 25) + 0x0000000F, /* bmaControls(26) */ +#endif +#if (NUM_USB_CHAN_OUT > 26) + 0x0000000F, /* bmaControls(27) */ +#endif +#if (NUM_USB_CHAN_OUT > 27) + 0x0000000F, /* bmaControls(28) */ +#endif +#if (NUM_USB_CHAN_OUT > 28) + 0x0000000F, /* bmaControls(29) */ +#endif +#if (NUM_USB_CHAN_OUT > 29) + 0x0000000F, /* bmaControls(30) */ +#endif +#if (NUM_USB_CHAN_OUT > 30) + 0x0000000F, /* bmaControls(31) */ +#endif +#if (NUM_USB_CHAN_OUT > 31) + 0x0000000F, /* bmaControls(32) */ +#endif + +#if (NUM_USB_CHAN_OUT > 32) +#error NUM_USB_CHAN_OUT > 32 #endif }, 0, /* 60 iFeature */ @@ -1733,7 +2364,49 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= 0x0000000F, /* bmaControls(18) */ #endif #if (NUM_USB_CHAN_IN > 18) -#error NUM_USB_CHAN_IN > 18 + 0x0000000F, /* bmaControls(19) */ +#endif +#if (NUM_USB_CHAN_IN > 19) + 0x0000000F, /* bmaControls(20) */ +#endif +#if (NUM_USB_CHAN_IN > 20) + 0x0000000F, /* bmaControls(21) */ +#endif +#if (NUM_USB_CHAN_IN > 21) + 0x0000000F, /* bmaControls(22) */ +#endif +#if (NUM_USB_CHAN_IN > 22) + 0x0000000F, /* bmaControls(23) */ +#endif +#if (NUM_USB_CHAN_IN > 23) + 0x0000000F, /* bmaControls(24) */ +#endif +#if (NUM_USB_CHAN_IN > 24) + 0x0000000F, /* bmaControls(25) */ +#endif +#if (NUM_USB_CHAN_IN > 25) + 0x0000000F, /* bmaControls(26) */ +#endif +#if (NUM_USB_CHAN_IN > 26) + 0x0000000F, /* bmaControls(27) */ +#endif +#if (NUM_USB_CHAN_IN > 27) + 0x0000000F, /* bmaControls(28) */ +#endif +#if (NUM_USB_CHAN_IN > 28) + 0x0000000F, /* bmaControls(29) */ +#endif +#if (NUM_USB_CHAN_IN > 29) + 0x0000000F, /* bmaControls(30) */ +#endif +#if (NUM_USB_CHAN_IN > 30) + 0x0000000F, /* bmaControls(31) */ +#endif +#if (NUM_USB_CHAN_IN > 31) + 0x0000000F, /* bmaControls(32) */ +#endif +#if (NUM_USB_CHAN_IN > 32) +#error NUM_USB_CHAN_IN > 32 #endif }, 0, /* 60 iFeature */ diff --git a/module_usb_audio/mixer/mixer.xc b/module_usb_audio/mixer/mixer.xc index 3e7df51d..01147865 100644 --- a/module_usb_audio/mixer/mixer.xc +++ b/module_usb_audio/mixer/mixer.xc @@ -17,10 +17,10 @@ static unsigned int multOut_array[NUM_USB_CHAN_OUT + 1]; static xc_ptr multOut; //#endif -#ifdef IN_VOLUME_IN_MIXER +//#ifdef IN_VOLUME_IN_MIXER static unsigned int multIn_array[NUM_USB_CHAN_IN + 1]; static xc_ptr multIn; -#endif +//#endif #if defined (LEVEL_METER_LEDS) || defined (LEVEL_METER_HOST) static unsigned abs(int x) @@ -36,8 +36,12 @@ static unsigned abs(int x) } #endif -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_array[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1]; /* One larger for an "off" channel for mixer sources" */ + +unsafe +{ + static int volatile * const unsafe ptr_samples = samples_array; +} int savedsamples2[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; @@ -155,7 +159,7 @@ static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) #endif #pragma unsafe arrays -static inline void giveSamplesToHost(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr multIn) +static inline void GiveSamplesToHost(chanend c, xc_ptr ptr, xc_ptr multIn) { #if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) int mult; @@ -164,12 +168,21 @@ static inline void giveSamplesToHost(chanend c, xc_ptr samples, xc_ptr ptr, xc_p #endif #pragma loop unroll - for (int i=0;i 0 read_via_xc_ptr_indexed(index,ptr,i); - read_via_xc_ptr_indexed(sample,samples,index); +#else + index = i + NUM_USB_CHAN_OUT; +#endif + unsafe + { + //read_via_xc_ptr_indexed(sample,samples,index); + sample = ptr_samples[index]; + } #if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) #warning IN Vols in mixer, AFTER mix & map @@ -183,93 +196,108 @@ static inline void giveSamplesToHost(chanend c, xc_ptr samples, xc_ptr ptr, xc_p #else outuint(c,sample); #endif - - } + } } #pragma unsafe arrays -static inline void getSamplesFromHost(chanend c, xc_ptr samples, int base, unsigned underflow) +static inline void GetSamplesFromHost(chanend c, unsigned underflow) { if(!underflow) { #pragma loop unroll - for (int i=0;i samples_from_host_streams[i]) - { - samples_from_host_streams[i] = x; - } + /* Compute peak level data */ + x = abs(sample); + if(x > samples_from_host_streams[i]) + { + samples_from_host_streams[i] = x; + } #endif #if defined(OUT_VOLUME_IN_MIXER) && !defined(OUT_VOLUME_AFTER_MIX) #warning OUT Vols in mixer, BEFORE mix & map - read_via_xc_ptr_indexed(mult, multOut, i); - {h, l} = macs(mult, sample, 0, 0); - h<<=3; + read_via_xc_ptr_indexed(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) + 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 #endif - write_via_xc_ptr_indexed(multOut, index, val); - write_via_xc_ptr_indexed(samples,base+i,h); + write_via_xc_ptr_indexed(multOut, index, val); + write_via_xc_ptr_indexed(samples, i, h); #else - write_via_xc_ptr_indexed(samples,base+i,sample); + ptr_samples[i] = sample; #endif -} } + } + } } #pragma unsafe arrays -static inline void giveSamplesToDevice(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr multOut, unsigned underflow) +static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut, unsigned underflow) { - outuint(c, underflow); if(!underflow) { #pragma loop unroll - for (int i=0;i 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); +#else + unsafe + { + /* Read the actual sample value */ + sample = ptr_samples[i]; + } #endif - int index; - read_via_xc_ptr_indexed(index, ptr, i); - read_via_xc_ptr_indexed(sample, samples, index) #if defined(OUT_VOLUME_IN_MIXER) && defined(OUT_VOLUME_AFTER_MIX) + /* Do volume control processing */ #warning OUT Vols in mixer, AFTER mix & map - read_via_xc_ptr_indexed(mult, multOut, i); - {h, l} = macs(mult, sample, 0, 0); - h<<=3; // Shift used to be done in audio thread but now done here incase of 32bit support + read_via_xc_ptr_indexed(mult, multOut, i); + {h, l} = macs(mult, sample, 0, 0); + h<<=3; // Shift used to be done in audio thread but now done here incase of 32bit support +#error #if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1) - h |= (l >>29)& 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit) + 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 #endif - outuint(c, h); + outuint(c, h); #else - outuint(c, sample); + outuint(c, sample); #endif - } + } } } #pragma unsafe arrays -static inline void getSamplesFromDevice(chanend c, xc_ptr samples, int base) +static inline void GetSamplesFromDevice(chanend c) { #if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX) int mult; @@ -299,13 +327,20 @@ static inline void getSamplesFromDevice(chanend c, xc_ptr samples, int base) #endif #if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX) + /* Read relevant multiplier */ read_via_xc_ptr_indexed(mult, multIn, i); + + /* Do the multiply */ {h, l} = macs(mult, sample, 0, 0); h <<=3; - write_via_xc_ptr_indexed(samples,base+i,h); + write_via_xc_ptr_indexed(samples, NUM_USB_CHAN_OUT+i, h); #else - write_via_xc_ptr_indexed(samples,base+i,sample); -#endif + /* No volume processing */ + unsafe + { + ptr_samples[NUM_USB_CHAN_OUT + i] = sample; + } +#endif } } @@ -319,15 +354,20 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #endif unsigned cmd; + unsigned underflow = 1; + while (1) { #pragma xta endpoint "mixer1_req" /* Request from audio() */ inuint(c_mixer2); - + + GiveSamplesToDevice(c_mixer2, samples_to_device_map, multOut, underflow); + GetSamplesFromDevice(c_mixer2); + /* Request data from decouple thread */ outuint(c_host, 0); - + /* Between request to decouple and respose ~ 400nS latency for interrupt to fire */ select { @@ -377,7 +417,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #endif break; #endif /* if MAX_MIX_COUNT > 0 */ - #ifdef IN_VOLUME_IN_MIXER case SET_MIX_IN_VOL: index = inuint(c_mix_ctl); @@ -464,6 +503,9 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) sampFreq = inuint(c_host); mixer1_mix2_flag = sampFreq > 96000; + /* Wait for request */ + inuint(c_mixer2); + /* Inform mixer2 (or audio()) about freq change */ outct(c_mixer2, command); outuint(c_mixer2, sampFreq); @@ -471,7 +513,11 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) case SET_STREAM_FORMAT_OUT: case SET_STREAM_FORMAT_IN: - /* Inform mixer2 (or audio()) about format change */ + + /* Wait for request */ + inuint(c_mixer2); + + /* Inform mixer2 (or audio()) about format change */ outct(c_mixer2, command); outuint(c_mixer2, inuint(c_host)); outuint(c_mixer2, inuint(c_host)); @@ -482,9 +528,14 @@ 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 0 outuint(c_mixer2, underflow); - giveSamplesToHost(c_host, samples, samples_to_host_map, multIn); + GiveSamplesToHost(c_host, samples, samples_to_host_map, multIn); outuint(c_mixer2, 0); inuint(c_mixer2); @@ -560,10 +611,9 @@ 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, samples_to_device_map, multOut, underflow); - getSamplesFromDevice(c_mixer2, samples, NUM_USB_CHAN_OUT); - giveSamplesToHost(c_host, samples, samples_to_host_map, multIn); - getSamplesFromHost(c_host, samples, 0, underflow); + + GiveSamplesToHost(c_host, samples_to_host_map, multIn); + GetSamplesFromHost(c_host, underflow); #endif } } @@ -707,7 +757,8 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) #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 = 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[])); @@ -725,8 +776,9 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) #endif for (int i=0;i