Commit 48385a0a authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

software/lib: removed softpll files (uses spll from WRCore)

parent 4b397849
#include <stdio.h>
#include "board.h"
#include "hw/softpll_regs.h"
#include "irq.h"
static volatile struct SPLL_WB *SPLL = (volatile struct SPLL_WB *) BASE_SOFTPLL;
/* The includes below contain code (not only declarations) to enable the compiler
to inline functions where necessary and save some CPU cycles */
#include "spll_defs.h"
#include "spll_common.h"
#include "spll_helper.h"
volatile int irq_count = 0,eee,yyy;
struct spll_helper_state helper;
void _irq_entry()
{
volatile uint32_t trr;
int src = -1, tag;
if(! (SPLL->CSR & SPLL_TRR_CSR_EMPTY))
{
trr = SPLL->TRR_R0;
src = SPLL_TRR_R0_CHAN_ID_R(trr);
tag = SPLL_TRR_R0_VALUE_R(trr);
eee = tag;
}
helper_update(&helper, tag, src);
yyy=helper.phase.pi.y;
irq_count++;
clear_irq();
}
void spll_init()
{
volatile int dummy;
disable_irq();
SPLL->CSR= 0 ;
SPLL->OCER = 0;
SPLL->RCER = 0;
SPLL->DEGLITCH_THR = 2000;
while(! (SPLL->TRR_CSR & SPLL_TRR_CSR_EMPTY)) dummy = SPLL->TRR_R0;
dummy = SPLL->PER_HPLL;
SPLL->EIC_IER = 1;
}
void spll_test()
{
int i = 0;
volatile int dummy;
spll_init();
helper_start(&helper, 6);
enable_irq();
for(;;)
{
mprintf("cnt %d serr %d src %d y %d d %d\n", irq_count, eee, serr, yyy, delta);
}
}
\ No newline at end of file
/*
White Rabbit Softcore PLL (SoftPLL) - common definitions
*/
/* PI regulator state */
typedef struct {
int ki, kp; /* integral and proportional gains (1<<PI_FRACBITS == 1.0f) */
int integrator; /* current integrator value */
int bias; /* DC offset always added to the output */
int anti_windup; /* when non-zero, anti-windup is enabled */
int y_min; /* min/max output range, used by claming and antiwindup algorithms */
int y_max;
int x,y; /* Current input and output value */
} spll_pi_t;
/* Processes a single sample (x) using PI controller (pi). Returns the value (y) which should
be used to drive the actuator. */
static inline int pi_update(spll_pi_t *pi, int x)
{
int i_new, y;
pi->x = x;
i_new = pi->integrator + x;
y = ((i_new * pi->ki + x * pi->kp) >> PI_FRACBITS) + pi->bias;
/* clamping (output has to be in <y_min, y_max>) and anti-windup:
stop the integretor if the output is already out of range and the output
is going further away from y_min/y_max. */
if(y < pi->y_min)
{
y = pi->y_min;
if((pi->anti_windup && (i_new > pi->integrator)) || !pi->anti_windup)
pi->integrator = i_new;
} else if (y > pi->y_max) {
y = pi->y_max;
if((pi->anti_windup && (i_new < pi->integrator)) || !pi->anti_windup)
pi->integrator = i_new;
} else
pi->integrator = i_new;
pi->y = y;
return y;
}
/* initializes the PI controller state. Currently almost a stub. */
static inline void pi_init(spll_pi_t *pi)
{
pi->integrator = 0;
}
/* lock detector state */
typedef struct {
int lock_cnt;
int lock_samples;
int delock_samples;
int threshold;
int locked;
} spll_lock_det_t;
/* Lock detector state machine. Takes an error sample (y) and checks if it's withing an acceptable range
(i.e. <-ld.threshold, ld.threshold>. If it has been inside the range for (ld.lock_samples) cyckes, the
FSM assumes the PLL is locked. */
static inline int ld_update(spll_lock_det_t *ld, int y)
{
if (abs(y) <= ld->threshold)
{
if(ld->lock_cnt < ld->lock_samples)
ld->lock_cnt++;
if(ld->lock_cnt == ld->lock_samples)
ld->locked = 1;
} else {
if(ld->lock_cnt > ld->delock_samples)
ld->lock_cnt--;
if(ld->lock_cnt == ld->delock_samples)
{
ld->lock_cnt= 0;
ld->locked = 0;
}
}
return ld->locked;
}
static void ld_init(spll_lock_det_t *ld)
{
ld->locked = 0;
ld->lock_cnt = 0;
}
/*
White Rabbit Softcore PLL (SoftPLL) - common definitions
*/
#include <stdio.h>
/* Reference clock frequency */
#define CLOCK_FREQ 125000000
/* Bit size of phase tags generated by the DMTDs. Used to sign-extend the tags. */
#define TAG_BITS 20
/* Helper PLL N divider (1/2**N is the frequency offset) */
#define HPLL_N 14
/* Fractional bits in PI controller coefficients */
#define PI_FRACBITS 12
/* State of the Helper PLL producing a clock (clk_dmtd_i) which is
slightly offset in frequency from the recovered/reference clock (clk_rx_i or clk_ref_i), so the
Main PLL can use it to perform linear phase measurements. This structure keeps the state of the pre-locking
stage */
struct spll_helper_prelock_state {
spll_pi_t pi;
spll_lock_det_t ld;
int f_setpoint;
int ref_select;
fdelay_device_t *dev;
};
volatile int serr;
void helper_prelock_init(struct spll_helper_prelock_state *s)
{
/* Frequency branch PI controller */
s->pi.y_min = 5;
s->pi.y_max = 65530;
s->pi.anti_windup = 0;
s->pi.kp = 28*32*16;
s->pi.ki = 50*32*16;
s->pi.bias = 32000;
/* Freqency branch lock detection */
s->ld.threshold = 2;
s->ld.lock_samples = 1000;
s->ld.delock_samples = 990;
s->f_setpoint = 131072 / (1<<HPLL_N);
pi_init(&s->pi);
ld_init(&s->ld);
}
void helper_prelock_enable(struct spll_helper_prelock_state *state, int ref_channel, int enable)
{
fdelay_device_t *dev = state->dev;
fd_decl_private(dev);
fd_writel(0, FD_REG_SPLLR);
}
#define SPLL_LOCKED 1
#define SPLL_LOCKING 0
int helper_prelock_update(struct spll_helper_prelock_state *s, int tag)
{
fdelay_device_t *dev = s->dev;
fd_decl_private(dev);
int y;
volatile uint32_t per = fd_readl(FD_REG_SPLLR);
short err = (short) (tag & 0xffff);
serr = (int)err;
err -= s->f_setpoint;
y = pi_update(&s->pi, err);
fd_writel(y, FD_REG_SDACR);
if(ld_update(&s->ld, err))
return SPLL_LOCKED;
return SPLL_LOCKING;
}
struct spll_helper_phase_state {
spll_pi_t pi;
spll_lock_det_t ld;
int p_setpoint, tag_d0;
int ref_src;
fdelay_device_t *dev;
};
void helper_phase_init(struct spll_helper_phase_state *s)
{
/* Phase branch PI controller */
s->pi.y_min = 5;
s->pi.y_max = 65530;
s->pi.kp = (int)(2.0 * 32.0 * 16.0);
s->pi.ki = (int)(0.05 * 32.0 * 3.0);
s->pi.anti_windup = 0;
s->pi.bias = 32000;
/* Phase branch lock detection */
s->ld.threshold = 500;
s->ld.lock_samples = 10000;
s->ld.delock_samples = 9900;
s->ref_src = 6;
s->p_setpoint = -1;
pi_init(&s->pi);
ld_init(&s->ld);
}
void helper_phase_enable(struct spll_helper_phase_state *state, int ref_channel, int enable)
{
fdelay_device_t *dev = state->dev;
fd_decl_private(dev);
fd_writel(FD_SPLLR_MODE, FD_REG_SPLLR);
}
volatile int delta;
int helper_phase_update(struct spll_helper_phase_state *s, int tag, int source)
{
fdelay_device_t *dev = s->dev;
fd_decl_private(dev);
int err, y;
serr = source;
// if(source == s->ref_src)
{
if(s->p_setpoint < 0)
{
s->p_setpoint = tag;
return;
}
err = tag - s->p_setpoint;
delta = tag - s->tag_d0;
s->tag_d0 = tag;
s->p_setpoint += (1<<HPLL_N);
if(s->p_setpoint > (1<<TAG_BITS))
s->p_setpoint -= (1<<TAG_BITS);
y = pi_update(&s->pi, err);
//printf("t %d sp %d\n", tag, s->p_setpoint);
fd_writel(y, FD_REG_SDACR);
if(ld_update(&s->ld, err))
{
return SPLL_LOCKED;
};
}
return SPLL_LOCKING;
}
#define HELPER_PRELOCKING 1
#define HELPER_PHASE 2
#define HELPER_LOCKED 3
struct spll_helper_state {
struct spll_helper_prelock_state prelock;
struct spll_helper_phase_state phase;
int state;
int ref_channel;
};
void helper_start(fdelay_device_t *dev, struct spll_helper_state *s)
{
s->state = HELPER_PRELOCKING;
s->ref_channel = 0;
s->prelock.dev = dev;
s->phase.dev = dev;
helper_prelock_init(&s->prelock);
helper_phase_init(&s->phase);
helper_prelock_enable(&s->prelock, 0, 1);
}
void helper_update(struct spll_helper_state *s)
{
fdelay_device_t *dev = s->prelock.dev;
fd_decl_private(dev);
uint32_t spllr = fd_readl(FD_REG_SPLLR);
if(! (spllr & FD_SPLLR_TAG_RDY))
return;
int tag = FD_SPLLR_TAG_R(spllr);
switch(s->state)
{
case HELPER_PRELOCKING:
if(helper_prelock_update(&s->prelock, tag) == SPLL_LOCKED)
{
s->state = HELPER_PHASE;
helper_prelock_enable(&s->prelock, 0, 0);
s->phase.pi.bias = s->prelock.pi.y;
helper_phase_enable(&s->phase, 0, 1);
}
break;
case HELPER_PHASE:
helper_phase_update(&s->phase, tag, 0);
break;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment