Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Software for White Rabbit PTP Core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
29
Issues
29
List
Board
Labels
Milestones
Merge Requests
5
Merge Requests
5
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Software for White Rabbit PTP Core
Commits
48f54b88
Commit
48f54b88
authored
Apr 26, 2012
by
Grzegorz Daniluk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
softpll_ng: imported from wr switch
parent
e0228897
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
638 additions
and
199 deletions
+638
-199
softpll_ng.c
dev/softpll_ng.c
+308
-91
spll_common.h
include/spll_common.h
+5
-3
spll_debug.h
include/spll_debug.h
+7
-2
spll_defs.h
include/spll_defs.h
+10
-4
spll_external.h
include/spll_external.h
+157
-23
spll_helper.h
include/spll_helper.h
+14
-17
spll_main.h
include/spll_main.h
+117
-49
spll_ptracker.h
include/spll_ptracker.h
+20
-10
No files found.
dev/softpll_ng.c
View file @
48f54b88
This diff is collapsed.
Click to expand it.
include/spll_common.h
View file @
48f54b88
...
...
@@ -3,9 +3,10 @@
White Rabbit Softcore PLL (SoftPLL) - common definitions
Copyright (c) 2010 - 2012 CERN / BE-CO-HT (Tomasz Włostowski)
Licensed under LGPL 2.1.
spll_common.h - common data structures and functions
*/
...
...
@@ -131,7 +132,8 @@ static int lowpass_update(spll_lowpass_t *lp, int x)
lp
->
y_d
=
x
;
return
x
;
}
else
{
lp
->
y_d
=
lp
->
y_d
+
((
lp
->
alpha
*
(
x
-
lp
->
y_d
))
>>
16
);
int
scaled
=
(
lp
->
alpha
*
(
x
-
lp
->
y_d
))
>>
15
;
lp
->
y_d
=
lp
->
y_d
+
(
scaled
>>
1
)
+
(
scaled
&
1
);
return
lp
->
y_d
;
}
}
...
...
@@ -164,5 +166,5 @@ static void spll_enable_tagger(int channel, int enable)
SPLL
->
RCER
&=
~
(
1
<<
channel
);
}
TRACE_DEV
(
"%s: ch %d, OCER 0x%x, RCER 0x%x
\n
"
,
__FUNCTION__
,
channel
,
SPLL
->
OCER
,
SPLL
->
RCER
);
// TRACE
("%s: ch %d, OCER 0x%x, RCER 0x%x\n", __FUNCTION__, channel, SPLL->OCER, SPLL->RCER);
}
include/spll_debug.h
View file @
48f54b88
/*
White Rabbit Softcore PLL (SoftPLL) - debugging/diagnostic interface
White Rabbit Softcore PLL (SoftPLL) - common definitions
Copyright (c) 2010 - 2012 CERN / BE-CO-HT (Tomasz Włostowski)
Licensed under LGPL 2.1.
spll_debug.h - debugging/diagnostic interface
The so-called debug inteface is a large, interrupt-driven FIFO which passes
various realtime parameters (e.g. error value, tags, DAC drive) to an external
application where they
can be
analyzed. It's very useful for optimizing PI coefficients
application where they
are further
analyzed. It's very useful for optimizing PI coefficients
and/or lock thresholds.
The data is organized as a stream of samples, where each sample can store a number of parameters.
...
...
include/spll_defs.h
View file @
48f54b88
...
...
@@ -10,7 +10,10 @@ WARNING: These parameters must be in sync with the generics of the HDL instantia
#include <stdio.h>
/* Reference clock frequency, in [Hz] */
#define CLOCK_FREQ 62500000
#define CLOCK_FREQ 125000000
/* Reference clock period, in picoseconds */
#define CLOCK_PERIOD_PICOSECONDS 8000
/* Number of bits in phase tags generated by the DMTDs. Used to sign-extend the tags.
Corresponding VHDL generic: g_tag_bits. */
...
...
@@ -25,10 +28,10 @@ WARNING: These parameters must be in sync with the generics of the HDL instantia
#define PI_FRACBITS 12
/* Max. allowed number of reference channels. Can be used to tweak memory usage. */
#define MAX_CHAN_REF
7
#define MAX_CHAN_REF
1
/* Max. allowed number of
output
channels */
#define MAX_CHAN_
OUT
1
/* Max. allowed number of
auxillary
channels */
#define MAX_CHAN_
AUX
1
/* Max. allowed number of phase trackers */
#define MAX_PTRACKERS 6
...
...
@@ -37,6 +40,9 @@ WARNING: These parameters must be in sync with the generics of the HDL instantia
all the outputs. */
#define DAC_BITS 16
/* Number of samples in a single ptracker averaging bin */
#define PTRACKER_AVERAGE_SAMPLES 512
/* 1.0 / (Speed of the phase shifter) - the higher value, the slower phase shifting.
Used to prevent de-locking PLLs when shifting large offsets. */
#define PHASE_SHIFTER_SPEED 1
include/spll_external.h
View file @
48f54b88
#include <timer.h>
#include <hw/pps_gen_regs.h>
/* Number of bits of the BB phase detector error counter. Bit [BB_ERROR_BITS] is the wrap-around bit */
#define BB_ERROR_BITS 16
/* Alignment FSM states */
/* 1st alignment stage, done before starting the ext channel PLL: alignment of the rising edge
of the external clock (10 MHz), with the rising edge of the local reference (62.5/125 MHz)
and the PPS signal. Because of non-integer ratio (6.25 or 12.5), the PLL must know which edges
shall be kept at phase==0. We align to the edge of the 10 MHz clock which comes right after the edge
of the PPS pulse (see drawing below):
PLL reference (62.5 MHz) ____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|
External clock (10 MHz) ^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|___
External PPS ___________|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
#define REALIGN_STAGE1 1
#define REALIGN_STAGE1_WAIT 2
/* 2nd alignment stage, done after the ext channel PLL has locked. We make sure that the switch's internal PPS signal
is produced exactly on the edge of PLL reference in-phase with 10 MHz clock edge, which has come right after the PPS input
PLL reference (62.5 MHz) ____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|
External clock (10 MHz) ^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|___
External PPS ___________|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Internal PPS __________________________________|^^^^^^^^^|______________________________________________________________________
^ aligned clock edges and PPS
*/
#define REALIGN_STAGE2 3
#define REALIGN_STAGE2_WAIT 4
/* Error state - PPS signal missing or of bad frequency */
#define REALIGN_PPS_INVALID 5
/* Realignment is disabled (i.e. the switch inputs only the reference frequency, but not time) */
#define REALIGN_DISABLED 6
/* Realignment done */
#define REALIGN_DONE 7
//GGDD
PACKED
struct
PPSG_WB
{
uint32_t
CR
;
uint32_t
CNTR_NSEC
;
uint32_t
CNTR_UTCLO
;
uint32_t
CNTR_UTCHI
;
uint32_t
ADJ_NSEC
;
uint32_t
ADJ_UTCLO
;
uint32_t
ADJ_UTCHI
;
uint32_t
ESCR
;
};
//volatile struct temp_ppsg_regs *PPSG = BASE_PPSGEN;
//
struct
spll_external_state
{
int
ref_src
;
int
sample_n
;
int
ph_err_offset
,
ph_err_cur
,
ph_err_d0
,
ph_raw_d0
;
spll_pi_t
pi
;
spll_lowpass_t
lp_short
,
lp_long
;
int
realign_clocks
;
int
realign_state
;
int
realign_timer
;
spll_pi_t
pi
;
spll_lowpass_t
lp_short
,
lp_long
;
spll_lock_det_t
ld
;
};
static
void
external_init
(
struct
spll_external_state
*
s
,
int
ext_ref
)
static
void
external_init
(
struct
spll_external_state
*
s
,
int
ext_ref
,
int
realign_clocks
)
{
s
->
pi
.
y_min
=
5
;
s
->
pi
.
y_max
=
(
1
<<
DAC_BITS
)
-
5
;
s
->
pi
.
kp
=
(
int
)(
300
);
s
->
pi
.
ki
=
(
int
)(
1
);
s
->
pi
.
ki
=
(
int
)(
1
);
s
->
pi
.
anti_windup
=
1
;
s
->
pi
.
bias
=
32768
;
/* Phase branch lock detection */
s
->
ld
.
threshold
=
250
;
s
->
ld
.
lock_samples
=
10000
;
...
...
@@ -29,21 +90,84 @@ static void external_init(struct spll_external_state *s, int ext_ref)
s
->
ph_err_cur
=
0
;
s
->
ph_err_d0
=
0
;
s
->
ph_raw_d0
=
0
;
s
->
realign_clocks
=
realign_clocks
;
s
->
realign_state
=
(
realign_clocks
?
REALIGN_STAGE1
:
REALIGN_DISABLED
);
pi_init
(
&
s
->
pi
);
ld_init
(
&
s
->
ld
);
lowpass_init
(
&
s
->
lp_short
,
4000
);
lowpass_init
(
&
s
->
lp_long
,
10
00
);
lowpass_init
(
&
s
->
lp_long
,
3
00
);
}
static
int
external_update
(
struct
spll_external_state
*
s
,
int
tag
,
int
source
)
static
inline
void
realign_fsm
(
struct
spll_external_state
*
s
)
{
uint32_t
eccr
;
switch
(
s
->
realign_state
)
{
case
REALIGN_STAGE1
:
SPLL
->
ECCR
|=
SPLL_ECCR_ALIGN_EN
;
s
->
realign_state
=
REALIGN_STAGE1_WAIT
;
s
->
realign_timer
=
timer_get_tics
();
break
;
case
REALIGN_STAGE1_WAIT
:
if
(
SPLL
->
ECCR
&
SPLL_ECCR_ALIGN_DONE
)
s
->
realign_state
=
REALIGN_STAGE2
;
else
if
(
timer_get_tics
()
-
s
->
realign_timer
>
2
*
TICS_PER_SECOND
)
{
SPLL
->
ECCR
&=
~
SPLL_ECCR_ALIGN_EN
;
s
->
realign_state
=
REALIGN_PPS_INVALID
;
}
break
;
case
REALIGN_STAGE2
:
if
(
s
->
ld
.
locked
)
{
PPSG
->
CR
=
PPSG_CR_CNT_RST
|
PPSG_CR_CNT_EN
;
PPSG
->
ADJ_UTCLO
=
0
;
PPSG
->
ADJ_UTCHI
=
0
;
PPSG
->
ADJ_NSEC
=
0
;
PPSG
->
ESCR
=
PPSG_ESCR_SYNC
;
s
->
realign_state
=
REALIGN_STAGE2_WAIT
;
s
->
realign_timer
=
timer_get_tics
();
}
break
;
case
REALIGN_STAGE2_WAIT
:
if
(
PPSG
->
ESCR
&
PPSG_ESCR_SYNC
)
{
PPSG
->
ESCR
=
PPSG_ESCR_PPS_VALID
|
PPSG_ESCR_TM_VALID
;
s
->
realign_state
=
REALIGN_DONE
;
}
else
if
(
timer_get_tics
()
-
s
->
realign_timer
>
2
*
TICS_PER_SECOND
)
{
PPSG
->
ESCR
=
0
;
s
->
realign_state
=
REALIGN_PPS_INVALID
;
}
break
;
case
REALIGN_PPS_INVALID
:
case
REALIGN_DISABLED
:
case
REALIGN_DONE
:
return
;
}
}
static
int
external_update
(
struct
spll_external_state
*
s
,
int
tag
,
int
source
)
{
int
err
,
y
,
y2
,
yd
,
ylt
;
if
(
source
==
s
->
ref_src
)
{
int
wrap
=
tag
&
(
1
<<
BB_ERROR_BITS
)
?
1
:
0
;
realign_fsm
(
s
);
tag
&=
((
1
<<
BB_ERROR_BITS
)
-
1
);
...
...
@@ -51,22 +175,28 @@ static int external_update(struct spll_external_state *s, int tag, int source)
// mprintf("err %d\n", tag);
if
(
wrap
)
{
if
(
tag
>
s
->
ph_raw_d0
)
if
(
tag
>
s
->
ph_raw_d0
)
s
->
ph_err_offset
-=
(
1
<<
BB_ERROR_BITS
);
else
if
(
tag
<=
s
->
ph_raw_d0
)
s
->
ph_err_offset
+=
(
1
<<
BB_ERROR_BITS
);
}
s
->
ph_raw_d0
=
tag
;
err
=
(
tag
+
s
->
ph_err_offset
)
-
s
->
ph_err_d0
;
s
->
ph_err_d0
=
(
tag
+
s
->
ph_err_offset
);
s
->
ph_err_d0
=
(
tag
+
s
->
ph_err_offset
);
y
=
pi_update
(
&
s
->
pi
,
err
);
y2
=
lowpass_update
(
&
s
->
lp_short
,
y
);
ylt
=
lowpass_update
(
&
s
->
lp_long
,
y
);
if
(
!
(
SPLL
->
ECCR
&
SPLL_ECCR_EXT_REF_PRESENT
))
/* no reference? de-lock now */
{
ld_init
(
&
s
->
ld
);
y2
=
32000
;
}
SPLL
->
DAC_MAIN
=
y2
&
0xffff
;
spll_debug
(
DBG_ERR
|
DBG_EXT
,
ylt
,
0
);
...
...
@@ -80,17 +210,21 @@ static int external_update(struct spll_external_state *s, int tag, int source)
}
static
void
external_start
(
struct
spll_external_state
*
s
,
int
align_pp
s
)
static
void
external_start
(
struct
spll_external_state
*
s
)
{
// mprintf("ExtStartup\n");
SPLL
->
ECCR
=
0
;
s
->
sample_n
=
0
;
s
->
realign_state
=
(
s
->
realign_clocks
?
REALIGN_STAGE1
:
REALIGN_DISABLED
);
SPLL
->
ECCR
=
SPLL_ECCR_EXT_EN
;
mprintf
(
"ExtStartup
\n
"
);
spll_debug
(
DBG_EVENT
|
DBG_EXT
,
DBG_EVT_START
,
1
);
if
(
align_pps
)
{
SPLL
->
ECCR
|=
SPLL_ECCR_ALIGN_EN
;
while
(
!
(
SPLL
->
ECCR
&
SPLL_ECCR_ALIGN_DONE
));
}
}
static
inline
int
external_locked
(
struct
spll_external_state
*
s
)
{
return
(
s
->
ld
.
locked
&&
(
s
->
realign_clocks
?
s
->
realign_state
==
REALIGN_DONE
:
1
));
}
include/spll_helper.h
View file @
48f54b88
...
...
@@ -20,7 +20,7 @@ struct spll_helper_state {
spll_pi_t
pi
;
spll_lock_det_t
ld
;
};
static
void
helper_init
(
struct
spll_helper_state
*
s
,
int
ref_channel
)
{
...
...
@@ -31,22 +31,12 @@ static void helper_init(struct spll_helper_state *s, int ref_channel)
s
->
pi
.
ki
=
(
int
)(
0
.
03
*
32
.
0
*
3
.
0
);
s
->
pi
.
anti_windup
=
1
;
/* Set the bias to the upper end of tuning range. This is to ensure that
the HPLL will always lock on positive frequency offset. */
s
->
pi
.
bias
=
s
->
pi
.
y_max
;
/* Phase branch lock detection */
s
->
ld
.
threshold
=
200
;
s
->
ld
.
lock_samples
=
1000
;
s
->
ld
.
delock_samples
=
900
;
s
->
ref_src
=
ref_channel
;
s
->
p_setpoint
=
0
;
s
->
p_adder
=
0
;
s
->
sample_n
=
0
;
s
->
tag_d0
=
-
1
;
pi_init
(
&
s
->
pi
);
ld_init
(
&
s
->
ld
);
}
static
int
helper_update
(
struct
spll_helper_state
*
s
,
int
tag
,
int
source
)
...
...
@@ -71,17 +61,11 @@ static int helper_update(struct spll_helper_state *s, int tag, int source)
err
=
(
tag
+
s
->
p_adder
)
-
s
->
p_setpoint
;
// if(s->tag_d0 - tag > -100000)
//spll_debug(DBG_ERR | DBG_HELPER, s->tag_d0-tag, 1);
if
(
HELPER_ERROR_CLAMP
)
{
if
(
err
<
-
HELPER_ERROR_CLAMP
)
err
=
-
HELPER_ERROR_CLAMP
;
if
(
err
>
HELPER_ERROR_CLAMP
)
err
=
HELPER_ERROR_CLAMP
;
}
//GD
//TRACE_DEV("hpll 2err=%d\n", err);
if
((
tag
+
s
->
p_adder
)
>
HELPER_TAG_WRAPAROUND
&&
s
->
p_setpoint
>
HELPER_TAG_WRAPAROUND
)
{
...
...
@@ -106,8 +90,21 @@ static int helper_update(struct spll_helper_state *s, int tag, int source)
}
static
void
helper_start
(
struct
spll_helper_state
*
s
)
{
/* Set the bias to the upper end of tuning range. This is to ensure that
the HPLL will always lock on positive frequency offset. */
s
->
pi
.
bias
=
s
->
pi
.
y_max
;
s
->
p_setpoint
=
0
;
s
->
p_adder
=
0
;
s
->
sample_n
=
0
;
s
->
tag_d0
=
-
1
;
pi_init
(
&
s
->
pi
);
ld_init
(
&
s
->
ld
);
spll_enable_tagger
(
s
->
ref_src
,
1
);
spll_debug
(
DBG_EVENT
|
DBG_HELPER
,
DBG_EVT_START
,
1
);
}
...
...
include/spll_main.h
View file @
48f54b88
#define MPLL_TAG_WRAPAROUND 1000000000
#define MPLL_TAG_WRAPAROUND 100000000
#define MATCH_NEXT_TAG 0
#define MATCH_WAIT_REF 1
#define MATCH_WAIT_OUT 2
#undef WITH_SEQUENCING
/* State of the Main PLL */
struct
spll_main_state
{
int
state
;
spll_pi_t
pi
;
spll_pi_t
pi
;
spll_lock_det_t
ld
;
int
adder_ref
,
adder_out
,
tag_ref
,
tag_out
,
tag_ref_d
,
tag_out_d
;
int
adder_ref
,
adder_out
,
tag_ref
,
tag_out
,
tag_ref_d
,
tag_out_d
;
// tag sequencing stuff
uint32_t
seq_ref
,
seq_out
;
int
match_state
;
int
match_seq
;
int
phase_shift_target
;
int
phase_shift_current
;
int
id_ref
,
id_out
;
/* IDs of the reference and the output channel */
int
sample_n
;
int
shift_div
;
};
volatile
int
lerr
=
0
,
ly
=
0
;
static
void
mpll_init
(
struct
spll_main_state
*
s
,
int
id_ref
,
int
id_out
)
{
...
...
@@ -32,58 +42,119 @@ static void mpll_init(struct spll_main_state *s, int id_ref, int id_out)
s
->
ld
.
threshold
=
120
;
s
->
ld
.
lock_samples
=
400
;
s
->
ld
.
delock_samples
=
390
;
s
->
id_ref
=
id_ref
;
s
->
id_out
=
id_out
;
pi_init
(
&
s
->
pi
);
ld_init
(
&
s
->
ld
);
}
static
void
mpll_start
(
struct
spll_main_state
*
s
)
{
s
->
adder_ref
=
s
->
adder_out
=
0
;
s
->
tag_ref
=
-
1
;
s
->
tag_out
=
-
1
;
s
->
tag_ref_d
=
-
1
;
s
->
tag_out_d
=
-
1
;
s
->
seq_ref
=
0
;
s
->
seq_out
=
0
;
s
->
match_state
=
MATCH_NEXT_TAG
;
s
->
phase_shift_target
=
0
;
s
->
phase_shift_current
=
0
;
s
->
id_ref
=
id_ref
;
s
->
id_out
=
id_out
;
s
->
sample_n
=
0
;
s
->
shift_div
=
0
;
pi_init
(
&
s
->
pi
);
ld_init
(
&
s
->
ld
);
}
static
void
mpll_start
(
struct
spll_main_state
*
s
)
{
spll_enable_tagger
(
s
->
id_ref
,
1
);
spll_enable_tagger
(
s
->
id_out
,
1
);
spll_debug
(
DBG_EVENT
|
DBG_MAIN
,
DBG_EVT_START
,
1
);
}
static
void
mpll_stop
(
struct
spll_main_state
*
s
)
{
spll_enable_tagger
(
s
->
id_out
,
0
);
}
static
int
mpll_update
(
struct
spll_main_state
*
s
,
int
tag
,
int
source
)
{
int
err
,
y
,
tmp
;
if
(
source
==
s
->
id_ref
)
#ifdef WITH_SEQUENCING
int
new_ref
=
-
1
,
new_out
=
-
1
;
if
(
source
==
s
->
id_ref
)
{
new_ref
=
tag
;
s
->
seq_ref
++
;
}
else
if
(
source
==
s
->
id_out
)
{
new_out
=
tag
;
s
->
seq_out
++
;
}
switch
(
s
->
match_state
)
{
case
MATCH_NEXT_TAG
:
if
(
new_ref
>
0
&&
s
->
seq_out
<
s
->
seq_ref
)
{
s
->
tag_ref
=
new_ref
;
s
->
match_seq
=
s
->
seq_ref
;
s
->
match_state
=
MATCH_WAIT_OUT
;
}
if
(
new_out
>
0
&&
s
->
seq_out
>
s
->
seq_ref
)
{
s
->
tag_out
=
new_out
;
s
->
match_seq
=
s
->
seq_out
;
s
->
match_state
=
MATCH_WAIT_REF
;
}
break
;
case
MATCH_WAIT_REF
:
if
(
new_ref
>
0
&&
s
->
seq_ref
==
s
->
match_seq
)
{
s
->
match_state
=
MATCH_NEXT_TAG
;
s
->
tag_ref
=
new_ref
;
}
break
;
case
MATCH_WAIT_OUT
:
if
(
new_out
>
0
&&
s
->
seq_out
==
s
->
match_seq
)
{
s
->
match_state
=
MATCH_NEXT_TAG
;
s
->
tag_out
=
new_out
;
}
break
;
}
#else
if
(
source
==
s
->
id_ref
)
s
->
tag_ref
=
tag
;
if
(
source
==
s
->
id_out
)
s
->
tag_out
=
tag
;
#endif
if
(
s
->
tag_ref
>=
0
&&
s
->
tag_out
>=
0
)
{
if
(
s
->
tag_ref_d
>=
0
&&
s
->
tag_ref_d
>
s
->
tag_ref
)
s
->
adder_ref
+=
(
1
<<
TAG_BITS
);
if
(
s
->
tag_out_d
>=
0
&&
s
->
tag_out_d
>
s
->
tag_out
)
s
->
adder_out
+=
(
1
<<
TAG_BITS
);
err
=
s
->
adder_ref
+
s
->
tag_ref
-
s
->
adder_out
-
s
->
tag_out
;
s
->
tag_ref_d
=
s
->
tag_ref
;
s
->
tag_out_d
=
s
->
tag_out
;
if
(
s
->
adder_ref
>
MPLL_TAG_WRAPAROUND
&&
s
->
adder_out
>
MPLL_TAG_WRAPAROUND
)
{
s
->
adder_ref
-=
MPLL_TAG_WRAPAROUND
;
s
->
adder_out
-=
MPLL_TAG_WRAPAROUND
;
}
err
=
s
->
adder_ref
+
s
->
tag_ref
-
s
->
adder_out
-
s
->
tag_out
;
#ifndef WITH_SEQUENCING
/* Hack: the PLL is locked, so the tags are close to each other. But when we start phase shifting, after reaching
/* Hack: the PLL is locked, so the tags are close to each other. But when we start phase shifting, after reaching
full clock period, one of the reference tags will flip before the other, causing a suddent 2**HPLL_N jump in the error.
So, once the PLL is locked, we just mask out everything above 2**HPLL_N.
Proper solution: tag sequence numbers */
if
(
s
->
ld
.
locked
)
{
...
...
@@ -91,41 +162,39 @@ static int mpll_update(struct spll_main_state *s, int tag, int source)
if
(
err
&
(
1
<<
(
HPLL_N
-
1
)))
err
|=
~
((
1
<<
HPLL_N
)
-
1
);
}
y
=
pi_update
(
&
s
->
pi
,
err
);
lerr
=
err
;
ly
=
y
;
#endif
y
=
pi_update
(
&
s
->
pi
,
err
)
;
SPLL
->
DAC_MAIN
=
SPLL_DAC_MAIN_VALUE_W
(
y
)
|
SPLL_DAC_MAIN_DAC_SEL_W
(
s
->
id_out
);
spll_debug
(
DBG_MAIN
|
DBG_REF
,
s
->
tag_ref
+
s
->
adder_ref
,
0
);
spll_debug
(
DBG_MAIN
|
DBG_TAG
,
s
->
tag_out
+
s
->
adder_out
,
0
);
spll_debug
(
DBG_MAIN
|
DBG_ERR
,
err
,
0
);
spll_debug
(
DBG_MAIN
|
DBG_SAMPLE_ID
,
s
->
sample_n
++
,
0
);
spll_debug
(
DBG_MAIN
|
DBG_Y
,
y
,
1
);
s
->
tag_ref_d
=
s
->
tag_ref
;
s
->
tag_out_d
=
s
->
tag_out
;
s
->
tag_out
=
-
1
;
s
->
tag_ref
=
-
1
;
s
->
tag_ref
=
-
1
;
if
(
s
->
phase_shift_current
<
s
->
phase_shift_target
)
{
if
(
s
->
shift_div
==
PHASE_SHIFTER_SPEED
-
1
)
{
s
->
phase_shift_current
++
;
s
->
adder_ref
++
;
s
->
shift_div
=
0
;
}
else
s
->
shift_div
++
;
}
else
if
(
s
->
phase_shift_current
>
s
->
phase_shift_target
)
{
if
(
s
->
shift_div
==
PHASE_SHIFTER_SPEED
-
1
)
if
(
s
->
adder_ref
>
2
*
MPLL_TAG_WRAPAROUND
&&
s
->
adder_out
>
2
*
MPLL_TAG_WRAPAROUND
)
{
s
->
adder_ref
-=
MPLL_TAG_WRAPAROUND
;
s
->
adder_out
-=
MPLL_TAG_WRAPAROUND
;
}
if
(
s
->
ld
.
locked
)
{
s
->
phase_shift_current
--
;
s
->
adder_ref
--
;
s
->
shift_div
=
0
;
}
else
s
->
shift_div
++
;
}
if
(
s
->
phase_shift_current
<
s
->
phase_shift_target
)
{
s
->
phase_shift_current
++
;
s
->
adder_ref
++
;
}
else
if
(
s
->
phase_shift_current
>
s
->
phase_shift_target
)
{
s
->
phase_shift_current
--
;
s
->
adder_ref
--
;
}
}
if
(
ld_update
(
&
s
->
ld
,
err
))
return
SPLL_LOCKED
;
...
...
@@ -136,11 +205,10 @@ static int mpll_update(struct spll_main_state *s, int tag, int source)
static
int
mpll_set_phase_shift
(
struct
spll_main_state
*
s
,
int
desired_shift
)
{
s
->
shift_div
=
0
;
s
->
phase_shift_target
=
desired_shift
;
}
static
int
mpll_shifter_busy
(
struct
spll_main_state
*
s
)
{
return
s
->
phase_shift_target
!=
s
->
phase_shift_current
;
}
\ No newline at end of file
}
include/spll_ptracker.h
View file @
48f54b88
...
...
@@ -5,7 +5,7 @@ struct spll_ptracker_state {
int
id_a
,
id_b
;
int
n_avg
,
acc
,
avg_count
;
int
phase_val
,
ready
;
int
tag_a
,
tag_b
;
int
tag_a
,
tag_b
;
int
sample_n
;
int
preserve_sign
;
};
...
...
@@ -14,7 +14,7 @@ struct spll_ptracker_state {
static
void
ptracker_init
(
struct
spll_ptracker_state
*
s
,
int
id_a
,
int
id_b
,
int
num_avgs
)
{
s
->
tag_a
=
s
->
tag_b
=
-
1
;
s
->
id_a
=
id_a
;
s
->
id_b
=
id_b
;
s
->
ready
=
0
;
...
...
@@ -27,6 +27,13 @@ static void ptracker_init(struct spll_ptracker_state *s, int id_a, int id_b, int
static
void
ptracker_start
(
struct
spll_ptracker_state
*
s
)
{
s
->
tag_a
=
s
->
tag_b
=
-
1
;
s
->
ready
=
0
;
s
->
acc
=
0
;
s
->
avg_count
=
0
;
s
->
sample_n
=
0
;
s
->
preserve_sign
=
0
;
spll_enable_tagger
(
s
->
id_a
,
1
);
spll_enable_tagger
(
s
->
id_b
,
1
);
}
...
...
@@ -45,21 +52,23 @@ static int ptracker_update(struct spll_ptracker_state *s, int tag, int source)
if
(
s
->
tag_a
>=
0
&&
s
->
tag_b
>=
0
)
{
int
delta
=
(
s
->
tag_a
-
s
->
tag_b
)
&
((
1
<<
HPLL_N
)
-
1
);
s
->
sample_n
++
;
if
(
s
->
avg_count
==
0
)
{
if
(
delta
<=
PTRACK_WRAP_LO
)
if
(
delta
<=
PTRACK_WRAP_LO
)
s
->
preserve_sign
=
-
1
;
else
if
(
delta
>=
PTRACK_WRAP_HI
)
s
->
preserve_sign
=
1
;
else
s
->
preserve_sign
=
0
;
s
->
avg_count
++
;
s
->
acc
=
delta
;
}
else
{
if
(
delta
<=
PTRACK_WRAP_LO
&&
s
->
preserve_sign
>
0
)
s
->
acc
+=
delta
+
(
1
<<
HPLL_N
);
else
if
(
delta
>=
PTRACK_WRAP_HI
&&
s
->
preserve_sign
<
0
)
...
...
@@ -76,8 +85,9 @@ static int ptracker_update(struct spll_ptracker_state *s, int tag, int source)
s
->
acc
=
0
;
s
->
avg_count
=
0
;
}
}
}
s
->
tag_b
=
s
->
tag_a
=
-
1
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment