From c25f6b558948afe0edc0c04d1cde94d90f9a5803 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 31 Oct 2014 10:48:31 +0000 Subject: [PATCH 01/30] Initial removal of samplesInPrev buffer in deliver --- module_usb_audio/audio.xc | 44 ++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 7b1d0891..efa99428 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -32,11 +32,19 @@ 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" -//#pragma xta command "analyse path i2s_output_r i2s_output_l" -//#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 "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) @@ -233,6 +241,7 @@ chanend ?c_adc) #if NUM_USB_CHAN_OUT > 0 if(underflow) { +#pragma xta endpoint "received_underflow" #pragma loop unroll for(int i = 0; i < NUM_USB_CHAN_OUT; i++) { @@ -306,6 +315,7 @@ chanend ?c_adc) #endif if(divide == 1) { +#pragma xta endpoint "divide_1" p_lrclk <: 0 @ tmp; tmp += 100; @@ -331,7 +341,12 @@ chanend ?c_adc) else { clearbuf(p_bclk); - + //for(int i = 0; i < I2S_WIRES_ADC; i++) + // { + // clearbuf(p_i2s_adc[i]); + // asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(32)); + //} + //doI2SClocks(divide); #if (I2S_CHANS_DAC != 0) /* Prefill the ports so data is input in advance */ for(int i = 0; i < I2S_WIRES_DAC; i++) @@ -340,6 +355,7 @@ chanend ?c_adc) } #endif p_lrclk <: 0x7FFFFFFF; + doI2SClocks(divide); } @@ -403,6 +419,7 @@ chanend ?c_adc) if(dsdMode == DSD_MODE_DOP) dsdMode = DSD_MODE_OFF; #endif +#pragma xta endpoint "received_command" return command; } @@ -590,7 +607,9 @@ chanend ?c_adc) /* 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 */ - p_lrclk <: 0x80000000; + //p_lrclk <: 0x80000000; + p_lrclk <: 0x7FFFFFFF; + doI2SClocks(divide); #endif @@ -608,7 +627,7 @@ chanend ?c_adc) samplesIn[i] = bitrev(sample); /* Store the previous left in left */ - samplesIn[i-1] = samplesInPrev[i]; + //samplesIn[i-1] = samplesInPrev[i]; #endif } #endif @@ -653,7 +672,8 @@ chanend ?c_adc) #ifndef CODEC_MASTER /* Clock out data (and LR clock) */ - p_lrclk <: 0x7FFFFFFF; + //p_lrclk <: 0x7FFFFFFF; + p_lrclk <: 0x80000000; doI2SClocks(divide); #endif @@ -662,14 +682,16 @@ chanend ?c_adc) /* Input previous L ADC sample */ index = 0; #pragma loop unroll - for(int i = 1; i < I2S_CHANS_ADC; i += 2) + for(int i = 0; i < I2S_CHANS_ADC; i += 2) { // p_i2s_adc[index++] :> sample; // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); #if NUM_USB_CHAN_IN > 0 - samplesInPrev[i] = bitrev(sample); + //samplesInPrev[i] = bitrev(sample); + samplesIn[i] = bitrev(sample); + #endif } @@ -731,6 +753,8 @@ chanend ?c_adc) } #endif } + +#pragma xta endpoint "deliver_return" return 0; } From 3c34a1c3c0d5b9066731648f6ac4ab0b4db1bc3a Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 6 Nov 2014 23:21:52 +0000 Subject: [PATCH 02/30] Updated I2S init and loop ordering to attempt to fix sample offset --- module_usb_audio/audio.xc | 127 ++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 48 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index efa99428..3a8eaae6 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -340,13 +340,10 @@ chanend ?c_adc) } else { + clearbuf(p_bclk); - //for(int i = 0; i < I2S_WIRES_ADC; i++) - // { - // clearbuf(p_i2s_adc[i]); - // asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(32)); - //} - //doI2SClocks(divide); + // asm("setpt res[%0], %1"::"r"(p_i2s_adc[0]),"r"(64)); +#if 1 #if (I2S_CHANS_DAC != 0) /* Prefill the ports so data is input in advance */ for(int i = 0; i < I2S_WIRES_DAC; i++) @@ -354,10 +351,40 @@ chanend ?c_adc) p_i2s_dac[i] <: 0; } #endif - p_lrclk <: 0x7FFFFFFF; - + p_lrclk <: 0xFFFFFFFF; doI2SClocks(divide); + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] <: 0; + } + p_lrclk <: 0x7FFFFFFF; + doI2SClocks(divide); + +#else + + + for (int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] @ 64 <: 0; + } + + for (int i = 0; i < I2S_WIRES_ADC; i++) + { + asm("setpt res[%0], %1" :: "r"(p_i2s_adc[i]), "r"(63)); + } + + p_lrclk @ 31 <: 0; + + // clocks for previous outputs / inputs + doI2SClocks(divide); + p_lrclk <: 0; + doI2SClocks(divide); + p_lrclk <: 0; + doI2SClocks(divide); + + +#endif } #if (DSD_CHANS_DAC > 0) } /* if (!dsdMode) */ @@ -593,32 +620,11 @@ chanend ?c_adc) #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 */ - //p_lrclk <: 0x80000000; - p_lrclk <: 0x7FFFFFFF; - - doI2SClocks(divide); -#endif - - #if (I2S_CHANS_ADC != 0) /* Input prevous R sample into R in buffer */ index = 0; #pragma loop unroll - for(int i = 1; i < I2S_CHANS_ADC; i += 2) + for(int i = 0; i < I2S_CHANS_ADC; i += 2) { // p_i2s_adc[index++] :> sample; // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) @@ -631,6 +637,30 @@ chanend ?c_adc) #endif } #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 */ + p_lrclk <: 0x80000000; + // p_lrclk <: 0x7FFFFFFF; + +#endif + +#pragma xta endpoint "i2s_output_l" + +#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) + tmp = 0; +#pragma loop unroll + for(int i = 0; i < I2S_CHANS_DAC; i+=2) + { + p_i2s_dac[tmp++] <: bitrev(samplesOut[i]); /* Output RIGHT sample to DAC */ + } +#endif + doI2SClocks(divide); + + + #if defined(SPDIF_RX) || defined(ADAT_RX) /* Sync with clockgen */ inuint(c_dig_rx); @@ -660,29 +690,12 @@ chanend ?c_adc) sample = samplesOut[SPDIF_TX_INDEX + 1]; outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ #endif - tmp = 0; -#pragma xta endpoint "i2s_output_r" -#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) -#pragma loop unroll - for(int i = 1; i < I2S_CHANS_DAC; i+=2) - { - p_i2s_dac[tmp++] <: bitrev(samplesOut[i]); /* Output RIGHT sample to DAC */ - } -#endif - -#ifndef CODEC_MASTER - /* Clock out data (and LR clock) */ - //p_lrclk <: 0x7FFFFFFF; - p_lrclk <: 0x80000000; - doI2SClocks(divide); -#endif - #if (I2S_CHANS_ADC != 0) /* Input previous L ADC sample */ index = 0; #pragma loop unroll - for(int i = 0; i < I2S_CHANS_ADC; i += 2) + for(int i = 1; i < I2S_CHANS_ADC; i += 2) { // p_i2s_adc[index++] :> sample; // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) @@ -706,6 +719,24 @@ chanend ?c_adc) #endif #endif +#ifndef CODEC_MASTER + /* Clock out data (and LR clock) */ + p_lrclk <: 0x7FFFFFFF; + //p_lrclk <: 0x80000000; +#endif + + + tmp = 0; +#pragma xta endpoint "i2s_output_r" +#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) +#pragma loop unroll + for(int i = 1; i < I2S_CHANS_DAC; i+=2) + { + p_i2s_dac[tmp++] <: bitrev(samplesOut[i]); /* Output LEFT sample to DAC */ + } +#endif + doI2SClocks(divide); + } // !dsdMode #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) /* Check for DSD - note we only move into DoP mode if valid DoP Freq */ From 743a4564f67b66603f3fd8f43c14530fa9276894 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 6 Nov 2014 23:57:45 +0000 Subject: [PATCH 03/30] Added DoSampleTransfer() function and updated comments --- module_usb_audio/audio.xc | 489 +++++++++++++++----------------------- 1 file changed, 194 insertions(+), 295 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 3a8eaae6..0d531fc3 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -150,284 +150,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, unsigned samplesOut[], unsigned samplesIn[], 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 xta endpoint "received_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) - { -#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; - - -#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); - // asm("setpt res[%0], %1"::"r"(p_i2s_adc[0]),"r"(64)); -#if 1 -#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 <: 0xFFFFFFFF; - doI2SClocks(divide); - - for(int i = 0; i < I2S_WIRES_DAC; i++) - { - p_i2s_dac[i] <: 0; - } - p_lrclk <: 0x7FFFFFFF; - doI2SClocks(divide); - -#else - - - for (int i = 0; i < I2S_WIRES_DAC; i++) - { - p_i2s_dac[i] @ 64 <: 0; - } - - for (int i = 0; i < I2S_WIRES_ADC; i++) - { - asm("setpt res[%0], %1" :: "r"(p_i2s_adc[i]), "r"(63)); - } - - p_lrclk @ 31 <: 0; - - // clocks for previous outputs / inputs - doI2SClocks(divide); - p_lrclk <: 0; - doI2SClocks(divide); - p_lrclk <: 0; - doI2SClocks(divide); - - -#endif - } -#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)) @@ -509,9 +238,189 @@ chanend ?c_adc) #endif } + return 0; + +} - tmp = 0; + +/* 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 + 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 + +#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_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; + + +#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 + { + /* Initialisation to get DAC buffered i2s ports inline with ADC ports */ +#if (I2S_CHANS_DAC != 0) + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] <: 0; + } +#endif + p_lrclk <: 0xFFFFFFFF; + doI2SClocks(divide); + +#if (I2S_CHANS_DAC != 0) + 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) + { + unsigned command = DoSampleTransfer(c_out, samplesOut, samplesIn, underflowWord); + + if(command) + return command; + #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) if(dsdMode == DSD_MODE_NATIVE) { @@ -621,7 +530,7 @@ chanend ?c_adc) { #if (I2S_CHANS_ADC != 0) - /* Input prevous R sample into R in buffer */ + /* Input previous L sample into L in buffer */ index = 0; #pragma loop unroll for(int i = 0; i < I2S_CHANS_ADC; i += 2) @@ -631,9 +540,6 @@ chanend ?c_adc) asm("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 } #endif @@ -643,24 +549,22 @@ chanend ?c_adc) * after the falling edge on which LRCLK was toggled. (see I2S spec) */ /* Generate clocks LR Clock low - LEFT */ p_lrclk <: 0x80000000; - // p_lrclk <: 0x7FFFFFFF; - #endif #pragma xta endpoint "i2s_output_l" #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) - tmp = 0; + index = 0; #pragma loop unroll for(int i = 0; i < I2S_CHANS_DAC; i+=2) { - p_i2s_dac[tmp++] <: bitrev(samplesOut[i]); /* Output RIGHT sample to DAC */ + p_i2s_dac[index++] <: bitrev(samplesOut[i]); /* Output Left sample to DAC */ } #endif + + /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */ doI2SClocks(divide); - - #if defined(SPDIF_RX) || defined(ADAT_RX) /* Sync with clockgen */ inuint(c_dig_rx); @@ -692,7 +596,7 @@ chanend ?c_adc) #endif #if (I2S_CHANS_ADC != 0) - /* Input previous L ADC sample */ + /* Input previous right ADC sample */ index = 0; #pragma loop unroll for(int i = 1; i < I2S_CHANS_ADC; i += 2) @@ -702,9 +606,7 @@ chanend ?c_adc) asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); #if NUM_USB_CHAN_IN > 0 - //samplesInPrev[i] = bitrev(sample); samplesIn[i] = bitrev(sample); - #endif } @@ -720,19 +622,16 @@ chanend ?c_adc) #endif #ifndef CODEC_MASTER - /* Clock out data (and LR clock) */ p_lrclk <: 0x7FFFFFFF; - //p_lrclk <: 0x80000000; #endif - - tmp = 0; + index = 0; #pragma xta endpoint "i2s_output_r" #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #pragma loop unroll for(int i = 1; i < I2S_CHANS_DAC; i+=2) { - p_i2s_dac[tmp++] <: bitrev(samplesOut[i]); /* Output LEFT sample to DAC */ + p_i2s_dac[index++] <: bitrev(samplesOut[i]); /* Output Right sample to DAC */ } #endif doI2SClocks(divide); From dc84486239d8e5cde51596070d035c44cc63e605 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 7 Nov 2014 10:42:22 +0000 Subject: [PATCH 04/30] Port init pulled out to a function --- module_usb_audio/audio.xc | 132 ++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 0d531fc3..f4f4bde4 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -242,69 +242,9 @@ static inline unsigned DoSampleTransfer(chanend c_out, unsigned samplesOut[], un } - - -/* 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 void InitPorts(unsigned divide) { -#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 - -#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_OFF) @@ -407,12 +347,78 @@ chanend ?c_adc) 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 + 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 + +#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 Date: Fri, 7 Nov 2014 12:24:16 +0000 Subject: [PATCH 05/30] First cut TDM implementation added --- module_usb_audio/audio.xc | 75 ++++++++-- module_usb_audio/devicedefines.h | 10 ++ module_usb_audio/endpoint0/descriptors.h | 175 ++++++++++++++++++++++- 3 files changed, 247 insertions(+), 13 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index f4f4bde4..26155835 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -150,8 +150,12 @@ static inline void doI2SClocks(unsigned divide) } #endif - -static inline unsigned DoSampleTransfer(chanend c_out, unsigned samplesOut[], unsigned samplesIn[], unsigned underflowWord) +#pragma unsafe arrays +static inline unsigned DoSampleTransfer(chanend c_out, unsigned samplesOut[], +#if NUM_USB_CHAN_IN > 0 + unsigned samplesIn[], +#endif +unsigned underflowWord) { unsigned command; unsigned underflow; @@ -373,9 +377,7 @@ chanend ?c_adc) 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; @@ -390,6 +392,8 @@ chanend ?c_adc) #endif unsigned underflowWord = 0; + unsigned tdmCount = 0; + #if NUM_USB_CHAN_IN > 0 for (int i=0;i 0 + samplesIn, +#endif + underflowWord); if(command) { @@ -422,10 +430,17 @@ chanend ?c_adc) /* Main Audio I/O loop */ while (1) { - unsigned command = DoSampleTransfer(c_out, samplesOut, samplesIn, underflowWord); + if(tdmCount == 0) + { + unsigned command = DoSampleTransfer(c_out, samplesOut, +#if NUM_USB_CHAN_IN > 0 + samplesIn, +#endif + underflowWord); - if(command) - return command; + if(command) + return command; + } #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) if(dsdMode == DSD_MODE_NATIVE) @@ -554,7 +569,12 @@ chanend ?c_adc) /* 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; + +#endif #endif #pragma xta endpoint "i2s_output_l" @@ -562,10 +582,17 @@ chanend ?c_adc) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) index = 0; #pragma loop unroll +#ifdef I2S_MODE_TDM + for(int i = 0; i < I2S_CHANS_DAC; i+=8) + { + p_i2s_dac[index++] <: bitrev(samplesOut[(2*tdmCount)+i]); + } +#else for(int i = 0; i < I2S_CHANS_DAC; i+=2) { p_i2s_dac[index++] <: bitrev(samplesOut[i]); /* Output Left sample to DAC */ } +#endif #endif /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */ @@ -628,17 +655,31 @@ chanend ?c_adc) #endif #ifndef CODEC_MASTER +#ifdef I2S_MODE_TDM + if(tdmCount == 3) + 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) #pragma loop unroll +#ifdef I2S_MODE_TDM + for(int i = 0; i < I2S_CHANS_DAC; i+=8) + { + p_i2s_dac[index++] <: bitrev(samplesOut[(2*tdmCount)+1+i]); + } +#else for(int i = 1; i < I2S_CHANS_DAC; i+=2) { p_i2s_dac[index++] <: bitrev(samplesOut[i]); /* Output Right sample to DAC */ } +#endif #endif doI2SClocks(divide); @@ -688,6 +729,13 @@ chanend ?c_adc) } } #endif + +#ifdef I2S_MODE_TDM + tdmCount++; + //tdmCount &= 0b11; /* if(tdmCount == 4) tdmCount = 0) */ + if(tdmCount == 4) + tdmCount = 0; +#endif } #pragma xta endpoint "deliver_return" @@ -746,7 +794,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, @@ -848,7 +895,15 @@ chanend ?c_config, chanend ?c) numBits = 32; } #endif - divide = mClk / ( curSamFreq * numBits ); + unsigned tdmDiv = 1; +#if I2S_MODE_TDM + if(dsdMode == DSD_MODE_OFF) + { + tdmDiv = 4; + } +#endif + + divide = mClk / ( curSamFreq * numBits * tdmDiv); } diff --git a/module_usb_audio/devicedefines.h b/module_usb_audio/devicedefines.h index 60e71691..c37631db 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,13 @@ #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 Max supported sample frequency for device (Hz). Default: 192000 diff --git a/module_usb_audio/endpoint0/descriptors.h b/module_usb_audio/endpoint0/descriptors.h index ca50bbf3..d4675a1d 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) @@ -557,7 +600,115 @@ 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) +#error NUM_USB_CHAN > 24 #endif /*** INPUT CHANNEL STRINGS ***/ @@ -1600,7 +1751,25 @@ 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) +#error NUM_USB_CHAN_OUT > 24 #endif }, 0, /* 60 iFeature */ From c08e4fc5d1878967c2ca527441e65e295afb3735 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 10 Nov 2014 18:36:20 +0000 Subject: [PATCH 06/30] TDM clock div tidied up --- module_usb_audio/audio.xc | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 26155835..5d393c83 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -895,15 +895,7 @@ chanend ?c_config, chanend ?c) numBits = 32; } #endif - unsigned tdmDiv = 1; -#if I2S_MODE_TDM - if(dsdMode == DSD_MODE_OFF) - { - tdmDiv = 4; - } -#endif - - divide = mClk / ( curSamFreq * numBits * tdmDiv); + divide = mClk / ( curSamFreq * numBits); } From 33d2cbd538f17126bfbbb3b126bcb9f84d832c53 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 10 Nov 2014 18:36:38 +0000 Subject: [PATCH 07/30] TDM clock div tidied up --- module_usb_audio/audio.xc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 5d393c83..21f4a69b 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -880,8 +880,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) From 6f0bf1e2e221124eb54bddad3b150bfce35de169 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 10 Nov 2014 18:36:51 +0000 Subject: [PATCH 08/30] First cut TDM input --- module_usb_audio/audio.xc | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 21f4a69b..6ce9fc3f 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -372,10 +372,10 @@ chanend ?c_adc) #if NUM_USB_CHAN_OUT > 0 unsigned samplesOut[NUM_USB_CHAN_OUT]; #endif -#if NUM_USB_CHAN_IN > 0 +//#if NUM_USB_CHAN_IN > 0 unsigned samplesIn[NUM_USB_CHAN_IN]; unsigned samplesInPrev[NUM_USB_CHAN_IN]; -#endif +//#endif unsigned tmp; unsigned index; #ifdef RAMP_CHECK @@ -554,16 +554,22 @@ chanend ?c_adc) /* Input previous L sample into L in buffer */ index = 0; #pragma loop unroll +#ifdef I2S_MODE_TDM + for(int i = 0; i < I2S_CHANS_ADC; i += 8) + { + asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + samplesIn[(2*tdmCount)+i] = bitrev(sample); + } +#else for(int i = 0; i < I2S_CHANS_ADC; i += 2) { // p_i2s_adc[index++] :> sample; // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); -#if NUM_USB_CHAN_IN > 0 samplesIn[i] = bitrev(sample); -#endif } #endif +#endif #ifndef CODEC_MASTER /* LR clock delayed by one clock, This is so MSB is output on the falling edge of BCLK @@ -632,16 +638,21 @@ chanend ?c_adc) /* Input previous right ADC sample */ index = 0; #pragma loop unroll +#ifdef I2S_MODE_TDM + for(int i = 1; i < I2S_CHANS_ADC; i += 8) + { + asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + samplesIn[(2*tdmCount)+i] = bitrev(sample); + } +#else for(int i = 1; i < I2S_CHANS_ADC; i += 2) { // p_i2s_adc[index++] :> sample; // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - -#if NUM_USB_CHAN_IN > 0 samplesIn[i] = bitrev(sample); -#endif } +#endif #ifdef SU1_ADC_ENABLE { From ea00ff49f360871d084580e46e8cedcd4438a879 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 10 Nov 2014 18:37:10 +0000 Subject: [PATCH 09/30] Tmp disabled volume in mixer --- module_usb_audio/devicedefines.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module_usb_audio/devicedefines.h b/module_usb_audio/devicedefines.h index c37631db..7ca77aff 100644 --- a/module_usb_audio/devicedefines.h +++ b/module_usb_audio/devicedefines.h @@ -985,7 +985,7 @@ #else #if defined(MIXER) // Enabled by default -#define OUT_VOLUME_IN_MIXER +//#define OUT_VOLUME_IN_MIXER #endif #endif @@ -1005,7 +1005,7 @@ #else #if defined(MIXER) /* Enabled by default */ -#define IN_VOLUME_IN_MIXER +//#define IN_VOLUME_IN_MIXER #endif #endif From 4854ea8f4d62e954aca85b7828fc6da9bfa3dfd6 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 10 Nov 2014 18:37:34 +0000 Subject: [PATCH 10/30] Added descriptors for larger channel counts --- module_usb_audio/endpoint0/descriptors.h | 173 ++++++++++++++++++++++- 1 file changed, 171 insertions(+), 2 deletions(-) diff --git a/module_usb_audio/endpoint0/descriptors.h b/module_usb_audio/endpoint0/descriptors.h index d4675a1d..8d35139c 100644 --- a/module_usb_audio/endpoint0/descriptors.h +++ b/module_usb_audio/endpoint0/descriptors.h @@ -708,7 +708,151 @@ StringDescTable_t g_strTable = #endif #if (NUM_USB_CHAN_OUT > 24) -#error NUM_USB_CHAN > 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 ***/ @@ -1769,7 +1913,32 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= 0x0000000F, /* bmaControls(24) */ #endif #if (NUM_USB_CHAN_OUT > 24) -#error 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 */ From a97d5f3e575bce185e7bf86c5e813cc8271b2fa8 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 10 Nov 2014 18:37:52 +0000 Subject: [PATCH 11/30] Comment in mixer only --- module_usb_audio/mixer/mixer.xc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module_usb_audio/mixer/mixer.xc b/module_usb_audio/mixer/mixer.xc index 3e7df51d..574e6f42 100644 --- a/module_usb_audio/mixer/mixer.xc +++ b/module_usb_audio/mixer/mixer.xc @@ -248,7 +248,11 @@ static inline void giveSamplesToDevice(chanend c, xc_ptr samples, xc_ptr ptr, xc unsigned l; #endif int index; + + /* 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) #if defined(OUT_VOLUME_IN_MIXER) && defined(OUT_VOLUME_AFTER_MIX) From 08cba47cb594b69afadda0c443f0c38d6d0fa189 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Mon, 10 Nov 2014 18:38:22 +0000 Subject: [PATCH 12/30] Fixed mixer build issue when IN_VOLUME_IN_MIXER not set --- module_usb_audio/mixer/mixer.xc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module_usb_audio/mixer/mixer.xc b/module_usb_audio/mixer/mixer.xc index 574e6f42..def1583a 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) From c82ddb5726a64356f52e543b5a3aa6da558fdb73 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 13 Nov 2014 15:51:10 +0000 Subject: [PATCH 13/30] LRClk startup a bit nicer (was double high) --- module_usb_audio/audio.xc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 6ce9fc3f..c5550e8c 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -307,7 +307,7 @@ static inline void InitPorts(unsigned divide) p_i2s_dac[i] <: 0; } #endif - p_lrclk <: 0xFFFFFFFF; + p_lrclk <: 0x0; doI2SClocks(divide); #if (I2S_CHANS_DAC != 0) From 2b85adc01d9ffa4e6c1d7d291db95cf1214d11de Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Wed, 19 Nov 2014 14:39:07 +0000 Subject: [PATCH 14/30] Simple TDM buffer added to sort channel delay issue. --- module_usb_audio/audio.xc | 151 +++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index c5550e8c..0b32d1c2 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -22,6 +22,8 @@ #include "commands.h" #include "xc_ptr.h" + + unsigned testsamples[100]; int p = 0; unsigned lastSample = 0; @@ -300,8 +302,8 @@ static inline void InitPorts(unsigned divide) } else { - /* Initialisation to get DAC buffered i2s ports inline with ADC ports */ #if (I2S_CHANS_DAC != 0) + /* Pre-fill the DAC ports */ for(int i = 0; i < I2S_WIRES_DAC; i++) { p_i2s_dac[i] <: 0; @@ -309,15 +311,6 @@ static inline void InitPorts(unsigned divide) #endif p_lrclk <: 0x0; doI2SClocks(divide); - -#if (I2S_CHANS_DAC != 0) - 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) */ @@ -374,7 +367,7 @@ chanend ?c_adc) #endif //#if NUM_USB_CHAN_IN > 0 unsigned samplesIn[NUM_USB_CHAN_IN]; - unsigned samplesInPrev[NUM_USB_CHAN_IN]; + unsigned samplesInPrev[NUM_USB_CHAN_IN]; /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ //#endif unsigned tmp; unsigned index; @@ -395,6 +388,7 @@ chanend ?c_adc) unsigned tdmCount = 0; #if NUM_USB_CHAN_IN > 0 + /* Initialise buffers to 0 */ for (int i=0;i sample; - // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) - asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[i] = bitrev(sample); - } -#endif -#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) */ @@ -600,10 +575,48 @@ chanend ?c_adc) } #endif #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; +#pragma loop unroll +#ifdef I2S_MODE_TDM + if(tdmCount == 0) + { + for(int i = 0; i < I2S_CHANS_ADC; i += 8) + { + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + samplesIn[7] = bitrev(sample); + } + for(int i = 0; i< 7; i++) + { + samplesIn[i] = samplesInPrev[i]; + } + } + else + { + for(int i = 0; i < I2S_CHANS_ADC; i += 8) + { + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + samplesInPrev[(2*tdmCount)+i-1] = bitrev(sample); + } + } +#else + for(int i = 0; i < I2S_CHANS_ADC; i += 2) + { + // 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++])); + + samplesIn[i] = bitrev(sample); + samplesIn[i-1] = samplesInPrev[i]; + } +#endif +#endif + + #if defined(SPDIF_RX) || defined(ADAT_RX) /* Sync with clockgen */ inuint(c_dig_rx); @@ -634,43 +647,12 @@ chanend ?c_adc) outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ #endif -#if (I2S_CHANS_ADC != 0) - /* Input previous right ADC sample */ - index = 0; -#pragma loop unroll -#ifdef I2S_MODE_TDM - for(int i = 1; i < I2S_CHANS_ADC; i += 8) - { - asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[(2*tdmCount)+i] = bitrev(sample); - } -#else - for(int i = 1; i < I2S_CHANS_ADC; i += 2) - { - // p_i2s_adc[index++] :> sample; - // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) - asm("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[i] = bitrev(sample); - } -#endif - -#ifdef SU1_ADC_ENABLE - { - unsigned x; - - x = inuint(c_adc); - inct(c_adc); - asm("stw %0, dp[g_adcVal]"::"r"(x)); - } -#endif -#endif - #ifndef CODEC_MASTER #ifdef I2S_MODE_TDM if(tdmCount == 3) p_lrclk <: 0x80000000; else - p_lrclk <: 0x00000000; + p_lrclk <: 0x00000000; #else p_lrclk <: 0x7FFFFFFF; #endif @@ -692,8 +674,43 @@ chanend ?c_adc) } #endif #endif + doI2SClocks(divide); +#if (I2S_CHANS_ADC != 0) + /* Input previous right ADC sample */ + index = 0; +#pragma loop unroll +#ifdef I2S_MODE_TDM + for(int i = 0; i < I2S_CHANS_ADC; i += 8) + { + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + //samplesIn[(2*tdmCount)+i+1] = bitrev(sample); + samplesInPrev[2*tdmCount+i] = bitrev(sample); + } +#else + for(int i = 0; i < I2S_CHANS_ADC; i += 2) + { + // 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++])); + samplesInPrev[i] = bitrev(sample); + } +#endif + +#ifdef SU1_ADC_ENABLE + { + unsigned x; + + x = inuint(c_adc); + inct(c_adc); + asm("stw %0, dp[g_adcVal]"::"r"(x)); + } +#endif +#endif + + + } // !dsdMode #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) /* Check for DSD - note we only move into DoP mode if valid DoP Freq */ @@ -745,7 +762,9 @@ chanend ?c_adc) tdmCount++; //tdmCount &= 0b11; /* if(tdmCount == 4) tdmCount = 0) */ if(tdmCount == 4) + { //while(1); tdmCount = 0; + } #endif } From 8d6ef4d1d44c682926c281d39330b94fb6a0728d Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Wed, 19 Nov 2014 15:52:37 +0000 Subject: [PATCH 15/30] Simplified TDM buffer to reduce copying. --- module_usb_audio/audio.xc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 0b32d1c2..56f20907 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -585,14 +585,12 @@ chanend ?c_adc) #ifdef I2S_MODE_TDM if(tdmCount == 0) { + /* First time around we get channel 7 of TDM8 */ for(int i = 0; i < I2S_CHANS_ADC; i += 8) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[7] = bitrev(sample); - } - for(int i = 0; i< 7; i++) - { - samplesIn[i] = samplesInPrev[i]; + samplesIn[7] = samplesInPrev[7]; + samplesInPrev[7] = bitrev(sample); } } else @@ -600,7 +598,7 @@ chanend ?c_adc) for(int i = 0; i < I2S_CHANS_ADC; i += 8) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesInPrev[(2*tdmCount)+i-1] = bitrev(sample); + samplesIn[(2*tdmCount)+i-1] = bitrev(sample); // channels 1, 3, 5.. on each line. } } #else @@ -686,7 +684,7 @@ chanend ?c_adc) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); //samplesIn[(2*tdmCount)+i+1] = bitrev(sample); - samplesInPrev[2*tdmCount+i] = bitrev(sample); + samplesIn[2*tdmCount+i] = bitrev(sample); // Channels 0, 2, 4.. on each line. } #else for(int i = 0; i < I2S_CHANS_ADC; i += 2) From d26f4788351fe2d9bcbb9740fcf0270bfb414698 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Wed, 19 Nov 2014 18:03:53 +0000 Subject: [PATCH 16/30] Introduced second input buffer to take up sample delay on last TDM channel. --- module_usb_audio/audio.xc | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 56f20907..fab21502 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -366,8 +366,10 @@ chanend ?c_adc) 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]; /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ + //unsigned samplesIn[NUM_USB_CHAN_IN]; + unsigned samplesIn[2][NUM_USB_CHAN_IN]; + unsigned readBuffNo = 0; + //unsigned samplesInPrev[NUM_USB_CHAN_IN]; /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ //#endif unsigned tmp; unsigned index; @@ -391,8 +393,9 @@ chanend ?c_adc) /* Initialise buffers to 0 */ for (int i=0;i 0 - samplesIn, + samplesIn[0], #endif underflowWord); @@ -426,17 +429,7 @@ chanend ?c_adc) /* Main Audio I/O loop */ while (1) { - if(tdmCount == 0) - { - unsigned command = DoSampleTransfer(c_out, samplesOut, -#if NUM_USB_CHAN_IN > 0 - samplesIn, -#endif - underflowWord); - - if(command) - return command; - } + #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) if(dsdMode == DSD_MODE_NATIVE) @@ -589,8 +582,7 @@ chanend ?c_adc) for(int i = 0; i < I2S_CHANS_ADC; i += 8) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[7] = samplesInPrev[7]; - samplesInPrev[7] = bitrev(sample); + samplesIn[readBuffNo][7] = bitrev(sample); } } else @@ -598,13 +590,12 @@ chanend ?c_adc) for(int i = 0; i < I2S_CHANS_ADC; i += 8) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[(2*tdmCount)+i-1] = bitrev(sample); // channels 1, 3, 5.. on each line. + samplesIn[!readBuffNo][(2*tdmCount)+i-1] = bitrev(sample); // channels 1, 3, 5.. on each line. } } #else for(int i = 0; i < I2S_CHANS_ADC; i += 2) { - // 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++])); @@ -684,7 +675,7 @@ chanend ?c_adc) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); //samplesIn[(2*tdmCount)+i+1] = bitrev(sample); - samplesIn[2*tdmCount+i] = bitrev(sample); // Channels 0, 2, 4.. on each line. + samplesIn[!readBuffNo][2*tdmCount+i] = bitrev(sample); // Channels 0, 2, 4.. on each line. } #else for(int i = 0; i < I2S_CHANS_ADC; i += 2) @@ -755,15 +746,24 @@ chanend ?c_adc) } } #endif - + #ifdef I2S_MODE_TDM - tdmCount++; - //tdmCount &= 0b11; /* if(tdmCount == 4) tdmCount = 0) */ - if(tdmCount == 4) - { //while(1); - tdmCount = 0; - } + tdmCount++; + if(tdmCount == 4) #endif + { + unsigned command = DoSampleTransfer(c_out, samplesOut, +#if NUM_USB_CHAN_IN > 0 + samplesIn[readBuffNo], +#endif + underflowWord); + + if(command) + return command; + + tdmCount = 0; + readBuffNo = !readBuffNo; + } } #pragma xta endpoint "deliver_return" From 69f8e83cc712f4477a2188a41fa0649bf41f7b56 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 20 Nov 2014 17:28:48 +0000 Subject: [PATCH 17/30] TDM code made a bit more generic. Fixed issue with multiple TDM input lines missing channels. --- module_usb_audio/audio.xc | 83 ++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index fab21502..17cfc2c2 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -23,6 +23,13 @@ #include "xc_ptr.h" +#ifdef I2S_MODE_TDM +#define I2S_CHANS_PER_FRAME 8 +#else +#error +#define I2S_CHANS_PER_FRAME 2 +#endif + unsigned testsamples[100]; int p = 0; @@ -300,7 +307,7 @@ static inline void InitPorts(unsigned divide) } #endif } - else + else /* Divide != 1 */ { #if (I2S_CHANS_DAC != 0) /* Pre-fill the DAC ports */ @@ -309,8 +316,11 @@ static inline void InitPorts(unsigned divide) 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) */ @@ -345,7 +355,6 @@ static inline void InitPorts(unsigned divide) } #endif #endif - } @@ -366,13 +375,13 @@ chanend ?c_adc) unsigned samplesOut[NUM_USB_CHAN_OUT]; #endif //#if NUM_USB_CHAN_IN > 0 - //unsigned samplesIn[NUM_USB_CHAN_IN]; + /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ unsigned samplesIn[2][NUM_USB_CHAN_IN]; unsigned readBuffNo = 0; - //unsigned samplesInPrev[NUM_USB_CHAN_IN]; /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ //#endif unsigned tmp; unsigned index; + #ifdef RAMP_CHECK unsigned prev=0; int started = 0; @@ -387,13 +396,12 @@ chanend ?c_adc) #endif unsigned underflowWord = 0; - unsigned tdmCount = 0; + unsigned frameCount = 0; #if NUM_USB_CHAN_IN > 0 - /* Initialise buffers to 0 */ + /* Initialise input buffers. Note two buffers due to offset between ADC and DAC ports */ for (int i=0;i 0) if(dsdMode == DSD_MODE_NATIVE) @@ -559,7 +566,7 @@ chanend ?c_adc) #ifdef I2S_MODE_TDM for(int i = 0; i < I2S_CHANS_DAC; i+=8) { - p_i2s_dac[index++] <: bitrev(samplesOut[(2*tdmCount)+i]); + p_i2s_dac[index++] <: bitrev(samplesOut[(frameCount)+i]); } #else for(int i = 0; i < I2S_CHANS_DAC; i+=2) @@ -576,29 +583,22 @@ chanend ?c_adc) index = 0; #pragma loop unroll #ifdef I2S_MODE_TDM - if(tdmCount == 0) + /* First input (i.e. frameCoint == 0) we read last ADC channel of previous frame.. */ + unsigned buffIndex = frameCount ? !readBuffNo : readBuffNo; + + /* First time around we get channel 7 of TDM8 */ + for(int i = 0; i < I2S_CHANS_ADC; i+=I2S_CHANS_PER_FRAME) { - /* First time around we get channel 7 of TDM8 */ - for(int i = 0; i < I2S_CHANS_ADC; i += 8) - { - asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[readBuffNo][7] = bitrev(sample); - } - } - else - { - for(int i = 0; i < I2S_CHANS_ADC; i += 8) - { - asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[!readBuffNo][(2*tdmCount)+i-1] = bitrev(sample); // channels 1, 3, 5.. on each line. - } + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + + /* Note the use of readBuffNo changes based on frameCount */ + samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line. } #else for(int i = 0; i < I2S_CHANS_ADC; i += 2) { - // 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++])); - samplesIn[i] = bitrev(sample); samplesIn[i-1] = samplesInPrev[i]; } @@ -638,7 +638,7 @@ chanend ?c_adc) #ifndef CODEC_MASTER #ifdef I2S_MODE_TDM - if(tdmCount == 3) + if(frameCount == (I2S_CHANS_PER_FRAME-2)) p_lrclk <: 0x80000000; else p_lrclk <: 0x00000000; @@ -652,9 +652,9 @@ chanend ?c_adc) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #pragma loop unroll #ifdef I2S_MODE_TDM - for(int i = 0; i < I2S_CHANS_DAC; i+=8) + for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) { - p_i2s_dac[index++] <: bitrev(samplesOut[(2*tdmCount)+1+i]); + p_i2s_dac[index++] <: bitrev(samplesOut[frameCount+1+i]); } #else for(int i = 1; i < I2S_CHANS_DAC; i+=2) @@ -667,21 +667,20 @@ chanend ?c_adc) doI2SClocks(divide); #if (I2S_CHANS_ADC != 0) - /* Input previous right ADC sample */ index = 0; #pragma loop unroll #ifdef I2S_MODE_TDM - for(int i = 0; i < I2S_CHANS_ADC; i += 8) + /* Channels 0, 2, 4.. on each line */ + for(int i = 0; i < I2S_CHANS_ADC; i += I2S_CHANS_PER_FRAME) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - //samplesIn[(2*tdmCount)+i+1] = bitrev(sample); - samplesIn[!readBuffNo][2*tdmCount+i] = bitrev(sample); // Channels 0, 2, 4.. on each line. + samplesIn[!readBuffNo][frameCount+i] = bitrev(sample); } #else + /* Input previous right ADC sample */ for(int i = 0; i < I2S_CHANS_ADC; i += 2) { - // 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++])); samplesInPrev[i] = bitrev(sample); } @@ -690,7 +689,6 @@ chanend ?c_adc) #ifdef SU1_ADC_ENABLE { unsigned x; - x = inuint(c_adc); inct(c_adc); asm("stw %0, dp[g_adcVal]"::"r"(x)); @@ -748,10 +746,12 @@ chanend ?c_adc) #endif #ifdef I2S_MODE_TDM - tdmCount++; - if(tdmCount == 4) + /* 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 */ unsigned command = DoSampleTransfer(c_out, samplesOut, #if NUM_USB_CHAN_IN > 0 samplesIn[readBuffNo], @@ -759,9 +759,12 @@ chanend ?c_adc) underflowWord); if(command) + { return command; - - tdmCount = 0; + } + + /* Reset frame counter and flip the ADC buffer */ + frameCount = 0; readBuffNo = !readBuffNo; } } From 525a9059397cd83be5532c66a3f0e5926f69bf10 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 20 Nov 2014 17:29:36 +0000 Subject: [PATCH 18/30] Required descriptor changes for input channel counts over 18 (now handles up to 32) --- module_usb_audio/endpoint0/descriptors.h | 200 ++++++++++++++++++++++- 1 file changed, 197 insertions(+), 3 deletions(-) diff --git a/module_usb_audio/endpoint0/descriptors.h b/module_usb_audio/endpoint0/descriptors.h index 8d35139c..f4063baa 100644 --- a/module_usb_audio/endpoint0/descriptors.h +++ b/module_usb_audio/endpoint0/descriptors.h @@ -216,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) @@ -1175,7 +1218,116 @@ 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 == 21) + #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) + .inputChanStr_24 = "Analogue 25/SPDIF 2", + #else + .inputChanStr_24 = "S/PDIF 2", + #endif +#else + .inputChanStr_24 = "Analogue 24", +#endif +#endif + + +#if (NUM_USB_CHAN_IN > 24) +#error NUM_USB_CHAN_IN > 24 #endif #if defined(MIXER) && (MAX_MIX_COUNT > 0) @@ -2071,7 +2223,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 */ From 2576a0e8a4b148e9d5b8e56570b310245256f814 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 25 Nov 2014 18:23:46 +0000 Subject: [PATCH 19/30] Added iput channel descriptors for > 24 < 32 channels. --- module_usb_audio/endpoint0/descriptors.h | 151 ++++++++++++++++++++++- 1 file changed, 146 insertions(+), 5 deletions(-) diff --git a/module_usb_audio/endpoint0/descriptors.h b/module_usb_audio/endpoint0/descriptors.h index f4063baa..0ffe3c9b 100644 --- a/module_usb_audio/endpoint0/descriptors.h +++ b/module_usb_audio/endpoint0/descriptors.h @@ -1314,9 +1314,9 @@ StringDescTable_t g_strTable = #else .inputChanStr_24 = "S/PDIF 1", #endif -#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 21) +#elif defined(SPDIF_RX) && (SPDIF_RX_INDEX == 22) #if(SPDIF_RX_INDEX < I2S_CHANS_ADC) - .inputChanStr_24 = "Analogue 25/SPDIF 2", + .inputChanStr_24 = "Analogue 24/SPDIF 2", #else .inputChanStr_24 = "S/PDIF 2", #endif @@ -1324,10 +1324,151 @@ StringDescTable_t g_strTable = .inputChanStr_24 = "Analogue 24", #endif #endif - - #if (NUM_USB_CHAN_IN > 24) -#error 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) From 36d0fec21aaf5a385fa13005f7522d12e9c45a9e Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 25 Nov 2014 18:24:09 +0000 Subject: [PATCH 20/30] Added -always-inline to module_usb_audio build info --- module_usb_audio/module_build_info | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module_usb_audio/module_build_info b/module_usb_audio/module_build_info index 4705b9d2..2872a33f 100644 --- a/module_usb_audio/module_build_info +++ b/module_usb_audio/module_build_info @@ -18,15 +18,15 @@ # # $(call SET_XCC_C_FLAGS, mydir1 mydir2, $(XCC_FLAGS) -g -O3) - # You can change the flags of an individual file by setting the # XCC_FLAGS_[filename] variable. e.g. # # XCC_FLAGS_myfile.xc = $(XCC_FLAGS) -fsubword-select - # You can exclude particular files from the build even if they occur # within SOURCE_DIRS by adding the file name (with no path) to the # EXCLUDE_FILES variable e..g # EXCLUDE_FILES += descriptors_2.rst + +MODULE_XCC_FLAGS += $(XCC_FLAGS) -falways-inline From c05e1f05c29b21c73ca87f98da0e0a241b353037 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 25 Nov 2014 18:24:29 +0000 Subject: [PATCH 21/30] Whitespace only. --- module_usb_audio/usb_buffer/xc_ptr.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/module_usb_audio/usb_buffer/xc_ptr.h b/module_usb_audio/usb_buffer/xc_ptr.h index 40d64f0c..b2be0b3d 100644 --- a/module_usb_audio/usb_buffer/xc_ptr.h +++ b/module_usb_audio/usb_buffer/xc_ptr.h @@ -9,12 +9,11 @@ typedef unsigned int xc_ptr; // the xc_ptr) inline xc_ptr array_to_xc_ptr(const unsigned a[]) { - xc_ptr x; - asm("mov %0, %1":"=r"(x):"r"(a)); - return x; + xc_ptr x; + asm("mov %0, %1":"=r"(x):"r"(a)); + return x; } - #define write_via_xc_ptr_indexed(p,i,x) asm volatile("stw %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) #define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) #define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) From 3ffbc9945615103b34c8b533cd024c760e831703 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 27 Nov 2014 12:44:39 +0000 Subject: [PATCH 22/30] DoSampleTransfer now takes readBuffNo rather than actual buffer. Now two separate In buffers (was 2D array). Attempts to help compiler. --- module_usb_audio/audio.xc | 70 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 17cfc2c2..26c532bd 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -23,6 +23,12 @@ #include "xc_ptr.h" +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[NUM_USB_CHAN_IN]; + #ifdef I2S_MODE_TDM #define I2S_CHANS_PER_FRAME 8 #else @@ -160,11 +166,7 @@ static inline void doI2SClocks(unsigned divide) #endif #pragma unsafe arrays -static inline unsigned DoSampleTransfer(chanend c_out, unsigned samplesOut[], -#if NUM_USB_CHAN_IN > 0 - unsigned samplesIn[], -#endif -unsigned underflowWord) +static inline unsigned DoSampleTransfer(chanend c_out, int readBuffNo, unsigned underflowWord) { unsigned command; unsigned underflow; @@ -245,7 +247,10 @@ unsigned underflowWord) #pragma loop unroll for(int i = 0; i < NUM_USB_CHAN_IN; i++) { - outuint(c_out, samplesIn[i]); + if(readBuffNo) + outuint(c_out, samplesIn_1[i]); + else + outuint(c_out, samplesIn_0[i]); } #endif #endif @@ -372,11 +377,9 @@ chanend ?c_adc) #endif unsigned underflow = 0; #if NUM_USB_CHAN_OUT > 0 - unsigned samplesOut[NUM_USB_CHAN_OUT]; #endif //#if NUM_USB_CHAN_IN > 0 /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ - unsigned samplesIn[2][NUM_USB_CHAN_IN]; unsigned readBuffNo = 0; //#endif unsigned tmp; @@ -398,15 +401,6 @@ chanend ?c_adc) unsigned frameCount = 0; -#if NUM_USB_CHAN_IN > 0 - /* Initialise input buffers. Note two buffers due to offset between ADC and DAC ports */ - for (int i=0;i 0 - samplesIn[0], -#endif - underflowWord); +#if 1 + unsigned command = DoSampleTransfer(c_out, readBuffNo, underflowWord); if(command) { return command; } +#endif InitPorts(divide); @@ -545,7 +537,6 @@ chanend ?c_adc) else #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) */ @@ -575,26 +566,30 @@ chanend ?c_adc) } #endif #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; -#pragma loop unroll #ifdef I2S_MODE_TDM /* 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) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); /* Note the use of readBuffNo changes based on frameCount */ - samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line. + 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. } #else +#pragma loop unroll for(int i = 0; i < I2S_CHANS_ADC; i += 2) { /* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */ @@ -635,6 +630,8 @@ chanend ?c_adc) sample = samplesOut[SPDIF_TX_INDEX + 1]; outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ #endif + + #ifndef CODEC_MASTER #ifdef I2S_MODE_TDM @@ -668,13 +665,16 @@ chanend ?c_adc) #if (I2S_CHANS_ADC != 0) index = 0; -#pragma loop unroll #ifdef I2S_MODE_TDM /* Channels 0, 2, 4.. on each line */ + #pragma loop unroll for(int i = 0; i < I2S_CHANS_ADC; i += I2S_CHANS_PER_FRAME) { asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - samplesIn[!readBuffNo][frameCount+i] = bitrev(sample); + if(readBuffNo) + samplesIn_0[frameCount+i] = bitrev(sample); + else + samplesIn_1[frameCount+i] = bitrev(sample); } #else /* Input previous right ADC sample */ @@ -696,8 +696,6 @@ chanend ?c_adc) #endif #endif - - } // !dsdMode #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) /* Check for DSD - note we only move into DoP mode if valid DoP Freq */ @@ -752,11 +750,13 @@ chanend ?c_adc) #endif { /* Do samples transfer */ - unsigned command = DoSampleTransfer(c_out, samplesOut, -#if NUM_USB_CHAN_IN > 0 - samplesIn[readBuffNo], -#endif - underflowWord); + /* 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) { From dbbeddff0333142cae30a0ae14f0e8b4426c0377 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 27 Nov 2014 12:44:54 +0000 Subject: [PATCH 23/30] Removed unused debug vars --- module_usb_audio/audio.xc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 26c532bd..f5c9fc58 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -36,10 +36,6 @@ static unsigned samplesIn_1[NUM_USB_CHAN_IN]; #define I2S_CHANS_PER_FRAME 2 #endif - -unsigned testsamples[100]; -int p = 0; -unsigned lastSample = 0; #if (DSD_CHANS_DAC != 0) extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC]; extern buffered out port:32 p_dsd_clk; From 5b4a6f9e94d6ff021052577586c8c5a3978c07f1 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 27 Nov 2014 12:50:38 +0000 Subject: [PATCH 24/30] Mix map disabled when MAX_MIX_COUNT is 0. Started to change code to using XC unsafe pointers rather than xc_ptr.h. This results in nice speed up since compiler uses ldw with intermediate addressing from DP - saves a lot of processing in the loops. --- module_usb_audio/mixer/mixer.xc | 188 ++++++++++++++++++++------------ 1 file changed, 118 insertions(+), 70 deletions(-) diff --git a/module_usb_audio/mixer/mixer.xc b/module_usb_audio/mixer/mixer.xc index def1583a..01147865 100644 --- a/module_usb_audio/mixer/mixer.xc +++ b/module_usb_audio/mixer/mixer.xc @@ -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,97 +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 #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; @@ -303,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 } } @@ -323,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 { @@ -381,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); @@ -468,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); @@ -475,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)); @@ -486,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); @@ -564,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 } } @@ -711,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[])); @@ -729,8 +776,9 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) #endif for (int i=0;i Date: Thu, 27 Nov 2014 17:57:28 +0000 Subject: [PATCH 25/30] Digital RX channels sent over in a separate loop in DoSampleTransfer(). Only I2S channels double buffered. --- module_usb_audio/audio.xc | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index f5c9fc58..c3936495 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -241,13 +241,19 @@ static inline unsigned DoSampleTransfer(chanend c_out, int readBuffNo, unsigned #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++) { 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 } @@ -598,23 +604,25 @@ chanend ?c_adc) #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) From 673946b028da6d30f5794ef259626e3e7a8787de Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 27 Nov 2014 17:58:07 +0000 Subject: [PATCH 26/30] Standard I2S mode up and running again. Still needs more generalisation. --- module_usb_audio/audio.xc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index c3936495..a25a0acf 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -27,12 +27,11 @@ 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[NUM_USB_CHAN_IN]; +static unsigned samplesIn_1[I2S_CHANS_ADC]; #ifdef I2S_MODE_TDM #define I2S_CHANS_PER_FRAME 8 #else -#error #define I2S_CHANS_PER_FRAME 2 #endif @@ -575,9 +574,9 @@ chanend ?c_adc) #if (I2S_CHANS_ADC != 0) /* Input previous L sample into L in buffer */ index = 0; -#ifdef I2S_MODE_TDM /* First input (i.e. frameCoint == 0) we read last ADC channel of previous frame.. */ unsigned buffIndex = frameCount ? !readBuffNo : readBuffNo; +#ifdef I2S_MODE_TDM #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) @@ -592,12 +591,17 @@ chanend ?c_adc) } #else #pragma loop unroll - for(int i = 0; i < I2S_CHANS_ADC; i += 2) + for(int i = 0; i < I2S_CHANS_ADC; i += 2) // TODO I2S_CHANS_PER_FRAME { /* 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++])); - samplesIn[i] = bitrev(sample); - samplesIn[i-1] = samplesInPrev[i]; + + 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. + // samplesIn_1[i] = bitrev(sample); + // samplesIn[i-1] = samplesInPrev[i]; } #endif #endif @@ -686,7 +690,13 @@ chanend ?c_adc) { /* 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++])); - samplesInPrev[i] = bitrev(sample); + //samplesInPrev[i] = bitrev(sample); + + if(readBuffNo) + samplesIn_0[frameCount+i] = bitrev(sample); + else + samplesIn_1[frameCount+i] = bitrev(sample); + //samplesIn_1[i] = bitrev(sample); } #endif From 86faae889045e32abc793991d7f33a4eded016c4 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 27 Nov 2014 18:15:04 +0000 Subject: [PATCH 27/30] Removed the extra I2S input code. TDM and I2S port input code now shared. --- module_usb_audio/audio.xc | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index a25a0acf..99c8414c 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -576,7 +576,7 @@ chanend ?c_adc) index = 0; /* First input (i.e. frameCoint == 0) we read last ADC channel of previous frame.. */ unsigned buffIndex = frameCount ? !readBuffNo : readBuffNo; -#ifdef I2S_MODE_TDM + #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) @@ -589,21 +589,6 @@ chanend ?c_adc) else samplesIn_0[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line. } -#else -#pragma loop unroll - for(int i = 0; i < I2S_CHANS_ADC; i += 2) // TODO I2S_CHANS_PER_FRAME - { - /* 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(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. - // samplesIn_1[i] = bitrev(sample); - // samplesIn[i-1] = samplesInPrev[i]; - } -#endif #endif @@ -673,32 +658,17 @@ chanend ?c_adc) #if (I2S_CHANS_ADC != 0) index = 0; -#ifdef I2S_MODE_TDM /* Channels 0, 2, 4.. on each line */ - #pragma loop unroll +#pragma loop unroll for(int i = 0; i < I2S_CHANS_ADC; i += I2S_CHANS_PER_FRAME) { + /* 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(readBuffNo) samplesIn_0[frameCount+i] = bitrev(sample); else samplesIn_1[frameCount+i] = bitrev(sample); } -#else - /* Input previous right ADC sample */ - for(int i = 0; i < I2S_CHANS_ADC; i += 2) - { - /* 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++])); - //samplesInPrev[i] = bitrev(sample); - - if(readBuffNo) - samplesIn_0[frameCount+i] = bitrev(sample); - else - samplesIn_1[frameCount+i] = bitrev(sample); - //samplesIn_1[i] = bitrev(sample); - } -#endif #ifdef SU1_ADC_ENABLE { From ee0c69c50fe9cd938d4544f4459e250389409c30 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Thu, 27 Nov 2014 18:29:26 +0000 Subject: [PATCH 28/30] Output TDM and I2S code now unified. --- module_usb_audio/audio.xc | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 99c8414c..6c944ab6 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -555,17 +555,11 @@ chanend ?c_adc) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) index = 0; #pragma loop unroll -#ifdef I2S_MODE_TDM - for(int i = 0; i < I2S_CHANS_DAC; i+=8) + /* 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]); } -#else - for(int i = 0; i < I2S_CHANS_DAC; i+=2) - { - p_i2s_dac[index++] <: bitrev(samplesOut[i]); /* Output Left sample to DAC */ - } -#endif #endif /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */ @@ -640,18 +634,12 @@ chanend ?c_adc) 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 -#ifdef I2S_MODE_TDM - for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) + for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) { - p_i2s_dac[index++] <: bitrev(samplesOut[frameCount+1+i]); + p_i2s_dac[index++] <: bitrev(samplesOut[frameCount+i]); } -#else - for(int i = 1; i < I2S_CHANS_DAC; i+=2) - { - p_i2s_dac[index++] <: bitrev(samplesOut[i]); /* Output Right sample to DAC */ - } -#endif #endif doI2SClocks(divide); From 7ac0e87e0b28ab3b3d2c2c29696bb6910d06d29f Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 2 Dec 2014 14:07:50 +0000 Subject: [PATCH 29/30] Fixed issue with TDM and S/PDIF Tx --- module_usb_audio/audio.xc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 6c944ab6..744b8f70 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -585,6 +585,8 @@ chanend ?c_adc) } #endif + if(frameCount == 0) + { #if defined(SPDIF_RX) || defined(ADAT_RX) /* Sync with clockgen */ @@ -610,15 +612,14 @@ chanend ?c_adc) #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 - - + } #ifndef CODEC_MASTER #ifdef I2S_MODE_TDM From 4ab8cff9a4a0152b02d7f1871aa7e18fa750cd70 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 2 Dec 2014 14:22:11 +0000 Subject: [PATCH 30/30] I2_CHANS_PER_FRAME default define moved from audio.xc to devicedefines.xc --- module_usb_audio/audio.xc | 7 ------- module_usb_audio/devicedefines.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 744b8f70..dd82c037 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -29,12 +29,6 @@ static unsigned samplesOut[NUM_USB_CHAN_OUT]; static unsigned samplesIn_0[NUM_USB_CHAN_IN]; static unsigned samplesIn_1[I2S_CHANS_ADC]; -#ifdef I2S_MODE_TDM -#define I2S_CHANS_PER_FRAME 8 -#else -#define I2S_CHANS_PER_FRAME 2 -#endif - #if (DSD_CHANS_DAC != 0) extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC]; extern buffered out port:32 p_dsd_clk; @@ -42,7 +36,6 @@ extern buffered out port:32 p_dsd_clk; unsigned g_adcVal = 0; - #ifdef XTA_TIMING_AUDIO #pragma xta command "add exclusion received_command" #pragma xta command "analyse path i2s_output_l i2s_output_r" diff --git a/module_usb_audio/devicedefines.h b/module_usb_audio/devicedefines.h index 7ca77aff..08012067 100644 --- a/module_usb_audio/devicedefines.h +++ b/module_usb_audio/devicedefines.h @@ -101,6 +101,20 @@ #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 */