diff --git a/lib_xua/module_build_info b/lib_xua/module_build_info index c327e5c2..25f5c719 100644 --- a/lib_xua/module_build_info +++ b/lib_xua/module_build_info @@ -14,7 +14,8 @@ DEPENDENT_MODULES = lib_locks(>=2.1.0) \ lib_spdif(>=5.0.0) \ lib_xassert(>=4.1.0) \ lib_xud(>=2.2.3) \ - lib_adat(>=1.0.0) + lib_adat(>=1.0.0) \ + lib_sw_pll(>=2.0.1) MODULE_XCC_FLAGS = $(XCC_FLAGS) \ -O3 \ diff --git a/lib_xua/src/core/clocking/clockgen.xc b/lib_xua/src/core/clocking/clockgen.xc index d6ebe69a..ddbe9b80 100644 --- a/lib_xua/src/core/clocking/clockgen.xc +++ b/lib_xua/src/core/clocking/clockgen.xc @@ -8,6 +8,13 @@ #include "xua_commands.h" #include "xua_clocking.h" +#ifdef __XS3A__ +extern "C" +{ + #include "sw_pll.h" +} +#endif + #if (XUA_SPDIF_RX_EN) #include "spdif.h" #endif @@ -333,490 +340,496 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa /* Initial ref clock output and get timestamp */ i_pll_ref.init(); - while(1) { - select + while(1) { + select + { #ifdef LEVEL_METER_LEDS #warning Level metering enabled - case t_level when timerafter(levelTime) :> void: + case t_level when timerafter(levelTime) :> void: - levelTime += LEVEL_UPDATE_RATE; + levelTime += LEVEL_UPDATE_RATE; - /* Copy over level data and reset */ - for(int i = 0; i< NUM_USB_CHAN_IN; i++) - { - int tmp; - - /* Read level data */ - //g_inputLevelData[i] = samples_to_host_inputs[i]; - asm volatile("ldw %0, %1[%2]":"=r"(tmp):"r"((const int *)samples_to_host_inputs),"r"(i)); - g_inputLevelData[i] = tmp; - - /* Reset level data */ - //samples_to_host_inputs[i] = 0; - asm volatile("stw %0, %1[%2]"::"r"(0),"r"((const int *)samples_to_host_inputs),"r"(i)); - - /* Guard against host polling slower than timer and missing peaks */ - asm volatile("ldw %0, %1[%2]":"=r"(tmp):"r"((const int *)samples_to_host_inputs_buff),"r"(i)); - - if (g_inputLevelData[i] > tmp) - //if(g_inputLevelData[i] > samples_to_host_inputs_buff[i]) + /* Copy over level data and reset */ + for(int i = 0; i< NUM_USB_CHAN_IN; i++) { - //samples_to_host_inputs_buff[i] = g_inputLevelData[i]; - asm volatile("stw %0, %1[%2]"::"r"(tmp),"r"((const int *)samples_to_host_inputs),"r"(i)); - } - } + int tmp; - /* Call user LED refresh */ - VendorLedRefresh(g_inputLevelData); + /* Read level data */ + //g_inputLevelData[i] = samples_to_host_inputs[i]; + asm volatile("ldw %0, %1[%2]":"=r"(tmp):"r"((const int *)samples_to_host_inputs),"r"(i)); + g_inputLevelData[i] = tmp; - break; -#endif + /* Reset level data */ + //samples_to_host_inputs[i] = 0; + asm volatile("stw %0, %1[%2]"::"r"(0),"r"((const int *)samples_to_host_inputs),"r"(i)); - /* Updates to clock settings from endpoint 0 */ - case inuint_byref(c_clk_ctl, tmp): - switch(tmp) - { - case GET_SEL: - chkct(c_clk_ctl, XS1_CT_END); + /* Guard against host polling slower than timer and missing peaks */ + asm volatile("ldw %0, %1[%2]":"=r"(tmp):"r"((const int *)samples_to_host_inputs_buff),"r"(i)); - /* Send back current clock mode */ - outuint(c_clk_ctl, clkMode); - outct(c_clk_ctl, XS1_CT_END); - - break; - - case SET_SEL: - /* Update clock mode */ - clkMode = inuint(c_clk_ctl); - chkct(c_clk_ctl, XS1_CT_END); - -#ifdef CLOCK_VALIDITY_CALL - switch(clkMode) + if (g_inputLevelData[i] > tmp) + //if(g_inputLevelData[i] > samples_to_host_inputs_buff[i]) { - case CLOCK_INTERNAL: - VendorClockValidity(1); - break; -#if (XUA_ADAT_RX_EN) - case CLOCK_ADAT: - VendorClockValidity(clockValid[CLOCK_ADAT]); - break; -#endif -#if (XUA_SPDIF_RX_EN) - case CLOCK_SPDIF: - VendorClockValidity(clockValid[CLOCK_SPDIF]); - break; -#endif + //samples_to_host_inputs_buff[i] = g_inputLevelData[i]; + asm volatile("stw %0, %1[%2]"::"r"(tmp),"r"((const int *)samples_to_host_inputs),"r"(i)); } -#endif - break; - - case GET_VALID: - /* Clock Unit Index */ - tmp = inuint(c_clk_ctl); - chkct(c_clk_ctl, XS1_CT_END); - outuint(c_clk_ctl, clockValid[tmp]); - outct(c_clk_ctl, XS1_CT_END); - break; - - case GET_FREQ: - tmp = inuint(c_clk_ctl); - chkct(c_clk_ctl, XS1_CT_END); - outuint(c_clk_ctl, clockFreq[tmp]); - outct(c_clk_ctl, XS1_CT_END); - break; - - case SET_SMUX: - smux = inuint(c_clk_ctl); -#if (XUA_ADAT_RX_EN) - adatRd = 0; /* Reset adat FIFO */ - adatWr = 0; - adatSamps = 0; -#endif - chkct(c_clk_ctl, XS1_CT_END); - break; - - default: -#ifdef VENDOR_AUDCORE_REQS - if(VendorAudCoreReqs(tmp, c_clk_ctl)) -#endif - printstrln("ERR: Bad req in clockgen\n"); - break; - } - - break; - - /* Generate local clock from timer */ - case t_local when timerafter(timeNextEdge) :> void: - - /* Setup next local clock edge */ - i_pll_ref.toggle_timed(0); - - /* Record time of edge */ - timeLastEdge = timeNextEdge; - - /* Setup for next edge */ - timeNextClockDetection = timeNextEdge + (LOCAL_CLOCK_INCREMENT/2); - timeNextEdge += LOCAL_CLOCK_INCREMENT; - - /* If we are in an external clock mode and this fire, then clock invalid - * reset counters in case we are moved to digital clock - we want a well timed - * first edge */ -#if (XUA_SPDIF_RX_EN) - spdifCounters.receivedSamples = 0; -#endif -#if (XUA_ADAT_RX_EN) - adatCounters.receivedSamples = 0; -#endif - -#ifdef CLOCK_VALIDITY_CALL - if(clkMode == CLOCK_INTERNAL) - { - /* Internal clock always valid */ - VendorClockValidity(1); - } -#endif - break; - -#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) - case t_external when timerafter(timeNextClockDetection) :> void: - { - int valid; - timeNextClockDetection += (LOCAL_CLOCK_INCREMENT); -#if (XUA_SPDIF_RX_EN) - /* Returns 1 if valid clock found */ - valid = validSamples(spdifCounters, CLOCK_SPDIF); - setClockValidity(c_clk_int, CLOCK_SPDIF, valid, clkMode); -#endif -#if (XUA_ADAT_RX_EN) - /* Returns 1 if valid clock found */ - valid = validSamples(adatCounters, CLOCK_ADAT); - setClockValidity(c_clk_int, CLOCK_ADAT, valid, clkMode); -#endif - } - break; -#endif - -#if (XUA_SPDIF_RX_EN) - /* Receive sample from S/PDIF RX thread (streaming chan) */ - case c_spdif_rx :> spdifRxData: - - /* Record time of sample */ - t_local :> spdifRxTime; - - /* Check parity and ignore if bad */ - if(spdif_rx_check_parity(spdifRxData)) - continue; - - /* Get preamble */ - unsigned preamble = spdifRxData & SPDIF_RX_PREAMBLE_MASK; - - switch(preamble) - { - /* LEFT */ - case SPDIF_FRAME_X: - case SPDIF_FRAME_Z: - spdifLeft = SPDIF_RX_EXTRACT_SAMPLE(spdifRxData); - break; - - /* RIGHT */ - case SPDIF_FRAME_Y: - - /* Only store sample if not in overflow and stream is reasonably valid */ - if(!spdifOverflow && clockValid[CLOCK_SPDIF]) - { - /* Store left and right sample pair to buffer */ - spdifSamples[spdifWr] = spdifLeft; - spdifSamples[spdifWr+1] = SPDIF_RX_EXTRACT_SAMPLE(spdifRxData); - - spdifWr = (spdifWr + 2) & (MAX_SPDIF_SAMPLES - 1); - - spdifSamps += 2; - - /* Check for over flow */ - if(spdifSamps > MAX_SPDIF_SAMPLES-1) - { - spdifOverflow = 1; - } - - /* Check for coming out of under flow */ - if(spdifUnderflow && (spdifSamps >= (MAX_SPDIF_SAMPLES >> 1))) - { - spdifUnderflow = 0; - } - } - break; - - default: - /* Bad sample, skip */ - continue; - break; } - spdifCounters.samples += 1; + /* Call user LED refresh */ + VendorLedRefresh(g_inputLevelData); - if(clkMode == CLOCK_SPDIF && clockValid[CLOCK_SPDIF]) - { - spdifCounters.receivedSamples+=1; - - /* Inspect for if we need to produce an edge */ - if((spdifCounters.receivedSamples >= spdifCounters.samplesPerTick)) - { - /* Check edge is about right... S/PDIF may have changed freq... */ - if(timeafter(spdifRxTime, (timeLastEdge + LOCAL_CLOCK_INCREMENT - LOCAL_CLOCK_MARGIN))) - { - /* Record edge time */ - timeLastEdge = spdifRxTime; - - /* Setup for next edge */ - timeNextEdge = spdifRxTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN; - - /* Toggle edge */ - i_pll_ref.toggle_timed(1); - - /* Reset counters */ - spdifCounters.receivedSamples = 0; - } - } - } - break; -#endif -#if (XUA_ADAT_RX_EN) - /* receive sample from ADAT rx thread (streaming channel with CT_END) */ - case inuint_byref(c_adat_rx, tmp): - /* record time of sample */ - t_local :> adatReceivedTime; - - /* Sync is: 1 | (user_byte << 4) */ - if(tmp&1) - { - /* user bits - start of frame */ - adatChannel = 0; - continue; - } - else - { - /* audio sample */ - adatSamplesEver++; - adatFrame[adatChannel] = tmp; - - adatChannel++; - if (adatChannel == 8) - { - /* only store left samples if not in overflow and stream is reasonably valid */ - if (!adatOverflow && clockValid[CLOCK_ADAT]) - { - /* Unpick the SMUX.. */ - if(smux == 2) - { - adatSamples[adatWr + 0] = adatFrame[0]; - adatSamples[adatWr + 1] = adatFrame[4]; - adatSamples[adatWr + 2] = adatFrame[1]; - adatSamples[adatWr + 3] = adatFrame[5]; - adatSamples[adatWr + 4] = adatFrame[2]; - adatSamples[adatWr + 5] = adatFrame[6]; - adatSamples[adatWr + 6] = adatFrame[3]; - adatSamples[adatWr + 7] = adatFrame[7]; - } - else if(smux) - { - - adatSamples[adatWr + 0] = adatFrame[0]; - adatSamples[adatWr + 1] = adatFrame[2]; - adatSamples[adatWr + 2] = adatFrame[4]; - adatSamples[adatWr + 3] = adatFrame[6]; - adatSamples[adatWr + 4] = adatFrame[1]; - adatSamples[adatWr + 5] = adatFrame[3]; - adatSamples[adatWr + 6] = adatFrame[5]; - adatSamples[adatWr + 7] = adatFrame[7]; - } - else - { - adatSamples[adatWr + 0] = adatFrame[0]; - adatSamples[adatWr + 1] = adatFrame[1]; - adatSamples[adatWr + 2] = adatFrame[2]; - adatSamples[adatWr + 3] = adatFrame[3]; - adatSamples[adatWr + 4] = adatFrame[4]; - adatSamples[adatWr + 5] = adatFrame[5]; - adatSamples[adatWr + 6] = adatFrame[6]; - adatSamples[adatWr + 7] = adatFrame[7]; - } - adatWr = (adatWr + 8) & (MAX_ADAT_SAMPLES - 1); - adatSamps += 8; - - /* check for overflow */ - if (adatSamps > MAX_ADAT_SAMPLES - 1) - { - adatOverflow = 1; - } - - /* check for coming out of underflow */ - if (adatUnderflow && (adatSamps >= (MAX_ADAT_SAMPLES >> 1))) - { - adatUnderflow = 0; - } - } - } - if(adatChannel == 4 || adatChannel == 8) - { - adatCounters.samples += 1; - - if (clkMode == CLOCK_ADAT && clockValid[CLOCK_ADAT]) - { - adatCounters.receivedSamples += 1; - - /* Inspect for if we need to produce an edge */ - if ((adatCounters.receivedSamples >= adatCounters.samplesPerTick)) - { - /* Check edge is about right... ADAT may have changed freq... */ - if (timeafter(adatReceivedTime, (timeLastEdge + LOCAL_CLOCK_INCREMENT - LOCAL_CLOCK_MARGIN))) - { - /* Record edge time */ - timeLastEdge = adatReceivedTime; - - /* Setup for next edge */ - timeNextEdge = adatReceivedTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN; - - /* Toggle edge */ - i_pll_ref.toggle_timed(1); - - /* Reset counters */ - adatCounters.receivedSamples = 0; - } - } - } - } - if (adatChannel == 8) - adatChannel = 0; - } break; #endif -#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) - /* AudioHub requests data */ - case inuint_byref(c_dig_rx, tmp): + /* Updates to clock settings from endpoint 0 */ + case inuint_byref(c_clk_ctl, tmp): + switch(tmp) + { + case GET_SEL: + chkct(c_clk_ctl, XS1_CT_END); + + /* Send back current clock mode */ + outuint(c_clk_ctl, clkMode); + outct(c_clk_ctl, XS1_CT_END); + + break; + + case SET_SEL: + /* Update clock mode */ + clkMode = inuint(c_clk_ctl); + chkct(c_clk_ctl, XS1_CT_END); + +#ifdef CLOCK_VALIDITY_CALL + switch(clkMode) + { + case CLOCK_INTERNAL: + VendorClockValidity(1); + break; +#if (XUA_ADAT_RX_EN) + case CLOCK_ADAT: + VendorClockValidity(clockValid[CLOCK_ADAT]); + break; +#endif #if (XUA_SPDIF_RX_EN) - if(spdifUnderflow) - { - /* S/PDIF underflowing, send out zero samples */ - g_digData[0] = 0; - g_digData[1] = 0; + case CLOCK_SPDIF: + VendorClockValidity(clockValid[CLOCK_SPDIF]); + break; +#endif + } +#endif + break; + + case GET_VALID: + /* Clock Unit Index */ + tmp = inuint(c_clk_ctl); + chkct(c_clk_ctl, XS1_CT_END); + outuint(c_clk_ctl, clockValid[tmp]); + outct(c_clk_ctl, XS1_CT_END); + break; + + case GET_FREQ: + tmp = inuint(c_clk_ctl); + chkct(c_clk_ctl, XS1_CT_END); + outuint(c_clk_ctl, clockFreq[tmp]); + outct(c_clk_ctl, XS1_CT_END); + break; + + case SET_SMUX: + smux = inuint(c_clk_ctl); +#if (XUA_ADAT_RX_EN) + adatRd = 0; /* Reset adat FIFO */ + adatWr = 0; + adatSamps = 0; +#endif + chkct(c_clk_ctl, XS1_CT_END); + break; + + default: +#ifdef VENDOR_AUDCORE_REQS + if(VendorAudCoreReqs(tmp, c_clk_ctl)) +#endif + printstrln("ERR: Bad req in clockgen\n"); + break; } - else - { - /* Read out samples from S/PDIF buffer and send... */ - tmp = spdifSamples[spdifRd]; - tmp2 = spdifSamples[spdifRd + 1]; - spdifRd += 2; - spdifRd &= (MAX_SPDIF_SAMPLES - 1); + break; - g_digData[0] = tmp; - g_digData[1] = tmp2; + /* Generate local clock from timer */ + case t_local when timerafter(timeNextEdge) :> void: - spdifSamps -= 2; + /* Setup next local clock edge */ + i_pll_ref.toggle_timed(0); + printstr("d\n"); - /* spdifSamps could go to -1 */ - if(spdifSamps < 0) - { - /* We're out of S/PDIF samples, mark underflow condition */ - spdifUnderflow = 1; - spdifLeft = 0; - } - /* If we are in over flow condition and we have a sensible number of samples - * come out of overflow condition */ - if(spdifOverflow && (spdifSamps < (MAX_SPDIF_SAMPLES>>1))) - { - spdifOverflow = 0; - } - } + /* Record time of edge */ + timeLastEdge = timeNextEdge; + + /* Setup for next edge */ + timeNextClockDetection = timeNextEdge + (LOCAL_CLOCK_INCREMENT/2); + timeNextEdge += LOCAL_CLOCK_INCREMENT; + + /* If we are in an external clock mode and this fire, then clock invalid + * reset counters in case we are moved to digital clock - we want a well timed + * first edge */ +#if (XUA_SPDIF_RX_EN) + spdifCounters.receivedSamples = 0; #endif #if (XUA_ADAT_RX_EN) - if (adatUnderflow) - { - /* ADAT underflowing, send out zero samples */ - g_digData[2] = 0; - g_digData[3] = 0; - g_digData[4] = 0; - g_digData[5] = 0; - g_digData[6] = 0; - g_digData[7] = 0; - g_digData[8] = 0; - g_digData[9] = 0; - } - else - { - /* read out samples from the ADAT buffer and send */ - /* always return 8 samples */ - /* SMUX II mode */ - if (smux == 2) - { - /* SMUX2 mode - 2 samples from fifo and 4 zero samples */ - g_digData[2] = adatSamples[adatRd + 0]; - g_digData[3] = adatSamples[adatRd + 1]; + adatCounters.receivedSamples = 0; +#endif +#ifdef CLOCK_VALIDITY_CALL + if(clkMode == CLOCK_INTERNAL) + { + /* Internal clock always valid */ + VendorClockValidity(1); + } +#endif + break; + +#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) + case t_external when timerafter(timeNextClockDetection) :> void: + { + int valid; + timeNextClockDetection += (LOCAL_CLOCK_INCREMENT); +#if (XUA_SPDIF_RX_EN) + /* Returns 1 if valid clock found */ + valid = validSamples(spdifCounters, CLOCK_SPDIF); + setClockValidity(c_clk_int, CLOCK_SPDIF, valid, clkMode); +#endif +#if (XUA_ADAT_RX_EN) + /* Returns 1 if valid clock found */ + valid = validSamples(adatCounters, CLOCK_ADAT); + setClockValidity(c_clk_int, CLOCK_ADAT, valid, clkMode); +#endif + } + break; +#endif + +#if (XUA_SPDIF_RX_EN) + /* Receive sample from S/PDIF RX thread (streaming chan) */ + case c_spdif_rx :> spdifRxData: + + /* Record time of sample */ + t_local :> spdifRxTime; + + /* Check parity and ignore if bad */ + if(spdif_rx_check_parity(spdifRxData)) + continue; + + /* Get preamble */ + unsigned preamble = spdifRxData & SPDIF_RX_PREAMBLE_MASK; + + switch(preamble) + { + /* LEFT */ + case SPDIF_FRAME_X: + case SPDIF_FRAME_Z: + spdifLeft = SPDIF_RX_EXTRACT_SAMPLE(spdifRxData); + break; + + /* RIGHT */ + case SPDIF_FRAME_Y: + + /* Only store sample if not in overflow and stream is reasonably valid */ + if(!spdifOverflow && clockValid[CLOCK_SPDIF]) + { + /* Store left and right sample pair to buffer */ + spdifSamples[spdifWr] = spdifLeft; + spdifSamples[spdifWr+1] = SPDIF_RX_EXTRACT_SAMPLE(spdifRxData); + + spdifWr = (spdifWr + 2) & (MAX_SPDIF_SAMPLES - 1); + + spdifSamps += 2; + + /* Check for over flow */ + if(spdifSamps > MAX_SPDIF_SAMPLES-1) + { + spdifOverflow = 1; + } + + /* Check for coming out of under flow */ + if(spdifUnderflow && (spdifSamps >= (MAX_SPDIF_SAMPLES >> 1))) + { + spdifUnderflow = 0; + } + } + break; + + default: + /* Bad sample, skip */ + continue; + break; + } + + spdifCounters.samples += 1; + + if(clkMode == CLOCK_SPDIF && clockValid[CLOCK_SPDIF]) + { + spdifCounters.receivedSamples+=1; + + /* Inspect for if we need to produce an edge */ + if((spdifCounters.receivedSamples >= spdifCounters.samplesPerTick)) + { + /* Check edge is about right... S/PDIF may have changed freq... */ + if(timeafter(spdifRxTime, (timeLastEdge + LOCAL_CLOCK_INCREMENT - LOCAL_CLOCK_MARGIN))) + { + /* Record edge time */ + timeLastEdge = spdifRxTime; + + /* Setup for next edge */ + timeNextEdge = spdifRxTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN; + + /* Toggle edge */ + i_pll_ref.toggle_timed(1); + printstr("s\n"); + + /* Reset counters */ + spdifCounters.receivedSamples = 0; + } + } + } + break; +#endif +#if (XUA_ADAT_RX_EN) + /* receive sample from ADAT rx thread (streaming channel with CT_END) */ + case inuint_byref(c_adat_rx, tmp): + /* record time of sample */ + t_local :> adatReceivedTime; + + /* Sync is: 1 | (user_byte << 4) */ + if(tmp&1) + { + /* user bits - start of frame */ + adatChannel = 0; + continue; + } + else + { + /* audio sample */ + adatSamplesEver++; + adatFrame[adatChannel] = tmp; + + adatChannel++; + if (adatChannel == 8) + { + /* only store left samples if not in overflow and stream is reasonably valid */ + if (!adatOverflow && clockValid[CLOCK_ADAT]) + { + /* Unpick the SMUX.. */ + if(smux == 2) + { + adatSamples[adatWr + 0] = adatFrame[0]; + adatSamples[adatWr + 1] = adatFrame[4]; + adatSamples[adatWr + 2] = adatFrame[1]; + adatSamples[adatWr + 3] = adatFrame[5]; + adatSamples[adatWr + 4] = adatFrame[2]; + adatSamples[adatWr + 5] = adatFrame[6]; + adatSamples[adatWr + 6] = adatFrame[3]; + adatSamples[adatWr + 7] = adatFrame[7]; + } + else if(smux) + { + + adatSamples[adatWr + 0] = adatFrame[0]; + adatSamples[adatWr + 1] = adatFrame[2]; + adatSamples[adatWr + 2] = adatFrame[4]; + adatSamples[adatWr + 3] = adatFrame[6]; + adatSamples[adatWr + 4] = adatFrame[1]; + adatSamples[adatWr + 5] = adatFrame[3]; + adatSamples[adatWr + 6] = adatFrame[5]; + adatSamples[adatWr + 7] = adatFrame[7]; + } + else + { + adatSamples[adatWr + 0] = adatFrame[0]; + adatSamples[adatWr + 1] = adatFrame[1]; + adatSamples[adatWr + 2] = adatFrame[2]; + adatSamples[adatWr + 3] = adatFrame[3]; + adatSamples[adatWr + 4] = adatFrame[4]; + adatSamples[adatWr + 5] = adatFrame[5]; + adatSamples[adatWr + 6] = adatFrame[6]; + adatSamples[adatWr + 7] = adatFrame[7]; + } + adatWr = (adatWr + 8) & (MAX_ADAT_SAMPLES - 1); + adatSamps += 8; + + /* check for overflow */ + if (adatSamps > MAX_ADAT_SAMPLES - 1) + { + adatOverflow = 1; + } + + /* check for coming out of underflow */ + if (adatUnderflow && (adatSamps >= (MAX_ADAT_SAMPLES >> 1))) + { + adatUnderflow = 0; + } + } + } + if(adatChannel == 4 || adatChannel == 8) + { + adatCounters.samples += 1; + + if (clkMode == CLOCK_ADAT && clockValid[CLOCK_ADAT]) + { + adatCounters.receivedSamples += 1; + + /* Inspect for if we need to produce an edge */ + if ((adatCounters.receivedSamples >= adatCounters.samplesPerTick)) + { + /* Check edge is about right... ADAT may have changed freq... */ + if (timeafter(adatReceivedTime, (timeLastEdge + LOCAL_CLOCK_INCREMENT - LOCAL_CLOCK_MARGIN))) + { + /* Record edge time */ + timeLastEdge = adatReceivedTime; + + /* Setup for next edge */ + timeNextEdge = adatReceivedTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN; + + /* Toggle edge */ + i_pll_ref.toggle_timed(1); + printstr("a\n"); + + /* Reset counters */ + adatCounters.receivedSamples = 0; + } + } + } + } + if (adatChannel == 8) + adatChannel = 0; + } + break; +#endif + +#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) + /* AudioHub requests data */ + case inuint_byref(c_dig_rx, tmp): +#if (XUA_SPDIF_RX_EN) + if(spdifUnderflow) + { + /* S/PDIF underflowing, send out zero samples */ + g_digData[0] = 0; + g_digData[1] = 0; + } + else + { + /* Read out samples from S/PDIF buffer and send... */ + tmp = spdifSamples[spdifRd]; + tmp2 = spdifSamples[spdifRd + 1]; + + spdifRd += 2; + spdifRd &= (MAX_SPDIF_SAMPLES - 1); + + g_digData[0] = tmp; + g_digData[1] = tmp2; + + spdifSamps -= 2; + + /* spdifSamps could go to -1 */ + if(spdifSamps < 0) + { + /* We're out of S/PDIF samples, mark underflow condition */ + spdifUnderflow = 1; + spdifLeft = 0; + } + + /* If we are in over flow condition and we have a sensible number of samples + * come out of overflow condition */ + if(spdifOverflow && (spdifSamps < (MAX_SPDIF_SAMPLES>>1))) + { + spdifOverflow = 0; + } + } +#endif +#if (XUA_ADAT_RX_EN) + if (adatUnderflow) + { + /* ADAT underflowing, send out zero samples */ + g_digData[2] = 0; + g_digData[3] = 0; g_digData[4] = 0; g_digData[5] = 0; g_digData[6] = 0; g_digData[7] = 0; g_digData[8] = 0; g_digData[9] = 0; - adatRd = (adatRd + 2) & (MAX_ADAT_SAMPLES - 1); - adatSamps -= 2; - } - else if(smux) - { - /* SMUX mode - 4 samples from fifo and 4 zero samples */ - g_digData[2] = adatSamples[adatRd + 0]; - g_digData[3] = adatSamples[adatRd + 1]; - g_digData[4] = adatSamples[adatRd + 2]; - g_digData[5] = adatSamples[adatRd + 3]; - - g_digData[6] = 0; - g_digData[7] = 0; - g_digData[8] = 0; - g_digData[9] = 0; - adatRd = (adatRd + 4) & (MAX_ADAT_SAMPLES - 1); - adatSamps -= 4; } else { - /* no SMUX mode - 8 samples from fifo */ - g_digData[2] = adatSamples[adatRd + 0]; - g_digData[3] = adatSamples[adatRd + 1]; - g_digData[4] = adatSamples[adatRd + 2]; - g_digData[5] = adatSamples[adatRd + 3]; + /* read out samples from the ADAT buffer and send */ + /* always return 8 samples */ + /* SMUX II mode */ + if (smux == 2) + { + /* SMUX2 mode - 2 samples from fifo and 4 zero samples */ + g_digData[2] = adatSamples[adatRd + 0]; + g_digData[3] = adatSamples[adatRd + 1]; - g_digData[6] = adatSamples[adatRd + 4]; - g_digData[7] = adatSamples[adatRd + 5]; - g_digData[8] = adatSamples[adatRd + 6]; - g_digData[9] = adatSamples[adatRd + 7]; + g_digData[4] = 0; + g_digData[5] = 0; + g_digData[6] = 0; + g_digData[7] = 0; + g_digData[8] = 0; + g_digData[9] = 0; + adatRd = (adatRd + 2) & (MAX_ADAT_SAMPLES - 1); + adatSamps -= 2; + } + else if(smux) + { + /* SMUX mode - 4 samples from fifo and 4 zero samples */ + g_digData[2] = adatSamples[adatRd + 0]; + g_digData[3] = adatSamples[adatRd + 1]; + g_digData[4] = adatSamples[adatRd + 2]; + g_digData[5] = adatSamples[adatRd + 3]; - adatRd = (adatRd + 8) & (MAX_ADAT_SAMPLES - 1); - adatSamps -= 8; + g_digData[6] = 0; + g_digData[7] = 0; + g_digData[8] = 0; + g_digData[9] = 0; + adatRd = (adatRd + 4) & (MAX_ADAT_SAMPLES - 1); + adatSamps -= 4; + } + else + { + /* no SMUX mode - 8 samples from fifo */ + g_digData[2] = adatSamples[adatRd + 0]; + g_digData[3] = adatSamples[adatRd + 1]; + g_digData[4] = adatSamples[adatRd + 2]; + g_digData[5] = adatSamples[adatRd + 3]; + + g_digData[6] = adatSamples[adatRd + 4]; + g_digData[7] = adatSamples[adatRd + 5]; + g_digData[8] = adatSamples[adatRd + 6]; + g_digData[9] = adatSamples[adatRd + 7]; + + adatRd = (adatRd + 8) & (MAX_ADAT_SAMPLES - 1); + adatSamps -= 8; + } + + /* adatSamps could go to -1 */ + if (adatSamps < 0) + { + /* we're out of ADAT samples, mark underflow condition */ + adatUnderflow = 1; + } + + /* if we are in overflow condition and have a sensible number of samples + come out of overflow condition */ + if (adatOverflow && adatSamps < (MAX_ADAT_SAMPLES >> 1)) + { + adatOverflow = 0; + } } - - /* adatSamps could go to -1 */ - if (adatSamps < 0) - { - /* we're out of ADAT samples, mark underflow condition */ - adatUnderflow = 1; - } - - /* if we are in overflow condition and have a sensible number of samples - come out of overflow condition */ - if (adatOverflow && adatSamps < (MAX_ADAT_SAMPLES >> 1)) - { - adatOverflow = 0; - } - } #endif - outuint(c_dig_rx, 1); - break; + outuint(c_dig_rx, 1); + break; #endif - } - } + } /* select */ + } /* while(1) */ + } /* clkgen task scope */ }