diff --git a/lib_xua/api/xua_clocking.h b/lib_xua/api/xua_clocking.h index c4028009..c41d130f 100644 --- a/lib_xua/api/xua_clocking.h +++ b/lib_xua/api/xua_clocking.h @@ -25,8 +25,15 @@ void PllRefPinTask(server interface pll_ref_if i_pll_ref, out port p_sync); * \param c_clk_ctl channel connected to Endpoint0() for configuration of the * clock * \param c_clk_int channel connected to the decouple() thread for clock - interrupts + * interrupts + * \param p_for_mclk_count_aud port used for counting mclk and providing a timestamp */ -void clockGen(streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interface pll_ref_if i_pll_ref, chanend c_audio, chanend c_clk_ctl, chanend c_clk_int); +void clockGen( streaming chanend ?c_spdif_rx, + chanend ?c_adat_rx, + client interface pll_ref_if i_pll_ref, + chanend c_audio, + chanend c_clk_ctl, + chanend c_clk_int, + port ?p_for_mclk_count_aud); #endif diff --git a/lib_xua/src/core/clocking/clockgen.xc b/lib_xua/src/core/clocking/clockgen.xc index ddbe9b80..a49b2356 100644 --- a/lib_xua/src/core/clocking/clockgen.xc +++ b/lib_xua/src/core/clocking/clockgen.xc @@ -8,7 +8,14 @@ #include "xua_commands.h" #include "xua_clocking.h" + #ifdef __XS3A__ +#define USE_SW_PLL 1 +#else +#define USE_SW_PLL 0 +#endif + +#if USE_SW_PLL extern "C" { #include "sw_pll.h" @@ -45,6 +52,7 @@ static int clockValid[NUM_CLOCKS]; /* Store current val static int clockInt[NUM_CLOCKS]; /* Interupt flag for clocks */ static int clockId[NUM_CLOCKS]; + [[distributable]] void PllRefPinTask(server interface pll_ref_if i_pll_ref, out port p_pll_ref) { @@ -86,6 +94,17 @@ void PllRefPinTask(server interface pll_ref_if i_pll_ref, out port p_pll_ref) } } +void do_sw_pll_control(sw_pll_state_t sw_pll, unsigned short mclk_time_stamp, chanend c_sigma_delta) +{ + static unsigned count = 0; + count++; + if(count == 30) + { + printuintln(mclk_time_stamp); + count = 0; + } +} + #if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) static int abs(int x) @@ -222,6 +241,72 @@ static inline int validSamples(Counter &counter, int clockIndex) } #endif +#if USE_SW_PLL +void SigmaDeltaTask(chanend c_sigma_delta){ + while(1) + { + c_sigma_delta :> int _; + } +} + +void InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk) +{ + /* Autogenerated SDM App PLL setup by dco_model.py using 22.5792_1M profile */ + /* Input freq: 24000000 + F: 134 + R: 0 + f: 8 + p: 18 + OD: 5 + ACD: 5 + */ + + #define APP_PLL_CTL_REG_22 0x0A808600 + #define APP_PLL_DIV_REG_22 0x80000005 + #define APP_PLL_FRAC_REG_22 0x80000812 + #define SW_PLL_SDM_CTRL_MID_22 498283 + #define SW_PLL_SDM_RATE_22 1000000 + + /* Autogenerated SDM App PLL setup by dco_model.py using 24.576_1M profile */ + /* Input freq: 24000000 + F: 146 + R: 0 + f: 4 + p: 10 + OD: 5 + ACD: 5 + */ + + #define APP_PLL_CTL_REG_24 0x0A809200 + #define APP_PLL_DIV_REG_24 0x80000005 + #define APP_PLL_FRAC_REG_24 0x8000040A + #define SW_PLL_SDM_CTRL_MID_24 478151 + #define SW_PLL_SDM_RATE_24 1000000 + + + const uint32_t app_pll_ctl_reg[2] = {APP_PLL_CTL_REG_22, APP_PLL_CTL_REG_24}; + const uint32_t app_pll_div_reg[2] = {APP_PLL_DIV_REG_22, APP_PLL_DIV_REG_24}; + const uint32_t app_pll_frac_reg[2] = {APP_PLL_FRAC_REG_22, APP_PLL_FRAC_REG_24}; + const uint32_t sw_pll_sdm_ctrl_mid[2] = {SW_PLL_SDM_CTRL_MID_22, SW_PLL_SDM_CTRL_MID_24}; + // const uint32_t sw_pll_sdm_rate[2] = {SW_PLL_SDM_RATE_22, SW_PLL_SDM_RATE_24}; + + const int clkIndex = mClk == MCLK_48 ? 1 : 0; + + sw_pll_sdm_init(&sw_pll, + SW_PLL_15Q16(0.0), + SW_PLL_15Q16(32.0), + SW_PLL_15Q16(0.25), + 0, /* LOOP COUNT Don't care for this API */ + 0, /* PLL_RATIO Don't care for this API */ + 0, /* No jitter compensation needed */ + app_pll_ctl_reg[clkIndex], + app_pll_div_reg[clkIndex], + app_pll_frac_reg[clkIndex], + sw_pll_sdm_ctrl_mid[clkIndex], + 3000 /* PPM_RANGE FOR PFD Don't care for this API*/ ); +} +#endif + #ifdef LEVEL_METER_LEDS void VendorLedRefresh(unsigned levelData[]); unsigned g_inputLevelData[NUM_USB_CHAN_IN]; @@ -232,7 +317,13 @@ extern int samples_to_host_inputs_buff[NUM_USB_CHAN_IN]; int VendorAudCoreReqs(unsigned cmd, chanend c); #pragma unsafe arrays -void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interface pll_ref_if i_pll_ref, chanend c_dig_rx, chanend c_clk_ctl, chanend c_clk_int) +void clockGen ( streaming chanend ?c_spdif_rx, + chanend ?c_adat_rx, + client interface pll_ref_if i_pll_ref, + chanend c_dig_rx, + chanend c_clk_ctl, + chanend c_clk_int, + port ?p_for_mclk_count_aud) { timer t_local; unsigned timeNextEdge, timeLastEdge, timeNextClockDetection; @@ -249,6 +340,9 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa #if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) timer t_external; + unsigned short mclk_time_stamp = 0; + /* Get MCLK count */ + asm volatile(" getts %0, res[%1]" : "=r" (mclk_time_stamp) : "r" (p_for_mclk_count_aud)); #endif #if (XUA_SPDIF_RX_EN) @@ -340,9 +434,21 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa /* Initial ref clock output and get timestamp */ i_pll_ref.init(); +#if USE_SW_PLL + chan c_sigma_delta; + sw_pll_state_t sw_pll; + InitSWPLL(sw_pll, MCLK_48); + + par { + SigmaDeltaTask(c_sigma_delta); +#else + { +#endif while(1) { + // TMP + c_sigma_delta <: 0; select { #ifdef LEVEL_METER_LEDS @@ -513,6 +619,7 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa case c_spdif_rx :> spdifRxData: /* Record time of sample */ + asm volatile(" getts %0, res[%1]" : "=r" (mclk_time_stamp) : "r" (p_for_mclk_count_aud)); t_local :> spdifRxTime; /* Check parity and ignore if bad */ @@ -582,10 +689,12 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa /* Setup for next edge */ timeNextEdge = spdifRxTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN; +#if USE_SW_PLL + do_sw_pll_control(sw_pll, mclk_time_stamp, c_sigma_delta); +#else /* Toggle edge */ i_pll_ref.toggle_timed(1); - printstr("s\n"); - +#endif /* Reset counters */ spdifCounters.receivedSamples = 0; } @@ -597,6 +706,7 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa /* receive sample from ADAT rx thread (streaming channel with CT_END) */ case inuint_byref(c_adat_rx, tmp): /* record time of sample */ + asm volatile(" getts %0, res[%1]" : "=r" (mclk_time_stamp) : "r" (p_for_mclk_count_aud)); t_local :> adatReceivedTime; /* Sync is: 1 | (user_byte << 4) */ @@ -689,10 +799,13 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa /* Setup for next edge */ timeNextEdge = adatReceivedTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN; +#if USE_SW_PLL + do_sw_pll_control(sw_pll, mclk_time_stamp, c_sigma_delta); +#else /* Toggle edge */ i_pll_ref.toggle_timed(1); - printstr("a\n"); - +#endif + /* Reset counters */ adatCounters.receivedSamples = 0; } diff --git a/lib_xua/src/core/main.xc b/lib_xua/src/core/main.xc index efa8ec29..d46b6026 100755 --- a/lib_xua/src/core/main.xc +++ b/lib_xua/src/core/main.xc @@ -144,6 +144,7 @@ on tile[XUD_TILE] : in port p_spdif_rx = PORT_SPDIF_IN; #if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) /* Reference to external clock multiplier */ on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF; +on tile[AUDIO_IO_TILE] : port p_for_mclk_count_aud = PORT_MCLK_COUNT_2; #endif #ifdef MIDI @@ -309,6 +310,7 @@ void usb_audio_io(chanend ?c_aud_in, #endif #if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) , client interface pll_ref_if i_pll_ref + , port p_for_mclk_count_aud #endif ) { @@ -318,6 +320,12 @@ void usb_audio_io(chanend ?c_aud_in, #if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) chan c_dig_rx; + + /* Connect p_for_mclk_count_aud to clk_audio_mclk so we can count mclks/timestamp in digital rx*/ + unsigned x = 0; + asm("ldw %0, dp[clk_audio_mclk]":"=r"(x)); + asm("setclk res[%0], %1"::"r"(p_for_mclk_count_aud), "r"(x)); + #else #define c_dig_rx null #endif @@ -385,7 +393,7 @@ void usb_audio_io(chanend ?c_aud_in, * However, due to the use of an interface the pll reference signal port can be on another tile */ thread_speed(); - clockGen(c_spdif_rx, c_adat_rx, i_pll_ref, c_dig_rx, c_clk_ctl, c_clk_int); + clockGen(c_spdif_rx, c_adat_rx, i_pll_ref, c_dig_rx, c_clk_ctl, c_clk_int, p_for_mclk_count_aud); } #endif @@ -437,7 +445,7 @@ int main() #define c_adat_rx null #endif -#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE) +#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) chan c_spdif_tx; #endif @@ -575,6 +583,7 @@ int main() on tile[AUDIO_IO_TILE]: { + /* Audio I/O task, includes mixing etc */ usb_audio_io(c_mix_out #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) @@ -595,6 +604,7 @@ int main() #endif #if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) , i_pll_ref + , p_for_mclk_count_aud #endif ); }