From 9b644d81d724854264acf3f01d41aff3b3ee798d Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 27 Dec 2017 14:12:28 +0000 Subject: [PATCH 01/13] move dsd out to inline functions --- lib_xua/src/core/audiohub/xua_audiohub.xc | 309 +++++++++++----------- 1 file changed, 159 insertions(+), 150 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index cd514f15..68989cd3 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -443,6 +443,161 @@ static inline void InitPorts(unsigned divide) #endif } +static inline void do_dsd_native(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ +#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) + /* 8 bits per chan, 1st 1-bit sample in MSB */ + dsdSample_l = samplesOut[0]; + dsdSample_r = samplesOut[1]; + dsdSample_r = bitrev(byterev(dsdSample_r)); + dsdSample_l = bitrev(byterev(dsdSample_l)); + + /* Output DSD data to ports then 32 clocks */ + switch (divide) + { + case 4: + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); + p_dsd_clk <: 0xCCCCCCCC; + p_dsd_clk <: 0xCCCCCCCC; + p_dsd_clk <: 0xCCCCCCCC; + p_dsd_clk <: 0xCCCCCCCC; + break; + + case 2: + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); + p_dsd_clk <: 0xAAAAAAAA; + p_dsd_clk <: 0xAAAAAAAA; + break; + + default: + /* Do some clocks anyway - this will stop us interrupting decouple too much */ + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + break; + } +#endif +} + +static inline void do_dsp_dop(unsigned &everyOther, unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ +#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) + if(!everyOther) + { + dsdSample_l = ((samplesOut[0] & 0xffff00) << 8); + dsdSample_r = ((samplesOut[1] & 0xffff00) << 8); + + everyOther = 1; + + switch (divide) + { + case 8: + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + break; + + case 4: + p_dsd_clk <: 0xCCCCCCCC; + p_dsd_clk <: 0xCCCCCCCC; + break; + + case 2: + p_dsd_clk <: 0xAAAAAAAA; + break; + } + } + else // everyOther + { + everyOther = 0; + dsdSample_l = dsdSample_l | ((samplesOut[0] & 0xffff00) >> 8); + dsdSample_r = dsdSample_r | ((samplesOut[1] & 0xffff00) >> 8); + + // Output 16 clocks DSD to all + //p_dsd_dac[0] <: bitrev(dsdSample_l); + //p_dsd_dac[1] <: bitrev(dsdSample_r); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(bitrev(dsdSample_l))); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(bitrev(dsdSample_r))); + switch (divide) + { + case 8: + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + break; + + case 4: + p_dsd_clk <: 0xCCCCCCCC; + p_dsd_clk <: 0xCCCCCCCC; + break; + + case 2: + p_dsd_clk <: 0xAAAAAAAA; + break; + } + } + } +#endif +} + +static inline void do_dsd_dop_check(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker){ +#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) + /* Check for DSD - note we only move into DoP mode if valid DoP Freq */ + /* Currently we only check on channel 0 - we get all 0's on channels without data */ + if((dsdMode == DSD_MODE_OFF) && (curSamFreq > 96000)) + { + if((DSD_MASK(samplesOut[0]) == dsdMarker) && (DSD_MASK(samplesOut[1]) == dsdMarker)) + { + dsdCount++; + dsdMarker ^= DSD_MARKER_XOR; + if(dsdCount == DSD_EN_THRESH) + { + dsdMode = DSD_MODE_DOP; + dsdCount = 0; + dsdMarker = DSD_MARKER_2; + + // Set clocks low + p_lrclk <: 0; + p_bclk <: 0; + p_dsd_clk <: 0; + return 0; + } + } + else + { + dsdCount = 0; + dsdMarker = DSD_MARKER_2; + } + } + else if(dsdMode == DSD_MODE_DOP) // DSD DoP Mode + { + /* If we are running in DOP mode, check if we need to come out */ + if((DSD_MASK(samplesOut[0]) != DSD_MARKER_1) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_1)) + { + if((DSD_MASK(samplesOut[0]) != DSD_MARKER_2) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_2)) + { + dsdMode = DSD_MODE_OFF; + // Set clocks low + p_lrclk <: 0; + p_bclk <: 0; + p_dsd_clk <: 0; + return 0; + } + } + } +#endif +} + + /* I2S delivery thread */ #pragma unsafe arrays unsigned static deliver(chanend ?c_out, chanend ?c_spd_out @@ -473,9 +628,9 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out int firstIteration = 1; #endif -#if (DSD_CHANS_DAC != 0) unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */ int dsdCount = 0; +#if (DSD_CHANS_DAC != 0) int everyOther = 1; unsigned dsdSample_l = 0x96960000; unsigned dsdSample_r = 0x96960000; @@ -577,109 +732,8 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out #endif // CODEC_MASTER { #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) - if(dsdMode == DSD_MODE_NATIVE) - { - /* 8 bits per chan, 1st 1-bit sample in MSB */ - dsdSample_l = samplesOut[0]; - dsdSample_r = samplesOut[1]; - dsdSample_r = bitrev(byterev(dsdSample_r)); - dsdSample_l = bitrev(byterev(dsdSample_l)); - - /* Output DSD data to ports then 32 clocks */ - switch (divide) - { - case 4: - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); - p_dsd_clk <: 0xCCCCCCCC; - p_dsd_clk <: 0xCCCCCCCC; - p_dsd_clk <: 0xCCCCCCCC; - p_dsd_clk <: 0xCCCCCCCC; - break; - - case 2: - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); - p_dsd_clk <: 0xAAAAAAAA; - p_dsd_clk <: 0xAAAAAAAA; - break; - - default: - /* Do some clocks anyway - this will stop us interrupting decouple too much */ - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - break; - } - - } - else if(dsdMode == DSD_MODE_DOP) - { - if(!everyOther) - { - dsdSample_l = ((samplesOut[0] & 0xffff00) << 8); - dsdSample_r = ((samplesOut[1] & 0xffff00) << 8); - - everyOther = 1; - - switch (divide) - { - case 8: - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - break; - - case 4: - p_dsd_clk <: 0xCCCCCCCC; - p_dsd_clk <: 0xCCCCCCCC; - break; - - case 2: - p_dsd_clk <: 0xAAAAAAAA; - break; - } - } - else // everyOther - { - everyOther = 0; - dsdSample_l = dsdSample_l | ((samplesOut[0] & 0xffff00) >> 8); - dsdSample_r = dsdSample_r | ((samplesOut[1] & 0xffff00) >> 8); - - // Output 16 clocks DSD to all - //p_dsd_dac[0] <: bitrev(dsdSample_l); - //p_dsd_dac[1] <: bitrev(dsdSample_r); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(bitrev(dsdSample_l))); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(bitrev(dsdSample_r))); - switch (divide) - { - case 8: - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - break; - - case 4: - p_dsd_clk <: 0xCCCCCCCC; - p_dsd_clk <: 0xCCCCCCCC; - break; - - case 2: - p_dsd_clk <: 0xAAAAAAAA; - break; - } - - } - } + if(dsdMode == DSD_MODE_NATIVE) do_dsd_native(samplesOut, dsdSample_l, dsdSample_r, divide); + else if(dsdMode == DSD_MODE_DOP) do_dsp_dop(everyOther, samplesOut, dsdSample_l, dsdSample_r, divide); else #endif { @@ -939,51 +993,7 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out } // !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 */ - /* Currently we only check on channel 0 - we get all 0's on channels without data */ - if((dsdMode == DSD_MODE_OFF) && (curSamFreq > 96000)) - { - if((DSD_MASK(samplesOut[0]) == dsdMarker) && (DSD_MASK(samplesOut[1]) == dsdMarker)) - { - dsdCount++; - dsdMarker ^= DSD_MARKER_XOR; - if(dsdCount == DSD_EN_THRESH) - { - dsdMode = DSD_MODE_DOP; - dsdCount = 0; - dsdMarker = DSD_MARKER_2; - - // Set clocks low - p_lrclk <: 0; - p_bclk <: 0; - p_dsd_clk <: 0; - return 0; - } - } - else - { - dsdCount = 0; - dsdMarker = DSD_MARKER_2; - } - } - else if(dsdMode == DSD_MODE_DOP) // DSD DoP Mode - { - /* If we are running in DOP mode, check if we need to come out */ - if((DSD_MASK(samplesOut[0]) != DSD_MARKER_1) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_1)) - { - if((DSD_MASK(samplesOut[0]) != DSD_MARKER_2) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_2)) - { - dsdMode = DSD_MODE_OFF; - // Set clocks low - p_lrclk <: 0; - p_bclk <: 0; - p_dsd_clk <: 0; - return 0; - } - } - } -#endif + do_dsd_dop_check(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); #ifdef I2S_MODE_TDM /* Increase frameCount by 2 since we have output two channels (per data line) */ @@ -1018,7 +1028,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out } } } - #pragma xta endpoint "deliver_return" return 0; } From b0642f7c4948d2a98eb8f9599ef4bba59383e9c4 Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 27 Dec 2017 14:23:54 +0000 Subject: [PATCH 02/13] Separate out master and slave into 2 delivers --- lib_xua/src/core/audiohub/xua_audiohub.xc | 467 +++++++++++++++++++--- 1 file changed, 403 insertions(+), 64 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 68989cd3..2a6b3e9e 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -598,9 +598,9 @@ static inline void do_dsd_dop_check(unsigned &dsdMode, int &dsdCount, unsigned c } -/* I2S delivery thread */ +#ifndef CODEC_MASTER #pragma unsafe arrays -unsigned static deliver(chanend ?c_out, chanend ?c_spd_out +unsigned static deliver_master(chanend ?c_out, chanend ?c_spd_out #ifdef ADAT_TX , chanend c_adat_out , unsigned adatSmuxMode @@ -624,10 +624,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out int started = 0; #endif -#ifdef CODEC_MASTER - int firstIteration = 1; -#endif - unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */ int dsdCount = 0; #if (DSD_CHANS_DAC != 0) @@ -713,23 +709,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out /* Main Audio I/O loop */ while (1) { -#ifdef CODEC_MASTER - /* In CODEC master mode, the I/O loop assumes L/RCLK = 32bit clocks. - * Check this every iteration and resync if we get a bclk glitch. - */ - int syncError = 0; - - if (!firstIteration) - { - InitPorts(divide); - } - else - { - firstIteration = 0; - } - - while (!syncError) -#endif // CODEC_MASTER { #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) if(dsdMode == DSD_MODE_NATIVE) do_dsd_native(samplesOut, dsdSample_l, dsdSample_r, divide); @@ -757,16 +736,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) unsigned sample; asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); -#ifdef CODEC_MASTER - unsigned lrval; - p_lrclk :> lrval; -#ifdef I2S_MODE_TDM - syncError += (lrval != 0x00000000); -#else - syncError += (lrval != 0x80000000); -#endif // I2S_MODE_TDM -#endif // CODEC_MASTER - sample = bitrev(sample); int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line. #if (AUD_TO_USB_RATIO > 1) @@ -794,10 +763,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out } #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 */ @@ -806,7 +771,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out #else p_lrclk <: 0x80000000; #endif -#endif #pragma xta endpoint "i2s_output_l" @@ -833,10 +797,8 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out } #endif // (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) -#ifndef CODEC_MASTER /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */ doI2SClocks(divide); -#endif // !CODEC_MASTER #ifdef ADAT_TX TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1); @@ -907,23 +869,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out /* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */ unsigned sample; asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); -#ifdef CODEC_MASTER - unsigned lrval; - p_lrclk :> lrval; -#ifdef I2S_MODE_TDM - if (frameCount == (I2S_CHANS_PER_FRAME-2)) - { - syncError += (lrval != 0x80000000); - } - else - { - syncError += (lrval != 0x00000000); - } -#else - syncError += (lrval != 0x7FFFFFFF); -#endif // I2S_MODE_TDM -#endif // CODEC_MASTER - sample = bitrev(sample); int chanIndex = ((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line. #if (AUD_TO_USB_RATIO > 1 && !I2S_DOWNSAMPLE_MONO_IN) @@ -951,7 +896,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out } #endif -#ifndef CODEC_MASTER #ifdef I2S_MODE_TDM if(frameCount == (I2S_CHANS_PER_FRAME-2)) p_lrclk <: 0x80000000; @@ -959,7 +903,6 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out p_lrclk <: 0x00000000; #else p_lrclk <: 0x7FFFFFFF; -#endif #endif index = 0; @@ -986,11 +929,7 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out } #endif // (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) -#ifndef CODEC_MASTER doI2SClocks(divide); -#endif // !CODEC_MASTER - - } // !dsdMode do_dsd_dop_check(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); @@ -1031,6 +970,402 @@ unsigned static deliver(chanend ?c_out, chanend ?c_spd_out #pragma xta endpoint "deliver_return" return 0; } +#endif //ndef CODEC_MASTER + + +#ifdef CODEC_MASTER +/* I2S delivery thread */ +#pragma unsafe arrays +unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out +#ifdef ADAT_TX + , chanend c_adat_out + , unsigned adatSmuxMode +#endif + , unsigned divide, unsigned curSamFreq +#if(defined(SPDIF_RX) || defined(ADAT_RX)) + , chanend c_dig_rx +#endif +#if (NUM_PDM_MICS > 0) + , chanend c_pdm_pcm +#endif +) +{ + + /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ + unsigned readBuffNo = 0; + unsigned index; + +#ifdef RAMP_CHECK + unsigned prev=0; + int started = 0; +#endif + + int firstIteration = 1; + + unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */ + int dsdCount = 0; +#if (DSD_CHANS_DAC != 0) + int everyOther = 1; + unsigned dsdSample_l = 0x96960000; + unsigned dsdSample_r = 0x96960000; +#endif + unsigned underflowWord = 0; + + unsigned frameCount = 0; +#ifdef ADAT_TX + adatCounter = 0; +#endif + +#if(DSD_CHANS_DAC != 0) + if(dsdMode == DSD_MODE_DOP) + { + underflowWord = 0xFA969600; + } + else if(dsdMode == DSD_MODE_NATIVE) + { + underflowWord = 0x96969696; + } +#endif + + unsigned audioToUsbRatioCounter = 0; +#if (NUM_PDM_MICS > 0) + unsigned audioToMicsRatioCounter = 0; +#endif + +#if (AUD_TO_USB_RATIO > 1) + union i2sInDs3 + { + long long doubleWordAlignmentEnsured; + int32_t delayLine[I2S_DOWNSAMPLE_CHANS_IN][SRC_FF3V_FIR_NUM_PHASES][SRC_FF3V_FIR_TAPS_PER_PHASE]; + } i2sInDs3; + memset(&i2sInDs3.delayLine, 0, sizeof i2sInDs3.delayLine); + int64_t i2sInDs3Sum[I2S_DOWNSAMPLE_CHANS_IN]; + + union i2sOutUs3 + { + long long doubleWordAlignmentEnsured; + int32_t delayLine[I2S_CHANS_DAC][SRC_FF3V_FIR_TAPS_PER_PHASE]; + } i2sOutUs3; + memset(&i2sOutUs3.delayLine, 0, sizeof i2sOutUs3.delayLine); +#endif /* (AUD_TO_USB_RATIO > 1) */ + + +#if ((DEBUG_MIC_ARRAY == 1) && (NUM_PDM_MICS > 0)) + /* Get initial samples from PDM->PCM converter to avoid stalling the decimators */ + c_pdm_pcm <: 1; + master + { +#pragma loop unroll + for(int i = PDM_MIC_INDEX; i < (NUM_PDM_MICS + PDM_MIC_INDEX); i++) + { + c_pdm_pcm :> samplesIn[readBuffNo][i]; + } + } +#endif // ((DEBUG_MIC_ARRAY == 1) && (NUM_PDM_MICS > 0)) + + UserBufferManagementInit(); + + unsigned command = DoSampleTransfer(c_out, readBuffNo, underflowWord); + + // Reinitialise user state before entering the main loop + UserBufferManagementInit(); + +#ifdef ADAT_TX + unsafe{ + //TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 0); + volatile unsigned * unsafe samplePtr = &samplesOut[ADAT_TX_INDEX]; + outuint(c_adat_out, (unsigned) samplePtr); + } +#endif + if(command) + { + return command; + } + + InitPorts(divide); + + /* Main Audio I/O loop */ + while (1) + { + /* In CODEC master mode, the I/O loop assumes L/RCLK = 32bit clocks. + * Check this every iteration and resync if we get a bclk glitch. + */ + int syncError = 0; + + if (!firstIteration) + { + InitPorts(divide); + } + else + { + firstIteration = 0; + } + + while (!syncError) + { +#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) + if(dsdMode == DSD_MODE_NATIVE) do_dsd_native(samplesOut, dsdSample_l, dsdSample_r, divide); + else if(dsdMode == DSD_MODE_DOP) do_dsp_dop(everyOther, samplesOut, dsdSample_l, dsdSample_r, divide); + else +#endif + { +#if (I2S_CHANS_ADC != 0) +#if (AUD_TO_USB_RATIO > 1) + if (0 == audioToUsbRatioCounter) + { + memset(&i2sInDs3Sum, 0, sizeof i2sInDs3Sum); + } +#endif /* (AUD_TO_USB_RATIO > 1) */ + /* Input previous L sample into L in buffer */ + index = 0; + /* First input (i.e. frameCount == 0) we read last ADC channel of previous frame.. */ + unsigned buffIndex = (frameCount > 1) ? !readBuffNo : readBuffNo; + +#pragma loop unroll + /* First time around we get channel 7 of TDM8 */ + for(int i = 0; i < I2S_CHANS_ADC; i+=I2S_CHANS_PER_FRAME) + { + // p_i2s_adc[index++] :> sample; + // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) + unsigned sample; + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + unsigned lrval; + p_lrclk :> lrval; +#ifdef I2S_MODE_TDM + syncError += (lrval != 0x00000000); +#else + syncError += (lrval != 0x80000000); +#endif // I2S_MODE_TDM + + sample = bitrev(sample); + int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line. +#if (AUD_TO_USB_RATIO > 1) + if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) + { + samplesIn[buffIndex][chanIndex] = + src_ds3_voice_add_final_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); + } + else + { + i2sInDs3Sum[chanIndex] = + src_ds3_voice_add_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); + } +#else + samplesIn[buffIndex][chanIndex] = sample; +#endif /* (AUD_TO_USB_RATIO > 1) */ + } +#endif + + +#pragma xta endpoint "i2s_output_l" + +#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) + index = 0; +#pragma loop unroll + /* Output "even" channel to DAC (i.e. left) */ + for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) + { +#if (AUD_TO_USB_RATIO > 1) + if (0 == audioToUsbRatioCounter) + { + samplesOut[frameCount+i] = src_us3_voice_input_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2], + samplesOut[frameCount+i]); + } + else /* audioToUsbRatioCounter == 1 or 2 */ + { + samplesOut[frameCount+i] = src_us3_voice_get_next_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); + } +#endif /* (AUD_TO_USB_RATIO > 1) */ + p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]); + } +#endif // (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) + +#ifdef ADAT_TX + TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1); +#endif + + if(frameCount == 0) + { + +#if defined(SPDIF_RX) || defined(ADAT_RX) + /* Sync with clockgen */ + inuint(c_dig_rx); + + /* Note, digi-data we just store in samplesIn[readBuffNo] - we only double buffer the I2S input data */ +#endif +#ifdef SPDIF_RX + asm("ldw %0, dp[g_digData]" :"=r"(samplesIn[readBuffNo][SPDIF_RX_INDEX + 0])); + asm("ldw %0, dp[g_digData+4]":"=r"(samplesIn[readBuffNo][SPDIF_RX_INDEX + 1])); +#endif +#ifdef ADAT_RX + asm("ldw %0, dp[g_digData+8]" :"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX])); + asm("ldw %0, dp[g_digData+12]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 1])); + asm("ldw %0, dp[g_digData+16]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 2])); + asm("ldw %0, dp[g_digData+20]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 3])); + asm("ldw %0, dp[g_digData+24]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 4])); + asm("ldw %0, dp[g_digData+28]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 5])); + asm("ldw %0, dp[g_digData+32]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 6])); + asm("ldw %0, dp[g_digData+36]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 7])); +#endif + +#if defined(SPDIF_RX) || defined(ADAT_RX) + /* Request digital data (with prefill) */ + outuint(c_dig_rx, 0); +#endif +#if defined(SPDIF_TX) && (NUM_USB_CHAN_OUT > 0) + outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to S/PDIF Tx thread */ + unsigned sample = samplesOut[SPDIF_TX_INDEX + 1]; + outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ +#endif + +#if (NUM_PDM_MICS > 0) + if ((AUD_TO_MICS_RATIO - 1) == audioToMicsRatioCounter) + { + /* Get samples from PDM->PCM converter */ + c_pdm_pcm <: 1; + master + { +#pragma loop unroll + for(int i = PDM_MIC_INDEX; i < (NUM_PDM_MICS + PDM_MIC_INDEX); i++) + { + c_pdm_pcm :> samplesIn[readBuffNo][i]; + } + } + audioToMicsRatioCounter = 0; + } + else + { + ++audioToMicsRatioCounter; + } +#endif + } + +#if (I2S_CHANS_ADC != 0) + index = 0; + /* Channels 0, 2, 4.. on each line */ +#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) */ + unsigned sample; + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + unsigned lrval; + p_lrclk :> lrval; +#ifdef I2S_MODE_TDM + if (frameCount == (I2S_CHANS_PER_FRAME-2)) + { + syncError += (lrval != 0x80000000); + } + else + { + syncError += (lrval != 0x00000000); + } +#else + syncError += (lrval != 0x7FFFFFFF); +#endif // I2S_MODE_TDM + + sample = bitrev(sample); + int chanIndex = ((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line. +#if (AUD_TO_USB_RATIO > 1 && !I2S_DOWNSAMPLE_MONO_IN) + if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) + { + samplesIn[buffIndex][chanIndex] = + src_ds3_voice_add_final_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); + } + else + { + i2sInDs3Sum[chanIndex] = + src_ds3_voice_add_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); + } +#else + samplesIn[buffIndex][chanIndex] = sample; +#endif /* (AUD_TO_USB_RATIO > 1) && !I2S_DOWNSAMPLE_MONO_IN */ + } +#endif + + index = 0; +#pragma xta endpoint "i2s_output_r" +#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) + /* Output "odd" channel to DAC (i.e. right) */ +#pragma loop unroll + for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) + { +#if (AUD_TO_USB_RATIO > 1) + if (audioToUsbRatioCounter == 0) + { + samplesOut[frameCount+i] = src_us3_voice_input_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2], + samplesOut[frameCount+i]); + } + else + { /* audioToUsbRatioCounter is 1 or 2 */ + samplesOut[frameCount+i] = src_us3_voice_get_next_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); + } +#endif /* (AUD_TO_USB_RATIO > 1) */ + p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]); + } +#endif // (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) + + } // !dsdMode + do_dsd_dop_check(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); + +#ifdef I2S_MODE_TDM + /* Increase frameCount by 2 since we have output two channels (per data line) */ + frameCount+=2; + if(frameCount == I2S_CHANS_PER_FRAME) +#endif + { + if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) + { + /* Do samples transfer */ + /* The below looks a bit odd but forces the compiler to inline twice */ + unsigned command; + if(readBuffNo) + command = DoSampleTransfer(c_out, 1, underflowWord); + else + command = DoSampleTransfer(c_out, 0, underflowWord); + + if(command) + { + return command; + } + + /* Reset frame counter and flip the ADC buffer */ + audioToUsbRatioCounter = 0; + frameCount = 0; + readBuffNo = !readBuffNo; + } + else + { + ++audioToUsbRatioCounter; + } + } + } + } +#pragma xta endpoint "deliver_return" + return 0; +} +#endif //CODEC_MASTER + #if defined(SPDIF_TX) && (SPDIF_TX_TILE != AUDIO_IO_TILE) void SpdifTxWrapper(chanend c_spdif_tx) @@ -1354,7 +1689,11 @@ chanend c_dig_rx, outuint(c_adat_out, adatMultiple); outuint(c_adat_out, adatSmuxMode); #endif - command = deliver(c_mix_out +#if CODEC_MASTER + command = deliver_slave(c_mix_out +#else + command = deliver_master(c_mix_out +#endif #ifdef SPDIF_TX , c_spdif_out #else From f4a5501d98d7cdeff7c67846f44d6d187791018a Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 27 Dec 2017 14:36:16 +0000 Subject: [PATCH 03/13] Separate out init ports for master and slave --- lib_xua/src/core/audiohub/xua_audiohub.xc | 273 +++++++++++----------- 1 file changed, 139 insertions(+), 134 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 2a6b3e9e..ea9d0a76 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -310,138 +310,7 @@ static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, co } #endif /* NO_USB */ -static inline void InitPorts(unsigned divide) -{ - unsigned tmp; -#ifndef CODEC_MASTER -#if (DSD_CHANS_DAC > 0) - if(dsdMode == DSD_MODE_OFF) - { -#endif -#if !defined(__XS2A__) - if(divide != 1) - { - /* b_clk must start high */ - p_bclk <: 0x80000000; - sync(p_bclk); - } -#endif - - /* 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 defined(__XS2A__) - if(1) -#else - if(divide == 1) -#endif - { -#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 /* Divide != 1 */ - { -#if (I2S_CHANS_DAC != 0) - /* Pre-fill the DAC ports */ - for(int i = 0; i < I2S_WIRES_DAC; i++) - { - p_i2s_dac[i] <: 0; - } -#endif - /* Pre-fill the LR clock output port */ - p_lrclk <: 0x0; - - doI2SClocks(divide); - -#if (I2S_CHANS_DAC != 0) - /* Pre-fill the DAC ports */ - for(int i = 0; i < I2S_WIRES_DAC; i++) - { - p_i2s_dac[i] <: 0; - } -#endif - /* Pre-fill the LR clock output port */ - p_lrclk <: 0x0; - - doI2SClocks(divide); - } -#if (DSD_CHANS_DAC > 0) - } /* if (!dsdMode) */ - else - { - /* p_dsd_clk must start high */ - p_dsd_clk <: 0x80000000; - } -#endif -#else /* ifndef CODEC_MASTER */ - - /* Wait for LRCLK edge (in I2S LRCLK = 0 is left, TDM rising edge is start of frame) */ - p_lrclk when pinseq(0) :> void; - p_lrclk when pinseq(1) :> void; - p_lrclk when pinseq(0) :> void; - p_lrclk when pinseq(1) :> void; -#ifdef I2S_MODE_TDM - p_lrclk when pinseq(0) :> void; - p_lrclk when pinseq(1) :> void @ tmp; -#else - p_lrclk when pinseq(0) :> void @ tmp; -#endif - - tmp += (I2S_CHANS_PER_FRAME * 32) - 32 + 1 ; - /* E.g. 2 * 32 - 32 + 1 = 33 for stereo */ - /* E.g. 8 * 32 - 32 + 1 = 225 for 8 chan TDM */ - -#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-1)); - } -#endif -#endif -} static inline void do_dsd_native(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) @@ -599,6 +468,104 @@ static inline void do_dsd_dop_check(unsigned &dsdMode, int &dsdCount, unsigned c #ifndef CODEC_MASTER +static inline void InitPorts_master(unsigned divide) +{ + unsigned tmp; +#if (DSD_CHANS_DAC > 0) + if(dsdMode == DSD_MODE_OFF) + { +#endif + +#if !defined(__XS2A__) + if(divide != 1) + { + /* b_clk must start high */ + p_bclk <: 0x80000000; + sync(p_bclk); + } +#endif + + /* 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 defined(__XS2A__) + if(1) +#else + if(divide == 1) +#endif + { +#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 /* Divide != 1 */ + { +#if (I2S_CHANS_DAC != 0) + /* Pre-fill the DAC ports */ + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] <: 0; + } +#endif + /* Pre-fill the LR clock output port */ + p_lrclk <: 0x0; + + doI2SClocks(divide); + +#if (I2S_CHANS_DAC != 0) + /* Pre-fill the DAC ports */ + for(int i = 0; i < I2S_WIRES_DAC; i++) + { + p_i2s_dac[i] <: 0; + } +#endif + /* Pre-fill the LR clock output port */ + p_lrclk <: 0x0; + + doI2SClocks(divide); + } +#if (DSD_CHANS_DAC > 0) + } /* if (!dsdMode) */ + else + { + /* p_dsd_clk must start high */ + p_dsd_clk <: 0x80000000; + } +#endif +} + #pragma unsafe arrays unsigned static deliver_master(chanend ?c_out, chanend ?c_spd_out #ifdef ADAT_TX @@ -704,7 +671,7 @@ unsigned static deliver_master(chanend ?c_out, chanend ?c_spd_out return command; } - InitPorts(divide); + InitPorts_master(divide); /* Main Audio I/O loop */ while (1) @@ -974,6 +941,44 @@ unsigned static deliver_master(chanend ?c_out, chanend ?c_spd_out #ifdef CODEC_MASTER +static inline void InitPorts_slave(unsigned divide) +{ + unsigned tmp; + + /* Wait for LRCLK edge (in I2S LRCLK = 0 is left, TDM rising edge is start of frame) */ + p_lrclk when pinseq(0) :> void; + p_lrclk when pinseq(1) :> void; + p_lrclk when pinseq(0) :> void; + p_lrclk when pinseq(1) :> void; +#ifdef I2S_MODE_TDM + p_lrclk when pinseq(0) :> void; + p_lrclk when pinseq(1) :> void @ tmp; +#else + p_lrclk when pinseq(0) :> void @ tmp; +#endif + + tmp += (I2S_CHANS_PER_FRAME * 32) - 32 + 1 ; + /* E.g. 2 * 32 - 32 + 1 = 33 for stereo */ + /* E.g. 8 * 32 - 32 + 1 = 225 for 8 chan TDM */ + +#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-1)); + } +#endif +} + + /* I2S delivery thread */ #pragma unsafe arrays unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out @@ -1082,7 +1087,7 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out return command; } - InitPorts(divide); + InitPorts_slave(divide); /* Main Audio I/O loop */ while (1) @@ -1094,7 +1099,7 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out if (!firstIteration) { - InitPorts(divide); + InitPorts_slave(divide); } else { From 573b7f3b0ce15a8d74d7626a3f88dfa3a01c9330 Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 27 Dec 2017 14:42:47 +0000 Subject: [PATCH 04/13] Remove DSD from slave --- lib_xua/src/core/audiohub/xua_audiohub.xc | 336 ++++++++++------------ 1 file changed, 155 insertions(+), 181 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index ea9d0a76..ca5b61a0 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -1007,13 +1007,6 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out int firstIteration = 1; - unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */ - int dsdCount = 0; -#if (DSD_CHANS_DAC != 0) - int everyOther = 1; - unsigned dsdSample_l = 0x96960000; - unsigned dsdSample_r = 0x96960000; -#endif unsigned underflowWord = 0; unsigned frameCount = 0; @@ -1021,17 +1014,6 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out adatCounter = 0; #endif -#if(DSD_CHANS_DAC != 0) - if(dsdMode == DSD_MODE_DOP) - { - underflowWord = 0xFA969600; - } - else if(dsdMode == DSD_MODE_NATIVE) - { - underflowWord = 0x96969696; - } -#endif - unsigned audioToUsbRatioCounter = 0; #if (NUM_PDM_MICS > 0) unsigned audioToMicsRatioCounter = 0; @@ -1108,230 +1090,222 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out while (!syncError) { -#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) - if(dsdMode == DSD_MODE_NATIVE) do_dsd_native(samplesOut, dsdSample_l, dsdSample_r, divide); - else if(dsdMode == DSD_MODE_DOP) do_dsp_dop(everyOther, samplesOut, dsdSample_l, dsdSample_r, divide); - else -#endif - { #if (I2S_CHANS_ADC != 0) #if (AUD_TO_USB_RATIO > 1) - if (0 == audioToUsbRatioCounter) - { - memset(&i2sInDs3Sum, 0, sizeof i2sInDs3Sum); - } + if (0 == audioToUsbRatioCounter) + { + memset(&i2sInDs3Sum, 0, sizeof i2sInDs3Sum); + } #endif /* (AUD_TO_USB_RATIO > 1) */ - /* Input previous L sample into L in buffer */ - index = 0; - /* First input (i.e. frameCount == 0) we read last ADC channel of previous frame.. */ - unsigned buffIndex = (frameCount > 1) ? !readBuffNo : readBuffNo; + /* Input previous L sample into L in buffer */ + index = 0; + /* First input (i.e. frameCount == 0) we read last ADC channel of previous frame.. */ + unsigned buffIndex = (frameCount > 1) ? !readBuffNo : readBuffNo; #pragma loop unroll - /* First time around we get channel 7 of TDM8 */ - for(int i = 0; i < I2S_CHANS_ADC; i+=I2S_CHANS_PER_FRAME) - { - // p_i2s_adc[index++] :> sample; - // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) - unsigned sample; - asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - unsigned lrval; - p_lrclk :> lrval; + /* First time around we get channel 7 of TDM8 */ + for(int i = 0; i < I2S_CHANS_ADC; i+=I2S_CHANS_PER_FRAME) + { + // p_i2s_adc[index++] :> sample; + // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) + unsigned sample; + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + unsigned lrval; + p_lrclk :> lrval; #ifdef I2S_MODE_TDM - syncError += (lrval != 0x00000000); + syncError += (lrval != 0x00000000); #else - syncError += (lrval != 0x80000000); + syncError += (lrval != 0x80000000); #endif // I2S_MODE_TDM - sample = bitrev(sample); - int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line. + sample = bitrev(sample); + int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line. #if (AUD_TO_USB_RATIO > 1) - if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) - { - samplesIn[buffIndex][chanIndex] = - src_ds3_voice_add_final_sample( - i2sInDs3Sum[chanIndex], - i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], - src_ff3v_fir_coefs[audioToUsbRatioCounter], - sample); - } - else - { - i2sInDs3Sum[chanIndex] = - src_ds3_voice_add_sample( - i2sInDs3Sum[chanIndex], - i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], - src_ff3v_fir_coefs[audioToUsbRatioCounter], - sample); - } -#else - samplesIn[buffIndex][chanIndex] = sample; -#endif /* (AUD_TO_USB_RATIO > 1) */ + if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) + { + samplesIn[buffIndex][chanIndex] = + src_ds3_voice_add_final_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); } + else + { + i2sInDs3Sum[chanIndex] = + src_ds3_voice_add_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); + } +#else + samplesIn[buffIndex][chanIndex] = sample; +#endif /* (AUD_TO_USB_RATIO > 1) */ + } #endif #pragma xta endpoint "i2s_output_l" #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) - index = 0; + index = 0; #pragma loop unroll - /* Output "even" channel to DAC (i.e. left) */ - for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) - { + /* Output "even" channel to DAC (i.e. left) */ + for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) + { #if (AUD_TO_USB_RATIO > 1) - if (0 == audioToUsbRatioCounter) - { - samplesOut[frameCount+i] = src_us3_voice_input_sample(i2sOutUs3.delayLine[i], - src_ff3v_fir_coefs[2], - samplesOut[frameCount+i]); - } - else /* audioToUsbRatioCounter == 1 or 2 */ - { - samplesOut[frameCount+i] = src_us3_voice_get_next_sample(i2sOutUs3.delayLine[i], - src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); - } -#endif /* (AUD_TO_USB_RATIO > 1) */ - p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]); + if (0 == audioToUsbRatioCounter) + { + samplesOut[frameCount+i] = src_us3_voice_input_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2], + samplesOut[frameCount+i]); } + else /* audioToUsbRatioCounter == 1 or 2 */ + { + samplesOut[frameCount+i] = src_us3_voice_get_next_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); + } +#endif /* (AUD_TO_USB_RATIO > 1) */ + p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]); + } #endif // (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #ifdef ADAT_TX - TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1); + TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1); #endif - if(frameCount == 0) - { + if(frameCount == 0) + { #if defined(SPDIF_RX) || defined(ADAT_RX) - /* Sync with clockgen */ - inuint(c_dig_rx); + /* Sync with clockgen */ + inuint(c_dig_rx); - /* Note, digi-data we just store in samplesIn[readBuffNo] - we only double buffer the I2S input data */ + /* Note, digi-data we just store in samplesIn[readBuffNo] - we only double buffer the I2S input data */ #endif #ifdef SPDIF_RX - asm("ldw %0, dp[g_digData]" :"=r"(samplesIn[readBuffNo][SPDIF_RX_INDEX + 0])); - asm("ldw %0, dp[g_digData+4]":"=r"(samplesIn[readBuffNo][SPDIF_RX_INDEX + 1])); + asm("ldw %0, dp[g_digData]" :"=r"(samplesIn[readBuffNo][SPDIF_RX_INDEX + 0])); + asm("ldw %0, dp[g_digData+4]":"=r"(samplesIn[readBuffNo][SPDIF_RX_INDEX + 1])); #endif #ifdef ADAT_RX - asm("ldw %0, dp[g_digData+8]" :"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX])); - asm("ldw %0, dp[g_digData+12]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 1])); - asm("ldw %0, dp[g_digData+16]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 2])); - asm("ldw %0, dp[g_digData+20]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 3])); - asm("ldw %0, dp[g_digData+24]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 4])); - asm("ldw %0, dp[g_digData+28]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 5])); - asm("ldw %0, dp[g_digData+32]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 6])); - asm("ldw %0, dp[g_digData+36]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 7])); + asm("ldw %0, dp[g_digData+8]" :"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX])); + asm("ldw %0, dp[g_digData+12]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 1])); + asm("ldw %0, dp[g_digData+16]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 2])); + asm("ldw %0, dp[g_digData+20]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 3])); + asm("ldw %0, dp[g_digData+24]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 4])); + asm("ldw %0, dp[g_digData+28]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 5])); + asm("ldw %0, dp[g_digData+32]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 6])); + asm("ldw %0, dp[g_digData+36]":"=r"(samplesIn[readBuffNo][ADAT_RX_INDEX + 7])); #endif #if defined(SPDIF_RX) || defined(ADAT_RX) - /* Request digital data (with prefill) */ - outuint(c_dig_rx, 0); + /* Request digital data (with prefill) */ + outuint(c_dig_rx, 0); #endif #if defined(SPDIF_TX) && (NUM_USB_CHAN_OUT > 0) - outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to S/PDIF Tx thread */ - unsigned sample = samplesOut[SPDIF_TX_INDEX + 1]; - outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ + outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to S/PDIF Tx thread */ + unsigned sample = samplesOut[SPDIF_TX_INDEX + 1]; + outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ #endif #if (NUM_PDM_MICS > 0) - if ((AUD_TO_MICS_RATIO - 1) == audioToMicsRatioCounter) + if ((AUD_TO_MICS_RATIO - 1) == audioToMicsRatioCounter) + { + /* Get samples from PDM->PCM converter */ + c_pdm_pcm <: 1; + master { - /* Get samples from PDM->PCM converter */ - c_pdm_pcm <: 1; - master - { #pragma loop unroll - for(int i = PDM_MIC_INDEX; i < (NUM_PDM_MICS + PDM_MIC_INDEX); i++) - { - c_pdm_pcm :> samplesIn[readBuffNo][i]; - } + for(int i = PDM_MIC_INDEX; i < (NUM_PDM_MICS + PDM_MIC_INDEX); i++) + { + c_pdm_pcm :> samplesIn[readBuffNo][i]; } - audioToMicsRatioCounter = 0; + } + audioToMicsRatioCounter = 0; + } + else + { + ++audioToMicsRatioCounter; + } +#endif + } + +#if (I2S_CHANS_ADC != 0) + index = 0; + /* Channels 0, 2, 4.. on each line */ +#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) */ + unsigned sample; + asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); + unsigned lrval; + p_lrclk :> lrval; +#ifdef I2S_MODE_TDM + if (frameCount == (I2S_CHANS_PER_FRAME-2)) + { + syncError += (lrval != 0x80000000); } else { - ++audioToMicsRatioCounter; + syncError += (lrval != 0x00000000); } -#endif - } - -#if (I2S_CHANS_ADC != 0) - index = 0; - /* Channels 0, 2, 4.. on each line */ -#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) */ - unsigned sample; - asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - unsigned lrval; - p_lrclk :> lrval; -#ifdef I2S_MODE_TDM - if (frameCount == (I2S_CHANS_PER_FRAME-2)) - { - syncError += (lrval != 0x80000000); - } - else - { - syncError += (lrval != 0x00000000); - } #else - syncError += (lrval != 0x7FFFFFFF); + syncError += (lrval != 0x7FFFFFFF); #endif // I2S_MODE_TDM - sample = bitrev(sample); - int chanIndex = ((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line. + sample = bitrev(sample); + int chanIndex = ((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line. #if (AUD_TO_USB_RATIO > 1 && !I2S_DOWNSAMPLE_MONO_IN) - if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) - { - samplesIn[buffIndex][chanIndex] = - src_ds3_voice_add_final_sample( - i2sInDs3Sum[chanIndex], - i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], - src_ff3v_fir_coefs[audioToUsbRatioCounter], - sample); - } - else - { - i2sInDs3Sum[chanIndex] = - src_ds3_voice_add_sample( - i2sInDs3Sum[chanIndex], - i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], - src_ff3v_fir_coefs[audioToUsbRatioCounter], - sample); - } -#else - samplesIn[buffIndex][chanIndex] = sample; -#endif /* (AUD_TO_USB_RATIO > 1) && !I2S_DOWNSAMPLE_MONO_IN */ + if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter) + { + samplesIn[buffIndex][chanIndex] = + src_ds3_voice_add_final_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); } + else + { + i2sInDs3Sum[chanIndex] = + src_ds3_voice_add_sample( + i2sInDs3Sum[chanIndex], + i2sInDs3.delayLine[chanIndex][audioToUsbRatioCounter], + src_ff3v_fir_coefs[audioToUsbRatioCounter], + sample); + } +#else + samplesIn[buffIndex][chanIndex] = sample; +#endif /* (AUD_TO_USB_RATIO > 1) && !I2S_DOWNSAMPLE_MONO_IN */ + } #endif - index = 0; + 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) */ + /* Output "odd" channel to DAC (i.e. right) */ #pragma loop unroll - for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) - { + for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME) + { #if (AUD_TO_USB_RATIO > 1) - if (audioToUsbRatioCounter == 0) - { - samplesOut[frameCount+i] = src_us3_voice_input_sample(i2sOutUs3.delayLine[i], - src_ff3v_fir_coefs[2], - samplesOut[frameCount+i]); - } - else - { /* audioToUsbRatioCounter is 1 or 2 */ - samplesOut[frameCount+i] = src_us3_voice_get_next_sample(i2sOutUs3.delayLine[i], - src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); - } -#endif /* (AUD_TO_USB_RATIO > 1) */ - p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]); + if (audioToUsbRatioCounter == 0) + { + samplesOut[frameCount+i] = src_us3_voice_input_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2], + samplesOut[frameCount+i]); } + else + { /* audioToUsbRatioCounter is 1 or 2 */ + samplesOut[frameCount+i] = src_us3_voice_get_next_sample(i2sOutUs3.delayLine[i], + src_ff3v_fir_coefs[2-audioToUsbRatioCounter]); + } +#endif /* (AUD_TO_USB_RATIO > 1) */ + p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]); + } #endif // (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) - } // !dsdMode - do_dsd_dop_check(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); #ifdef I2S_MODE_TDM /* Increase frameCount by 2 since we have output two channels (per data line) */ From 308e63a97d95ed6b9ce3ed6e9403c183c4397ebe Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 27 Dec 2017 16:10:00 +0000 Subject: [PATCH 05/13] 8ch i2s slave passing --- lib_xua/src/core/audiohub/xua_audiohub.xc | 64 ++++++++++++++++------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index ca5b61a0..780ca266 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -995,7 +995,6 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out #endif ) { - /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ unsigned readBuffNo = 0; unsigned index; @@ -1006,9 +1005,7 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out #endif int firstIteration = 1; - unsigned underflowWord = 0; - unsigned frameCount = 0; #ifdef ADAT_TX adatCounter = 0; @@ -1078,6 +1075,7 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out * Check this every iteration and resync if we get a bclk glitch. */ int syncError = 0; + unsigned lrval; if (!firstIteration) { @@ -1110,13 +1108,16 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out // Manual IN instruction since compiler generates an extra setc per IN (bug #15256) unsigned sample; asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - unsigned lrval; - p_lrclk :> lrval; + + if (i == 0){ + p_lrclk :> lrval; #ifdef I2S_MODE_TDM - syncError += (lrval != 0x00000000); + //We do not check this part of the frame because TDM frame sync falling egde timing + //is not defined. We only care about rising edge which is checked in first half of frame #else - syncError += (lrval != 0x80000000); + syncError += (lrval != 0x80000000); #endif // I2S_MODE_TDM + } sample = bitrev(sample); int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line. @@ -1143,7 +1144,15 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out samplesIn[buffIndex][chanIndex] = sample; #endif /* (AUD_TO_USB_RATIO > 1) */ } -#endif +#else //(I2S_CHANS_ADC != 0) //If no ADC channels then just check lrclk for sync + p_lrclk :> lrval; +#ifdef I2S_MODE_TDM + //We do not check this part of the frame because TDM frame sync falling egde timing + //is not defined. We only care about rising edge which is checked in first half of frame +#else + syncError += (lrval != 0x80000000); +#endif // I2S_MODE_TDM +#endif //(I2S_CHANS_ADC != 0) #pragma xta endpoint "i2s_output_l" @@ -1240,20 +1249,21 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out /* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */ unsigned sample; asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); - unsigned lrval; - p_lrclk :> lrval; + if (i == 0) { + p_lrclk :> lrval; #ifdef I2S_MODE_TDM - if (frameCount == (I2S_CHANS_PER_FRAME-2)) - { - syncError += (lrval != 0x80000000); - } - else - { - syncError += (lrval != 0x00000000); - } + if (frameCount == (I2S_CHANS_PER_FRAME-2)) + { + syncError += (lrval != 0x80000000); + } + else + { + syncError += (lrval != 0x00000000); + } #else - syncError += (lrval != 0x7FFFFFFF); + syncError += (lrval != 0x7FFFFFFF); #endif // I2S_MODE_TDM + } sample = bitrev(sample); int chanIndex = ((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line. @@ -1280,7 +1290,21 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out samplesIn[buffIndex][chanIndex] = sample; #endif /* (AUD_TO_USB_RATIO > 1) && !I2S_DOWNSAMPLE_MONO_IN */ } -#endif +#else //(I2S_CHANS_ADC != 0) //No ADC so just do lrclk sync check only + p_lrclk :> lrval; +#ifdef I2S_MODE_TDM + if (frameCount == (I2S_CHANS_PER_FRAME-2)) + { + syncError += (lrval != 0x80000000); + } + else + { + syncError += (lrval != 0x00000000); + } +#else + syncError += (lrval != 0x7FFFFFFF); +#endif //I2S_MODE_TDM +#endif //(I2S_CHANS_ADC != 0) index = 0; #pragma xta endpoint "i2s_output_r" From 0f6bc2fa2c824309940c2d6b6982198f27cc1f74 Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 27 Dec 2017 16:14:19 +0000 Subject: [PATCH 06/13] Update tdm slave sync check to only look for correct rising edge of frame clock --- lib_xua/src/core/audiohub/xua_audiohub.xc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 780ca266..f6910b7c 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -1252,13 +1252,10 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out if (i == 0) { p_lrclk :> lrval; #ifdef I2S_MODE_TDM - if (frameCount == (I2S_CHANS_PER_FRAME-2)) - { - syncError += (lrval != 0x80000000); - } - else - { - syncError += (lrval != 0x00000000); + //Just check for the rising edge of frame synch being in the right place because falling edge timing not specified + if (frameCount == 0) { + lrval &= 0xc0000000; //Mask off last two (MSB) frame clock bits which are the most recently sampled + syncError += (lrval != 0x80000000); //We need MSB = 1 and MSB-1 = 0 to signify rising edge } #else syncError += (lrval != 0x7FFFFFFF); From 665aa5c0aa8174aa5de14b7147ca1eb38129cd10 Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Tue, 2 Jan 2018 07:25:08 +0000 Subject: [PATCH 07/13] Function names to meet existing coding style & some comments --- lib_xua/src/core/audiohub/xua_audiohub.xc | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index f6910b7c..caa4648b 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -311,8 +311,8 @@ static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, co #endif /* NO_USB */ - -static inline void do_dsd_native(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ +/* This function performs the DSD native loop and outputs a 32b DSD stream per loop */ +static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) /* 8 bits per chan, 1st 1-bit sample in MSB */ dsdSample_l = samplesOut[0]; @@ -356,7 +356,9 @@ static inline void do_dsd_native(unsigned samplesOut[], unsigned &dsdSample_l, u #endif } -static inline void do_dsp_dop(unsigned &everyOther, unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ +/* This function performs the DOP loop and collects 16b of DSD per loop + and outputs a 32b word into the port buffer every other cycle. */ +static inline void DoDsdDop(unsigned &everyOther, unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) if(!everyOther) { @@ -418,7 +420,12 @@ static inline void do_dsp_dop(unsigned &everyOther, unsigned samplesOut[], unsig #endif } -static inline void do_dsd_dop_check(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker){ +/* When DSD is enabled and streaming is normal I2S, this function checks for a series of DoP markers in the upper byte. + If found it will exit deliver() with the command to restart in DoP mode. + When in DoP mode, this function will check for a single absence of the DoP marker and exit deliver() with the command + to restart in I2S mode. */ + +static inline void DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker){ #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) /* Check for DSD - note we only move into DoP mode if valid DoP Freq */ /* Currently we only check on channel 0 - we get all 0's on channels without data */ @@ -678,8 +685,8 @@ unsigned static deliver_master(chanend ?c_out, chanend ?c_spd_out { { #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) - if(dsdMode == DSD_MODE_NATIVE) do_dsd_native(samplesOut, dsdSample_l, dsdSample_r, divide); - else if(dsdMode == DSD_MODE_DOP) do_dsp_dop(everyOther, samplesOut, dsdSample_l, dsdSample_r, divide); + if(dsdMode == DSD_MODE_NATIVE) DoDsdNative(samplesOut, dsdSample_l, dsdSample_r, divide); + else if(dsdMode == DSD_MODE_DOP) DoDsdDop(everyOther, samplesOut, dsdSample_l, dsdSample_r, divide); else #endif { @@ -899,7 +906,7 @@ unsigned static deliver_master(chanend ?c_out, chanend ?c_spd_out doI2SClocks(divide); } // !dsdMode - do_dsd_dop_check(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); + DoDsdDopCheck(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); #ifdef I2S_MODE_TDM /* Increase frameCount by 2 since we have output two channels (per data line) */ From 313fa5b8febe65c04510a5733699f93337de666b Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 3 Jan 2018 07:19:27 +0000 Subject: [PATCH 08/13] Add DSD XS2 fix --- lib_xua/src/core/audiohub/xua_audiohub.xc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index caa4648b..f251762b 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -320,6 +320,7 @@ static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, uns dsdSample_r = bitrev(byterev(dsdSample_r)); dsdSample_l = bitrev(byterev(dsdSample_l)); +#ifndef __XS2A__ /* Output DSD data to ports then 32 clocks */ switch (divide) { @@ -353,6 +354,7 @@ static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, uns p_dsd_clk <: 0xF0F0F0F0; break; } +#endif // __XS2A__ #endif } @@ -367,6 +369,7 @@ static inline void DoDsdDop(unsigned &everyOther, unsigned samplesOut[], unsigne everyOther = 1; +#ifndef __XS2A__ switch (divide) { case 8: @@ -385,6 +388,7 @@ static inline void DoDsdDop(unsigned &everyOther, unsigned samplesOut[], unsigne p_dsd_clk <: 0xAAAAAAAA; break; } +#endif // __XS2A__ } else // everyOther { @@ -397,6 +401,8 @@ static inline void DoDsdDop(unsigned &everyOther, unsigned samplesOut[], unsigne //p_dsd_dac[1] <: bitrev(dsdSample_r); asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(bitrev(dsdSample_l))); asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(bitrev(dsdSample_r))); + +#ifndef __XS2A__ switch (divide) { case 8: @@ -415,6 +421,7 @@ static inline void DoDsdDop(unsigned &everyOther, unsigned samplesOut[], unsigne p_dsd_clk <: 0xAAAAAAAA; break; } +#endif // __XS2A__ } } #endif From 4963a12e18784f4d1e43f0ce72b897cd6d658e6c Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Fri, 5 Jan 2018 15:02:41 +0000 Subject: [PATCH 09/13] Remove error when DFU enabled --- lib_xua/src/core/audiohub/xua_audiohub.xc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index f251762b..b72dd1c5 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -1402,6 +1402,11 @@ void SpdifTxWrapper(chanend c_spdif_tx) } #endif +#if XUA_DFU_EN +[[distributable]] +void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd); +#endif + /* This function is a dummy version of the deliver thread that does not connect to the codec ports. It is used during DFU reset. */ From bc4fe5223d1256c53b908addc091075a6d371dab Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Fri, 5 Jan 2018 15:03:24 +0000 Subject: [PATCH 10/13] Fix DSD implementation (HW tested for DSD64 & DSD128) --- lib_xua/src/core/audiohub/xua_audiohub.xc | 111 +++++++++++----------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index b72dd1c5..389208ac 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -312,7 +312,8 @@ static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, co /* This function performs the DSD native loop and outputs a 32b DSD stream per loop */ -static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ +static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide) +{ #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) /* 8 bits per chan, 1st 1-bit sample in MSB */ dsdSample_l = samplesOut[0]; @@ -360,69 +361,69 @@ static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, uns /* This function performs the DOP loop and collects 16b of DSD per loop and outputs a 32b word into the port buffer every other cycle. */ -static inline void DoDsdDop(unsigned &everyOther, unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide){ +static inline void DoDsdDop(int &everyOther, unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide) +{ #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) if(!everyOther) - { - dsdSample_l = ((samplesOut[0] & 0xffff00) << 8); - dsdSample_r = ((samplesOut[1] & 0xffff00) << 8); + { + dsdSample_l = ((samplesOut[0] & 0xffff00) << 8); + dsdSample_r = ((samplesOut[1] & 0xffff00) << 8); - everyOther = 1; + everyOther = 1; #ifndef __XS2A__ - switch (divide) - { - case 8: - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - break; - - case 4: - p_dsd_clk <: 0xCCCCCCCC; - p_dsd_clk <: 0xCCCCCCCC; - break; - - case 2: - p_dsd_clk <: 0xAAAAAAAA; - break; - } -#endif // __XS2A__ - } - else // everyOther + switch (divide) { - everyOther = 0; - dsdSample_l = dsdSample_l | ((samplesOut[0] & 0xffff00) >> 8); - dsdSample_r = dsdSample_r | ((samplesOut[1] & 0xffff00) >> 8); + case 8: + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + break; - // Output 16 clocks DSD to all - //p_dsd_dac[0] <: bitrev(dsdSample_l); - //p_dsd_dac[1] <: bitrev(dsdSample_r); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(bitrev(dsdSample_l))); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(bitrev(dsdSample_r))); + case 4: + p_dsd_clk <: 0xCCCCCCCC; + p_dsd_clk <: 0xCCCCCCCC; + break; + + case 2: + p_dsd_clk <: 0xAAAAAAAA; + break; + } +#endif // __XS2A__ + } +else // everyOther + { + everyOther = 0; + dsdSample_l = dsdSample_l | ((samplesOut[0] & 0xffff00) >> 8); + dsdSample_r = dsdSample_r | ((samplesOut[1] & 0xffff00) >> 8); + + // Output 16 clocks DSD to all + //p_dsd_dac[0] <: bitrev(dsdSample_l); + //p_dsd_dac[1] <: bitrev(dsdSample_r); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(bitrev(dsdSample_l))); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(bitrev(dsdSample_r))); #ifndef __XS2A__ - switch (divide) - { - case 8: - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - p_dsd_clk <: 0xF0F0F0F0; - break; + switch (divide) + { + case 8: + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + p_dsd_clk <: 0xF0F0F0F0; + break; - case 4: - p_dsd_clk <: 0xCCCCCCCC; - p_dsd_clk <: 0xCCCCCCCC; - break; + case 4: + p_dsd_clk <: 0xCCCCCCCC; + p_dsd_clk <: 0xCCCCCCCC; + break; - case 2: - p_dsd_clk <: 0xAAAAAAAA; - break; - } -#endif // __XS2A__ + case 2: + p_dsd_clk <: 0xAAAAAAAA; + break; } +#endif // __XS2A__ } #endif } @@ -432,7 +433,7 @@ static inline void DoDsdDop(unsigned &everyOther, unsigned samplesOut[], unsigne When in DoP mode, this function will check for a single absence of the DoP marker and exit deliver() with the command to restart in I2S mode. */ -static inline void DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker){ +static inline int DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker){ #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) /* Check for DSD - note we only move into DoP mode if valid DoP Freq */ /* Currently we only check on channel 0 - we get all 0's on channels without data */ @@ -478,6 +479,7 @@ static inline void DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curS } } #endif + return 1; } @@ -913,7 +915,8 @@ unsigned static deliver_master(chanend ?c_out, chanend ?c_spd_out doI2SClocks(divide); } // !dsdMode - DoDsdDopCheck(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); + int ret = DoDsdDopCheck(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker); + if (ret == 0) return 0; #ifdef I2S_MODE_TDM /* Increase frameCount by 2 since we have output two channels (per data line) */ From fe3211b0fcf1272c4a75ff65eeb0667b5d48b691 Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Fri, 5 Jan 2018 15:49:14 +0000 Subject: [PATCH 11/13] DSD native XS2 fix --- lib_xua/src/core/audiohub/xua_audiohub.xc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 389208ac..8d338ff6 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -321,13 +321,14 @@ static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, uns dsdSample_r = bitrev(byterev(dsdSample_r)); dsdSample_l = bitrev(byterev(dsdSample_l)); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); + asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); + #ifndef __XS2A__ /* Output DSD data to ports then 32 clocks */ switch (divide) { case 4: - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); p_dsd_clk <: 0xCCCCCCCC; p_dsd_clk <: 0xCCCCCCCC; p_dsd_clk <: 0xCCCCCCCC; @@ -335,16 +336,12 @@ static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, uns break; case 2: - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); p_dsd_clk <: 0xAAAAAAAA; p_dsd_clk <: 0xAAAAAAAA; break; default: /* Do some clocks anyway - this will stop us interrupting decouple too much */ - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l)); - asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r)); p_dsd_clk <: 0xF0F0F0F0; p_dsd_clk <: 0xF0F0F0F0; p_dsd_clk <: 0xF0F0F0F0; From 256ee957cffd6536c2c06ac6af120799ae08df43 Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 10 Jan 2018 09:23:20 +0000 Subject: [PATCH 12/13] Remove warning when DFU not enabled --- lib_xua/src/core/audiohub/xua_audiohub.xc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 202fb783..e3d1ebe5 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -1420,6 +1420,7 @@ void testct_byref(chanend c, int &returnVal) returnVal = 1; } +#if (XUA_DFU_EN == 1) [[combinable]] static void dummy_deliver(chanend ?c_out, unsigned &command) { @@ -1465,6 +1466,7 @@ static void dummy_deliver(chanend ?c_out, unsigned &command) } } } +#endif void XUA_AudioHub(chanend ?c_mix_out #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) From 85a22bbbf3aa5be5bfc8f98cfa7f0aee4b63930a Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Wed, 10 Jan 2018 09:23:51 +0000 Subject: [PATCH 13/13] FIx #define issue from merge --- lib_xua/src/core/audiohub/xua_audiohub.xc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index e3d1ebe5..b89798c3 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -1229,7 +1229,7 @@ unsigned static deliver_slave(chanend ?c_out, chanend ?c_spd_out /* Request digital data (with prefill) */ outuint(c_dig_rx, 0); #endif -#if defined(SPDIF_TX) && (NUM_USB_CHAN_OUT > 0) +#if ((XUA_SPDIF_TX_EN) && (NUM_USB_CHAN_OUT > 0)) outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to S/PDIF Tx thread */ unsigned sample = samplesOut[SPDIF_TX_INDEX + 1]; outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */ @@ -1723,7 +1723,7 @@ void XUA_AudioHub(chanend ?c_mix_out #else command = deliver_master(c_mix_out #endif -#ifdef XUA_SPDIF_TX_EN +#if (XUA_SPDIF_TX_EN) , c_spdif_out #else , null