Skip to content

Commit

Permalink
Vanilla sw_pll now called sw_pll_lut
Browse files Browse the repository at this point in the history
  • Loading branch information
ed-xmos committed Nov 29, 2023
1 parent c7bddf5 commit 29c1f6c
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 131 deletions.
28 changes: 14 additions & 14 deletions examples/i2s_slave_lut/src/i2s_slave_sw_pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ static i2s_restart_t i2s_restart_check(void *app_data){
old_mclk_pt = mclk_pt;
old_bclk_pt = bclk_pt;

sw_pll_do_control(cb_args->sw_pll, mclk_pt, bclk_pt);
sw_pll_lut_do_control(cb_args->sw_pll, mclk_pt, bclk_pt);

if(cb_args->sw_pll->lock_status != cb_args->curr_lock_status){
cb_args->curr_lock_status = cb_args->sw_pll->lock_status;
Expand Down Expand Up @@ -175,19 +175,19 @@ void sw_pll_test(void){
printf("Initialising SW PLL\n");

sw_pll_state_t sw_pll;
sw_pll_init(&sw_pll,
SW_PLL_15Q16(0.0),
SW_PLL_15Q16(1.0),
SW_PLL_15Q16(0.0),
CONTROL_LOOP_COUNT,
PLL_RATIO,
BCLKS_PER_LRCLK,
frac_values_80,
SW_PLL_NUM_LUT_ENTRIES(frac_values_80),
APP_PLL_CTL_12288,
APP_PLL_DIV_12288,
APP_PLL_NOMINAL_INDEX_12288,
PPM_RANGE);
sw_pll_lut_init(&sw_pll,
SW_PLL_15Q16(0.0),
SW_PLL_15Q16(1.0),
SW_PLL_15Q16(0.0),
CONTROL_LOOP_COUNT,
PLL_RATIO,
BCLKS_PER_LRCLK,
frac_values_80,
SW_PLL_NUM_LUT_ENTRIES(frac_values_80),
APP_PLL_CTL_12288,
APP_PLL_DIV_12288,
APP_PLL_NOMINAL_INDEX_12288,
PPM_RANGE);


printf("i_windup_limit: %ld\n", sw_pll.pi_state.i_windup_limit);
Expand Down
28 changes: 14 additions & 14 deletions examples/simple_lut/src/simple_sw_pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ void sw_pll_test(void){
setup_recovered_ref_clock_output(p_recovered_ref_clk, clk_recovered_ref_clk, p_mclk, PLL_RATIO);

sw_pll_state_t sw_pll;
sw_pll_init(&sw_pll,
SW_PLL_15Q16(0.0),
SW_PLL_15Q16(1.0),
SW_PLL_15Q16(0.0),
CONTROL_LOOP_COUNT,
PLL_RATIO,
0,
frac_values_80,
SW_PLL_NUM_LUT_ENTRIES(frac_values_80),
APP_PLL_CTL_12288,
APP_PLL_DIV_12288,
APP_PLL_NOMINAL_INDEX_12288,
PPM_RANGE);
sw_pll_lut_init(&sw_pll,
SW_PLL_15Q16(0.0),
SW_PLL_15Q16(1.0),
SW_PLL_15Q16(0.0),
CONTROL_LOOP_COUNT,
PLL_RATIO,
0,
frac_values_80,
SW_PLL_NUM_LUT_ENTRIES(frac_values_80),
APP_PLL_CTL_12288,
APP_PLL_DIV_12288,
APP_PLL_NOMINAL_INDEX_12288,
PPM_RANGE);

sw_pll_lock_status_t lock_status = SW_PLL_LOCKED;

Expand All @@ -61,7 +61,7 @@ void sw_pll_test(void){
uint16_t mclk_pt = port_get_trigger_time(p_ref_clk);// Get the port timer val from p_ref_clk (which is running from MCLK). So this is basically a 16 bit free running counter running from MCLK.

uint32_t t0 = get_reference_time();
sw_pll_do_control(&sw_pll, mclk_pt, 0);
sw_pll_lut_do_control(&sw_pll, mclk_pt, 0);
uint32_t t1 = get_reference_time();
if(t1 - t0 > max_time){
max_time = t1 - t0;
Expand Down
109 changes: 55 additions & 54 deletions lib_sw_pll/api/sw_pll.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,52 +24,6 @@
* @{
*/


/**
* sw_pll initialisation function.
*
* This must be called before use of sw_pll_do_control.
* Call this passing a pointer to the sw_pll_state_t stuct declared locally.
*
* \param sw_pll Pointer to the struct to be initialised.
* \param Kp Proportional PI constant. Use SW_PLL_15Q16() to convert from a float.
* \param Ki Integral PI constant. Use SW_PLL_15Q16() to convert from a float.
* \param Kii Double integral PI constant. Use SW_PLL_15Q16() to convert from a float.
* \param loop_rate_count How many counts of the call to sw_pll_do_control before control is done.
* Note this is only used by sw_pll_do_control. sw_pll_do_control_from_error
* calls the control loop every time so this is ignored.
* \param pll_ratio Integer ratio between input reference clock and the PLL output.
* Only used by sw_pll_do_control. Don't care otherwise.
* \param ref_clk_expected_inc Expected ref clock increment each time sw_pll_do_control is called.
* Pass in zero if you are sure the mclk sampling timing is precise. This
* will disable the scaling of the mclk count inside sw_pll_do_control.
* Only used by sw_pll_do_control. Don't care otherwise.
* \param lut_table_base Pointer to the base of the fractional PLL LUT used
* \param num_lut_entries Number of entries in the LUT (half sizeof since entries are 16b)
* \param app_pll_ctl_reg_val The setting of the app pll control register.
* \param app_pll_div_reg_val The setting of the app pll divider register.
* \param nominal_lut_idx The index into the LUT which gives the nominal output. Normally
* close to halfway to allow symmetrical range.
* \param ppm_range The pre-calculated PPM range. Used to determine the maximum deviation
* of counted mclk before the PLL resets its state.
* Note this is only used by sw_pll_do_control. sw_pll_do_control_from_error
* calls the control loop every time so this is ignored.
*
*/
void sw_pll_init( sw_pll_state_t * const sw_pll,
const sw_pll_15q16_t Kp,
const sw_pll_15q16_t Ki,
const sw_pll_15q16_t Kii,
const size_t loop_rate_count,
const size_t pll_ratio,
const uint32_t ref_clk_expected_inc,
const int16_t * const lut_table_base,
const size_t num_lut_entries,
const uint32_t app_pll_ctl_reg_val,
const uint32_t app_pll_div_reg_val,
const unsigned nominal_lut_idx,
const unsigned ppm_range);

/**
* Helper to do a partial init of the PI controller at runtime without setting the physical PLL and LUT settings.
*
Expand Down Expand Up @@ -112,7 +66,54 @@ static inline void sw_pll_reset(sw_pll_state_t *sw_pll, sw_pll_15q16_t Kp, sw_pl
*/

/**
* sw_pll control function.
* sw_lut_pll initialisation function.
*
* This must be called before use of sw_pll_lut_do_control.
* Call this passing a pointer to the sw_pll_state_t stuct declared locally.
*
* \param sw_pll Pointer to the struct to be initialised.
* \param Kp Proportional PI constant. Use SW_PLL_15Q16() to convert from a float.
* \param Ki Integral PI constant. Use SW_PLL_15Q16() to convert from a float.
* \param Kii Double integral PI constant. Use SW_PLL_15Q16() to convert from a float.
* \param loop_rate_count How many counts of the call to sw_pll_lut_do_control before control is done.
* Note this is only used by sw_pll_lut_do_control. sw_pll_lut_do_control_from_error
* calls the control loop every time so this is ignored.
* \param pll_ratio Integer ratio between input reference clock and the PLL output.
* Only used by sw_pll_lut_do_control. Don't care otherwise.
* \param ref_clk_expected_inc Expected ref clock increment each time sw_pll_lut_do_control is called.
* Pass in zero if you are sure the mclk sampling timing is precise. This
* will disable the scaling of the mclk count inside sw_pll_lut_do_control.
* Only used by sw_pll_lut_do_control. Don't care otherwise.
* \param lut_table_base Pointer to the base of the fractional PLL LUT used
* \param num_lut_entries Number of entries in the LUT (half sizeof since entries are 16b)
* \param app_pll_ctl_reg_val The setting of the app pll control register.
* \param app_pll_div_reg_val The setting of the app pll divider register.
* \param nominal_lut_idx The index into the LUT which gives the nominal output. Normally
* close to halfway to allow symmetrical range.
* \param ppm_range The pre-calculated PPM range. Used to determine the maximum deviation
* of counted mclk before the PLL resets its state.
* Note this is only used by sw_pll_lut_do_control. sw_pll_lut_do_control_from_error
* calls the control loop every time so this is ignored.
*
*/
void sw_pll_lut_init( sw_pll_state_t * const sw_pll,
const sw_pll_15q16_t Kp,
const sw_pll_15q16_t Ki,
const sw_pll_15q16_t Kii,
const size_t loop_rate_count,
const size_t pll_ratio,
const uint32_t ref_clk_expected_inc,
const int16_t * const lut_table_base,
const size_t num_lut_entries,
const uint32_t app_pll_ctl_reg_val,
const uint32_t app_pll_div_reg_val,
const unsigned nominal_lut_idx,
const unsigned ppm_range);



/**
* sw_pll LUT version control function.
*
* This must be called periodically for every reference clock transition.
* Typically, in an audio system, this would be at the I2S or reference clock input rate.
Expand All @@ -127,16 +128,16 @@ static inline void sw_pll_reset(sw_pll_state_t *sw_pll, sw_pll_15q16_t Kp, sw_pl
* to output jitter being a PLL.
*
* \param sw_pll Pointer to the struct to be initialised.
* \param mclk_pt The 16b port timer count of mclk at the time of calling sw_pll_do_control.
* \param ref_pt The 16b port timer ref ount at the time of calling sw_pll_do_control. This value
* \param mclk_pt The 16b port timer count of mclk at the time of calling sw_pll_lut_do_control.
* \param ref_pt The 16b port timer ref ount at the time of calling sw_pll_lut_do_control. This value
* is ignored when the pll is initialised with a zero ref_clk_expected_inc and the
* control loop will assume that mclk_pt sample timing is precise.
*
* \returns The lock status of the PLL. Locked or unlocked high/low. Note that
* this value is only updated when the control loop has run.
* The type is sw_pll_lock_status_t.
*/
sw_pll_lock_status_t sw_pll_do_control(sw_pll_state_t * const sw_pll, const uint16_t mclk_pt, const uint16_t ref_pt);
sw_pll_lock_status_t sw_pll_lut_do_control(sw_pll_state_t * const sw_pll, const uint16_t mclk_pt, const uint16_t ref_pt);

/**
* low level sw_pll control function for use as pure PLL control loop.
Expand All @@ -152,7 +153,7 @@ sw_pll_lock_status_t sw_pll_do_control(sw_pll_state_t * const sw_pll, const uint
* this value is only updated when the control loop is running.
* The type is sw_pll_lock_status_t.
*/
sw_pll_lock_status_t sw_pll_do_control_from_error(sw_pll_state_t * const sw_pll, int16_t error);
sw_pll_lock_status_t sw_pll_lut_do_control_from_error(sw_pll_state_t * const sw_pll, int16_t error);

/**@}*/ // END: addtogroup sw_pll_lut

Expand All @@ -179,7 +180,7 @@ sw_pll_lock_status_t sw_pll_do_control_from_error(sw_pll_state_t * const sw_pll,
* calls the control loop every time so this is ignored.
* \param pll_ratio Integer ratio between input reference clock and the PLL output.
* Only used by sw_pll_sdm_do_control. Don't care otherwise.
* \param ref_clk_expected_inc Expected ref clock increment each time sw_pll_do_control is called.
* \param ref_clk_expected_inc Expected ref clock increment each time sw_pll_sdm_do_control is called.
* Pass in zero if you are sure the mclk sampling timing is precise. This
* will disable the scaling of the mclk count inside sw_pll_sdm_do_control.
* Only used by sw_pll_sdm_do_control. Don't care otherwise.
Expand Down Expand Up @@ -226,8 +227,8 @@ void sw_pll_sdm_init(sw_pll_state_t * const sw_pll,
* to output jitter being a PLL.
*
* \param sw_pll Pointer to the struct to be initialised.
* \param mclk_pt The 16b port timer count of mclk at the time of calling sw_pll_do_control.
* \param ref_pt The 16b port timer ref ount at the time of calling sw_pll_do_control. This value
* \param mclk_pt The 16b port timer count of mclk at the time of calling sw_pll_sdm_do_control.
* \param ref_pt The 16b port timer ref ount at the time of calling sw_pll_sdm_do_control. This value
* is ignored when the pll is initialised with a zero ref_clk_expected_inc and the
* control loop will assume that mclk_pt sample timing is precise.
*
Expand Down
32 changes: 16 additions & 16 deletions lib_sw_pll/src/sw_pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,19 @@ static inline uint16_t lookup_pll_frac(sw_pll_state_t * const sw_pll, const int3
return sw_pll->lut_state.lut_table_base[frac_index];
}

void sw_pll_init( sw_pll_state_t * const sw_pll,
const sw_pll_15q16_t Kp,
const sw_pll_15q16_t Ki,
const sw_pll_15q16_t Kii,
const size_t loop_rate_count,
const size_t pll_ratio,
const uint32_t ref_clk_expected_inc,
const int16_t * const lut_table_base,
const size_t num_lut_entries,
const uint32_t app_pll_ctl_reg_val,
const uint32_t app_pll_div_reg_val,
const unsigned nominal_lut_idx,
const unsigned ppm_range)
void sw_pll_lut_init( sw_pll_state_t * const sw_pll,
const sw_pll_15q16_t Kp,
const sw_pll_15q16_t Ki,
const sw_pll_15q16_t Kii,
const size_t loop_rate_count,
const size_t pll_ratio,
const uint32_t ref_clk_expected_inc,
const int16_t * const lut_table_base,
const size_t num_lut_entries,
const uint32_t app_pll_ctl_reg_val,
const uint32_t app_pll_div_reg_val,
const unsigned nominal_lut_idx,
const unsigned ppm_range)
{
// Get PLL started and running at nominal
sw_pll_app_pll_init(get_local_tile_id(),
Expand Down Expand Up @@ -115,7 +115,7 @@ void sw_pll_init( sw_pll_state_t * const sw_pll,


__attribute__((always_inline))
inline sw_pll_lock_status_t sw_pll_do_control_from_error(sw_pll_state_t * const sw_pll, int16_t error)
inline sw_pll_lock_status_t sw_pll_lut_do_control_from_error(sw_pll_state_t * const sw_pll, int16_t error)
{
int32_t total_error = sw_pll_do_pi_ctrl(sw_pll, error);
sw_pll->lut_state.current_reg_val = lookup_pll_frac(sw_pll, total_error);
Expand All @@ -125,7 +125,7 @@ inline sw_pll_lock_status_t sw_pll_do_control_from_error(sw_pll_state_t * const
return sw_pll->lock_status;
}

sw_pll_lock_status_t sw_pll_do_control(sw_pll_state_t * const sw_pll, const uint16_t mclk_pt, const uint16_t ref_clk_pt)
sw_pll_lock_status_t sw_pll_lut_do_control(sw_pll_state_t * const sw_pll, const uint16_t mclk_pt, const uint16_t ref_clk_pt)
{
if (++sw_pll->loop_counter == sw_pll->loop_rate_count)
{
Expand All @@ -145,7 +145,7 @@ sw_pll_lock_status_t sw_pll_do_control(sw_pll_state_t * const sw_pll, const uint
else
{
sw_pll_calc_error_from_port_timers(&sw_pll->pfd_state, &sw_pll->first_loop, mclk_pt, ref_clk_pt);
sw_pll_do_control_from_error(sw_pll, sw_pll->pfd_state.mclk_diff);
sw_pll_lut_do_control_from_error(sw_pll, sw_pll->pfd_state.mclk_diff);

// Save for next iteration to calc diff
sw_pll->pfd_state.mclk_pt_last = mclk_pt;
Expand Down
30 changes: 15 additions & 15 deletions tests/test_app/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
///
/// Application to call the control loop with the parameters fully
/// controllable by an external application. This app expects the
/// sw_pll_init parameters on the commannd line. These will be integers
/// sw_pll_lut_init parameters on the commannd line. These will be integers
/// for lut_table_base, skip the parameter in the list and append the whole
/// lut to the command line
///
Expand Down Expand Up @@ -66,19 +66,19 @@ int main(int argc, char** argv) {
fprintf(stderr, "\n");

sw_pll_state_t sw_pll;
sw_pll_init( &sw_pll,
SW_PLL_15Q16(kp),
SW_PLL_15Q16(ki),
SW_PLL_15Q16(kii),
loop_rate_count,
pll_ratio,
ref_clk_expected_inc,
lut_table_base,
num_lut_entries,
app_pll_ctl_reg_val,
app_pll_div_reg_val,
nominal_lut_idx,
ppm_range);
sw_pll_lut_init( &sw_pll,
SW_PLL_15Q16(kp),
SW_PLL_15Q16(ki),
SW_PLL_15Q16(kii),
loop_rate_count,
pll_ratio,
ref_clk_expected_inc,
lut_table_base,
num_lut_entries,
app_pll_ctl_reg_val,
app_pll_div_reg_val,
nominal_lut_idx,
ppm_range);


for(;;) {
Expand All @@ -104,7 +104,7 @@ int main(int argc, char** argv) {
sscanf(read_buf, "%hu %hu", &mclk_pt, &ref_pt);
fprintf(stderr, "%hu %hu\n", mclk_pt, ref_pt);
uint32_t t0 = get_reference_time();
sw_pll_lock_status_t s = sw_pll_do_control(&sw_pll, mclk_pt, ref_pt);
sw_pll_lock_status_t s = sw_pll_lut_do_control(&sw_pll, mclk_pt, ref_pt);
uint32_t t1 = get_reference_time();

// xsim doesn't support our register and the val that was set gets
Expand Down
Loading

0 comments on commit 29c1f6c

Please sign in to comment.