forked from PAWPAW-Mirror/lib_xua
Initial loop closed
This commit is contained in:
@@ -232,6 +232,12 @@ static inline int validSamples(Counter &counter, int clockIndex)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
|
/* Pointer to sw_pll struct to allow it to be used in separate SDM thread */
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
sw_pll_state_t * unsafe sw_pll_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk)
|
unsigned InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk)
|
||||||
{
|
{
|
||||||
/* Autogenerated SDM App PLL setup by dco_model.py using 22.5792_1M profile */
|
/* Autogenerated SDM App PLL setup by dco_model.py using 22.5792_1M profile */
|
||||||
@@ -294,29 +300,26 @@ unsigned InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk)
|
|||||||
return (XS1_TIMER_HZ / sw_pll_sdm_rate[clkIndex]);
|
return (XS1_TIMER_HZ / sw_pll_sdm_rate[clkIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_sw_pll_control( sw_pll_state_t sw_pll,
|
void do_sw_pll_phase_frequency_detector( sw_pll_state_t sw_pll,
|
||||||
unsigned short mclk_time_stamp,
|
unsigned short mclk_time_stamp,
|
||||||
unsigned mclks_per_sample,
|
unsigned mclks_per_sample,
|
||||||
chanend c_sigma_delta,
|
chanend c_sigma_delta,
|
||||||
int receivedSamples)
|
int receivedSamples)
|
||||||
{
|
{
|
||||||
|
/* Keep a store of the last mclk time stamp so we can work out the increment */
|
||||||
static unsigned short last_mclk_time_stamp = 0;
|
static unsigned short last_mclk_time_stamp = 0;
|
||||||
static unsigned count = 0;
|
|
||||||
count++;
|
|
||||||
|
|
||||||
const unsigned expected_mclk_inc = mclks_per_sample * receivedSamples;
|
/* Calculate what the zero-error mclk count increment should be for this many samples */
|
||||||
const unsigned short expected_mclk_count = (last_mclk_time_stamp + expected_mclk_inc) & 0xffff;
|
const unsigned expected_mclk_inc = mclks_per_sample * receivedSamples / 2; /* divide by 2 because this fn is called per edge */
|
||||||
|
|
||||||
short f_error = (int)mclk_time_stamp - (int)expected_mclk_count;
|
/* Calculate actualy time-stamped mclk count increment is */
|
||||||
|
const unsigned short actual_mclk_inc = mclk_time_stamp - last_mclk_time_stamp;
|
||||||
|
|
||||||
|
/* The difference is the raw error in terms of mclk counts */
|
||||||
|
short f_error = (int)actual_mclk_inc - (int)expected_mclk_inc;
|
||||||
|
|
||||||
if(count == 30)
|
/* send PFD output to the sigma delta thread */
|
||||||
{
|
|
||||||
//calc mclk inc
|
|
||||||
|
|
||||||
outuint(c_sigma_delta, (unsigned) (1000000 + f_error));
|
outuint(c_sigma_delta, (unsigned) (1000000 + f_error));
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_mclk_time_stamp = mclk_time_stamp;
|
last_mclk_time_stamp = mclk_time_stamp;
|
||||||
}
|
}
|
||||||
@@ -326,9 +329,15 @@ void SigmaDeltaTask(chanend c_sigma_delta, unsigned sdm_interval){
|
|||||||
the first control value has been received. This avoids issues with
|
the first control value has been received. This avoids issues with
|
||||||
channel lockup if two tasks (eg. init and SDM) try to write at the same time. */
|
channel lockup if two tasks (eg. init and SDM) try to write at the same time. */
|
||||||
|
|
||||||
int dco_setting = 0;
|
/* To be extra safe, spin on sw_pll_ptr until it has been initialised */
|
||||||
sw_pll_sdm_state_t sdm_state;
|
while(sw_pll_ptr == NULL);
|
||||||
sw_pll_init_sigma_delta(&sdm_state);
|
|
||||||
|
int f_error = 0;
|
||||||
|
int dco_setting = SW_PLL_SDM_CTRL_MID_24; // TODO FIX ME
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
sw_pll_init_sigma_delta(&sw_pll_ptr->sdm_state);
|
||||||
|
}
|
||||||
|
|
||||||
tileref_t this_tile = get_local_tile_id();
|
tileref_t this_tile = get_local_tile_id();
|
||||||
|
|
||||||
@@ -344,8 +353,13 @@ void SigmaDeltaTask(chanend c_sigma_delta, unsigned sdm_interval){
|
|||||||
select
|
select
|
||||||
{
|
{
|
||||||
case inuint_byref(c_sigma_delta, tmp):
|
case inuint_byref(c_sigma_delta, tmp):
|
||||||
dco_setting = (int32_t)tmp;
|
f_error = (int32_t)tmp;
|
||||||
printstr("sigma-delta got: "); printintln(dco_setting);
|
printstr("sigma-delta got: "); printintln(f_error);
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
sw_pll_sdm_do_control_from_error(sw_pll_ptr, -f_error + 1000000);
|
||||||
|
dco_setting = sw_pll_ptr->sdm_state.current_ctrl_val;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Do nothing & fall-through
|
// Do nothing & fall-through
|
||||||
@@ -367,9 +381,9 @@ void SigmaDeltaTask(chanend c_sigma_delta, unsigned sdm_interval){
|
|||||||
control value. This will avoid the writing of the
|
control value. This will avoid the writing of the
|
||||||
frac reg from two different threads which may cause
|
frac reg from two different threads which may cause
|
||||||
a channel deadlock. */
|
a channel deadlock. */
|
||||||
if(dco_setting != 0)
|
if(f_error != 0)
|
||||||
{
|
unsafe {
|
||||||
sw_pll_do_sigma_delta(&sdm_state, this_tile, dco_setting);
|
sw_pll_do_sigma_delta(&sw_pll_ptr->sdm_state, this_tile, dco_setting);
|
||||||
send_ack_once = 1;
|
send_ack_once = 1;
|
||||||
}
|
}
|
||||||
else if(send_ack_once)
|
else if(send_ack_once)
|
||||||
@@ -524,6 +538,13 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
chan c_sigma_delta;
|
chan c_sigma_delta;
|
||||||
sw_pll_state_t sw_pll;
|
sw_pll_state_t sw_pll;
|
||||||
|
|
||||||
|
/* Initialise before we par off the SDM task */
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
sw_pll_ptr = &sw_pll;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned sdm_interval = InitSWPLL(sw_pll, MCLK_48);
|
unsigned sdm_interval = InitSWPLL(sw_pll, MCLK_48);
|
||||||
|
|
||||||
par
|
par
|
||||||
@@ -708,7 +729,7 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
printstr("c_mclk_change: "); printuintln(selected_mclk_rate);
|
printstr("c_mclk_change: "); printuintln(selected_mclk_rate);
|
||||||
disable_sigma_delta(c_sigma_delta); /* Blocks until SDM is idle */
|
disable_sigma_delta(c_sigma_delta); /* Blocks until SDM is idle */
|
||||||
InitSWPLL(sw_pll, selected_mclk_rate);
|
InitSWPLL(sw_pll, selected_mclk_rate);
|
||||||
outuint(c_sigma_delta, sw_pll.sdm_state.ctrl_mid_point); /* Send ctrl mid point to enable SDM */
|
outuint(c_sigma_delta, sw_pll.sdm_state.ctrl_mid_point); /* Send ctrl mid point to re-enable SDM and set to nominal mclk */
|
||||||
printstr("swpll int'd\n");
|
printstr("swpll int'd\n");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -792,7 +813,7 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
timeNextEdge = spdifRxTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
timeNextEdge = spdifRxTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
||||||
|
|
||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
do_sw_pll_control(sw_pll, mclk_time_stamp, mclks_per_sample, c_sigma_delta, spdifCounters.receivedSamples);
|
do_sw_pll_phase_frequency_detector(sw_pll, mclk_time_stamp, mclks_per_sample, c_sigma_delta, spdifCounters.receivedSamples);
|
||||||
#else
|
#else
|
||||||
/* Toggle edge */
|
/* Toggle edge */
|
||||||
i_pll_ref.toggle_timed(1);
|
i_pll_ref.toggle_timed(1);
|
||||||
@@ -902,7 +923,7 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
timeNextEdge = adatReceivedTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
timeNextEdge = adatReceivedTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
||||||
|
|
||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
do_sw_pll_control(sw_pll, mclk_time_stamp, mclks_per_sample, c_sigma_delta, adatCounters.receivedSamples);
|
do_sw_pll_phase_frequency_detector(sw_pll, mclk_time_stamp, mclks_per_sample, c_sigma_delta, adatCounters.receivedSamples);
|
||||||
#else
|
#else
|
||||||
/* Toggle edge */
|
/* Toggle edge */
|
||||||
i_pll_ref.toggle_timed(1);
|
i_pll_ref.toggle_timed(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user