summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Walls <awalls.cx18@gmail.com>2019-01-21 19:18:39 -0500
committerMartin Braun <martin.braun@ettus.com>2019-02-17 11:12:54 -0800
commitf863efb1a9d3f535f0b51647cab22ce08379a6be (patch)
tree79dc064c18bf89fd2a5afde0800b1dd976f0d54b
parent3864d35f53a79bd201a1d1da4e7c30533793a6c9 (diff)
gr-digital: Prevent the clock tracking loop from generating negative estimates
Under extreme circumstances of the error signal input, the clock tracking loop would allow the average clock period and instantaneous clock period estimates to go negative, resulting in an infinite loop when wrapping the clock phase. Change clock period estimate limiting to happen when the estimates are being formed, so that the negative, non-sensical values aren't allowed to happen.
-rw-r--r--gr-digital/lib/clock_tracking_loop.cc12
-rw-r--r--gr-digital/lib/clock_tracking_loop.h8
-rw-r--r--gr-digital/lib/symbol_sync_cc_impl.cc1
-rw-r--r--gr-digital/lib/symbol_sync_ff_impl.cc1
4 files changed, 16 insertions, 6 deletions
diff --git a/gr-digital/lib/clock_tracking_loop.cc b/gr-digital/lib/clock_tracking_loop.cc
index 0eaa8f29cf..ed8b3efe05 100644
--- a/gr-digital/lib/clock_tracking_loop.cc
+++ b/gr-digital/lib/clock_tracking_loop.cc
@@ -126,8 +126,20 @@ namespace gr {
// Integral arm of PI filter
d_avg_period = d_avg_period + d_beta * error;
+ // Limit the integral arm output here, as a large negative
+ // error input can lead to a negative d_avg_period, which
+ // will cause an infitine loop in the phase wrap method.
+ period_limit();
+
// Proportional arm of PI filter and final sum of PI filter arms
d_inst_period = d_avg_period + d_alpha * error;
+ // Limit the filter output here, for the errant case of a large
+ // negative error input, that can lead to a negative d_inst_period,
+ // which results in an incorrect phase increment, as it is assumed
+ // to be moving forward to the next symbol.
+ if (d_inst_period <= 0.f)
+ d_inst_period = d_avg_period;
+
// Compute the new, unwrapped clock phase
d_phase = d_phase + d_inst_period;
}
diff --git a/gr-digital/lib/clock_tracking_loop.h b/gr-digital/lib/clock_tracking_loop.h
index bc4aee1e6a..e8f0fe7989 100644
--- a/gr-digital/lib/clock_tracking_loop.h
+++ b/gr-digital/lib/clock_tracking_loop.h
@@ -415,12 +415,12 @@ namespace gr {
* integrator portion of an IIR filter, so T_avg could potentially
* wander very far during periods of noise/nonsense input.
*
- * This function should be called after advance_loop to keep the
+ * This function is called in advance_loop to keep the
* estimated average clock period, T_avg, in the specified range.
- * It is set as a separate method in case another way is desired as
- * this is fairly heavy-handed.
+ * It is set as a separate virtual method in case another way is desired
+ * as this is fairly heavy-handed.
*/
- void period_limit();
+ virtual void period_limit();
/*******************************************************************
* SET FUNCTIONS
diff --git a/gr-digital/lib/symbol_sync_cc_impl.cc b/gr-digital/lib/symbol_sync_cc_impl.cc
index e00edeeeb8..c9e44c708b 100644
--- a/gr-digital/lib/symbol_sync_cc_impl.cc
+++ b/gr-digital/lib/symbol_sync_cc_impl.cc
@@ -538,7 +538,6 @@ namespace gr {
d_inst_clock_period = d_clock->get_inst_period();
d_avg_clock_period = d_clock->get_avg_period();
d_clock->phase_wrap();
- d_clock->period_limit();
// Symbol Clock and Interpolator Positioning & Alignment
d_inst_interp_period = d_inst_clock_period / d_interps_per_symbol;
diff --git a/gr-digital/lib/symbol_sync_ff_impl.cc b/gr-digital/lib/symbol_sync_ff_impl.cc
index 180204f77e..da14f05282 100644
--- a/gr-digital/lib/symbol_sync_ff_impl.cc
+++ b/gr-digital/lib/symbol_sync_ff_impl.cc
@@ -538,7 +538,6 @@ namespace gr {
d_inst_clock_period = d_clock->get_inst_period();
d_avg_clock_period = d_clock->get_avg_period();
d_clock->phase_wrap();
- d_clock->period_limit();
// Symbol Clock and Interpolator Positioning & Alignment
d_inst_interp_period = d_inst_clock_period / d_interps_per_symbol;