diff options
author | ghostop14 <ghostop14@gmail.com> | 2020-02-14 11:47:37 -0500 |
---|---|---|
committer | Marcus Müller <marcus@hostalia.de> | 2020-02-15 14:25:57 +0100 |
commit | 504ab76d9e4fc3e9f497b9fd34f01c1bad346a5d (patch) | |
tree | c64edca089a87217e56d8840a38382d7e2b4ec56 | |
parent | a56c3a7f4908133dc6ceb93ffd3b2f9e1dda8e0e (diff) |
gr-digital: Improve PLL Loops and Clock Recovery
These updates incorporate the same inlining of loop functions and
the newly pushed fast_cc_multiply function to ensure
consistent performance improvements across systems that do not
support the cx-limited-range compiler parameter (Macs and Windows).
-rw-r--r-- | gr-analog/lib/pll_carriertracking_cc_impl.cc | 27 | ||||
-rw-r--r-- | gr-analog/lib/pll_carriertracking_cc_impl.h | 23 | ||||
-rw-r--r-- | gr-analog/lib/pll_freqdet_cf_impl.cc | 17 | ||||
-rw-r--r-- | gr-analog/lib/pll_freqdet_cf_impl.h | 21 | ||||
-rw-r--r-- | gr-analog/lib/pll_refout_cc_impl.cc | 18 | ||||
-rw-r--r-- | gr-analog/lib/pll_refout_cc_impl.h | 20 | ||||
-rw-r--r-- | gr-digital/lib/clock_recovery_mm_cc_impl.cc | 29 | ||||
-rw-r--r-- | gr-digital/lib/clock_recovery_mm_cc_impl.h | 22 | ||||
-rw-r--r-- | gr-digital/lib/clock_recovery_mm_ff_impl.cc | 2 | ||||
-rw-r--r-- | gr-digital/lib/clock_recovery_mm_ff_impl.h | 2 | ||||
-rw-r--r-- | gr-digital/lib/clock_tracking_loop.cc | 54 | ||||
-rw-r--r-- | gr-digital/lib/clock_tracking_loop.h | 54 | ||||
-rw-r--r-- | gr-dtv/lib/atsc/atsc_fpll_impl.cc | 7 |
13 files changed, 135 insertions, 161 deletions
diff --git a/gr-analog/lib/pll_carriertracking_cc_impl.cc b/gr-analog/lib/pll_carriertracking_cc_impl.cc index 81c04aa01b..f403cf3528 100644 --- a/gr-analog/lib/pll_carriertracking_cc_impl.cc +++ b/gr-analog/lib/pll_carriertracking_cc_impl.cc @@ -14,7 +14,6 @@ #include "pll_carriertracking_cc_impl.h" #include <gnuradio/io_signature.h> -#include <gnuradio/math.h> #include <gnuradio/sincos.h> #include <cmath> @@ -44,29 +43,6 @@ pll_carriertracking_cc_impl::pll_carriertracking_cc_impl(float loop_bw, pll_carriertracking_cc_impl::~pll_carriertracking_cc_impl() {} -float pll_carriertracking_cc_impl::mod_2pi(float in) -{ - if (in > GR_M_PI) - return in - (2.0 * GR_M_PI); - else if (in < -GR_M_PI) - return in + (2.0 * GR_M_PI); - else - return in; -} - -float pll_carriertracking_cc_impl::phase_detector(gr_complex sample, float ref_phase) -{ - float sample_phase; - // sample_phase = atan2(sample.imag(),sample.real()); - sample_phase = gr::fast_atan2f(sample.imag(), sample.real()); - return mod_2pi(sample_phase - ref_phase); -} - -bool pll_carriertracking_cc_impl::lock_detector(void) -{ - return (fabsf(d_locksig) > d_lock_threshold); -} - bool pll_carriertracking_cc_impl::squelch_enable(bool set_squelch) { return d_squelch_enable = set_squelch; @@ -89,7 +65,8 @@ int pll_carriertracking_cc_impl::work(int noutput_items, for (int i = 0; i < noutput_items; i++) { gr::sincosf(d_phase, &t_imag, &t_real); - optr[i] = iptr[i] * gr_complex(t_real, -t_imag); + + fast_cc_multiply(optr[i], iptr[i], gr_complex(t_real, -t_imag)); error = phase_detector(iptr[i], d_phase); diff --git a/gr-analog/lib/pll_carriertracking_cc_impl.h b/gr-analog/lib/pll_carriertracking_cc_impl.h index 3cb7146da9..82a2f1c21c 100644 --- a/gr-analog/lib/pll_carriertracking_cc_impl.h +++ b/gr-analog/lib/pll_carriertracking_cc_impl.h @@ -12,6 +12,7 @@ #define INCLUDED_ANALOG_PLL_CARRIERTRACKING_CC_IMPL_H #include <gnuradio/analog/pll_carriertracking_cc.h> +#include <gnuradio/math.h> namespace gr { namespace analog { @@ -22,14 +23,30 @@ private: float d_locksig, d_lock_threshold; bool d_squelch_enable; - float mod_2pi(float in); - float phase_detector(gr_complex sample, float ref_phase); + float mod_2pi(float in) + { + if (in > GR_M_PI) + return in - (2.0 * GR_M_PI); + else if (in < -GR_M_PI) + return in + (2.0 * GR_M_PI); + else + return in; + } + + float phase_detector(gr_complex sample, float ref_phase) + { + float sample_phase; + // sample_phase = atan2(sample.imag(),sample.real()); + sample_phase = gr::fast_atan2f(sample.imag(), sample.real()); + return mod_2pi(sample_phase - ref_phase); + } public: pll_carriertracking_cc_impl(float loop_bw, float max_freq, float min_freq); ~pll_carriertracking_cc_impl(); - bool lock_detector(void); + bool lock_detector(void) { return (fabsf(d_locksig) > d_lock_threshold); } + bool squelch_enable(bool); float set_lock_threshold(float); diff --git a/gr-analog/lib/pll_freqdet_cf_impl.cc b/gr-analog/lib/pll_freqdet_cf_impl.cc index f460441e92..baeecc7739 100644 --- a/gr-analog/lib/pll_freqdet_cf_impl.cc +++ b/gr-analog/lib/pll_freqdet_cf_impl.cc @@ -37,23 +37,6 @@ pll_freqdet_cf_impl::pll_freqdet_cf_impl(float loop_bw, float max_freq, float mi pll_freqdet_cf_impl::~pll_freqdet_cf_impl() {} -float pll_freqdet_cf_impl::mod_2pi(float in) -{ - if (in > GR_M_PI) - return in - (2.0 * GR_M_PI); - else if (in < -GR_M_PI) - return in + (2.0 * GR_M_PI); - else - return in; -} - -float pll_freqdet_cf_impl::phase_detector(gr_complex sample, float ref_phase) -{ - float sample_phase; - sample_phase = gr::fast_atan2f(sample.imag(), sample.real()); - return mod_2pi(sample_phase - ref_phase); -} - int pll_freqdet_cf_impl::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) diff --git a/gr-analog/lib/pll_freqdet_cf_impl.h b/gr-analog/lib/pll_freqdet_cf_impl.h index de5c03192b..2110bcc720 100644 --- a/gr-analog/lib/pll_freqdet_cf_impl.h +++ b/gr-analog/lib/pll_freqdet_cf_impl.h @@ -12,6 +12,7 @@ #define INCLUDED_ANALOG_PLL_FREQDET_CF_IMPL_H #include <gnuradio/analog/pll_freqdet_cf.h> +#include <gnuradio/math.h> namespace gr { namespace analog { @@ -19,14 +20,28 @@ namespace analog { class pll_freqdet_cf_impl : public pll_freqdet_cf { private: - float phase_detector(gr_complex sample, float ref_phase); + float mod_2pi(float in) + { + if (in > GR_M_PI) + return in - (2.0 * GR_M_PI); + else if (in < -GR_M_PI) + return in + (2.0 * GR_M_PI); + else + return in; + } + + float phase_detector(gr_complex sample, float ref_phase) + { + float sample_phase; + sample_phase = gr::fast_atan2f(sample.imag(), sample.real()); + return mod_2pi(sample_phase - ref_phase); + } + public: pll_freqdet_cf_impl(float loop_bw, float max_freq, float min_freq); ~pll_freqdet_cf_impl(); - float mod_2pi(float in); - void set_loop_bandwidth(float bw); void set_damping_factor(float df); void set_alpha(float alpha); diff --git a/gr-analog/lib/pll_refout_cc_impl.cc b/gr-analog/lib/pll_refout_cc_impl.cc index 067e650de5..9824d12178 100644 --- a/gr-analog/lib/pll_refout_cc_impl.cc +++ b/gr-analog/lib/pll_refout_cc_impl.cc @@ -14,7 +14,6 @@ #include "pll_refout_cc_impl.h" #include <gnuradio/io_signature.h> -#include <gnuradio/math.h> #include <gnuradio/sincos.h> #include <math.h> @@ -37,23 +36,6 @@ pll_refout_cc_impl::pll_refout_cc_impl(float loop_bw, float max_freq, float min_ pll_refout_cc_impl::~pll_refout_cc_impl() {} -float pll_refout_cc_impl::mod_2pi(float in) -{ - if (in > GR_M_PI) - return in - (2.0 * GR_M_PI); - else if (in < -GR_M_PI) - return in + (2.0 * GR_M_PI); - else - return in; -} - -float pll_refout_cc_impl::phase_detector(gr_complex sample, float ref_phase) -{ - float sample_phase; - sample_phase = gr::fast_atan2f(sample.imag(), sample.real()); - return mod_2pi(sample_phase - ref_phase); -} - int pll_refout_cc_impl::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) diff --git a/gr-analog/lib/pll_refout_cc_impl.h b/gr-analog/lib/pll_refout_cc_impl.h index da9be48b16..dc8bf2dc9d 100644 --- a/gr-analog/lib/pll_refout_cc_impl.h +++ b/gr-analog/lib/pll_refout_cc_impl.h @@ -12,6 +12,7 @@ #define INCLUDED_ANALOG_PLL_REFOUT_CC_IMPL_H #include <gnuradio/analog/pll_refout_cc.h> +#include <gnuradio/math.h> namespace gr { namespace analog { @@ -19,8 +20,23 @@ namespace analog { class pll_refout_cc_impl : public pll_refout_cc { private: - float mod_2pi(float in); - float phase_detector(gr_complex sample, float ref_phase); + float mod_2pi(float in) + { + if (in > GR_M_PI) + return in - (2.0 * GR_M_PI); + else if (in < -GR_M_PI) + return in + (2.0 * GR_M_PI); + else + return in; + } + + float phase_detector(gr_complex sample, float ref_phase) + { + float sample_phase; + sample_phase = gr::fast_atan2f(sample.imag(), sample.real()); + return mod_2pi(sample_phase - ref_phase); + } + public: pll_refout_cc_impl(float loop_bw, float max_freq, float min_freq); diff --git a/gr-digital/lib/clock_recovery_mm_cc_impl.cc b/gr-digital/lib/clock_recovery_mm_cc_impl.cc index 0c1b7e0892..4f2f4c0c58 100644 --- a/gr-digital/lib/clock_recovery_mm_cc_impl.cc +++ b/gr-digital/lib/clock_recovery_mm_cc_impl.cc @@ -74,27 +74,6 @@ void clock_recovery_mm_cc_impl::forecast(int noutput_items, (int)ceil((noutput_items * d_omega) + d_interp->ntaps()) + FUDGE; } -gr_complex clock_recovery_mm_cc_impl::slicer_0deg(gr_complex sample) -{ - float real = 0, imag = 0; - - if (sample.real() > 0) - real = 1; - if (sample.imag() > 0) - imag = 1; - return gr_complex(real, imag); -} - -gr_complex clock_recovery_mm_cc_impl::slicer_45deg(gr_complex sample) -{ - float real = -1, imag = -1; - if (sample.real() > 0) - real = 1; - if (sample.imag() > 0) - imag = 1; - return gr_complex(real, imag); -} - void clock_recovery_mm_cc_impl::set_omega(float omega) { d_omega = omega; @@ -135,8 +114,8 @@ int clock_recovery_mm_cc_impl::general_work(int noutput_items, d_c_1T = d_c_0T; d_c_0T = slicer_0deg(d_p_0T); - x = (d_c_0T - d_c_2T) * conj(d_p_1T); - y = (d_p_0T - d_p_2T) * conj(d_c_1T); + fast_cc_multiply(x, d_c_0T - d_c_2T, conj(d_p_1T)); + fast_cc_multiply(y, d_p_0T - d_p_2T, conj(d_c_1T)); u = y - x; mm_val = u.real(); out[oo++] = d_p_0T; @@ -169,8 +148,8 @@ int clock_recovery_mm_cc_impl::general_work(int noutput_items, d_c_1T = d_c_0T; d_c_0T = slicer_0deg(d_p_0T); - x = (d_c_0T - d_c_2T) * conj(d_p_1T); - y = (d_p_0T - d_p_2T) * conj(d_c_1T); + fast_cc_multiply(x, d_c_0T - d_c_2T, conj(d_p_1T)); + fast_cc_multiply(y, d_p_0T - d_p_2T, conj(d_c_1T)); u = y - x; mm_val = u.real(); out[oo++] = d_p_0T; diff --git a/gr-digital/lib/clock_recovery_mm_cc_impl.h b/gr-digital/lib/clock_recovery_mm_cc_impl.h index cb444020c3..79402f5896 100644 --- a/gr-digital/lib/clock_recovery_mm_cc_impl.h +++ b/gr-digital/lib/clock_recovery_mm_cc_impl.h @@ -61,8 +61,26 @@ private: gr_complex d_p_2T, d_p_1T, d_p_0T; gr_complex d_c_2T, d_c_1T, d_c_0T; - gr_complex slicer_0deg(gr_complex sample); - gr_complex slicer_45deg(gr_complex sample); + gr_complex slicer_0deg(gr_complex sample) + { + float real = 0.0f, imag = 0.0f; + + if (sample.real() > 0.0f) + real = 1.0f; + if (sample.imag() > 0.0f) + imag = 1.0f; + return gr_complex(real, imag); + } + + gr_complex slicer_45deg(gr_complex sample) + { + float real = -1.0f, imag = -1.0f; + if (sample.real() > 0.0f) + real = 1.0f; + if (sample.imag() > 0.0f) + imag = 1.0f; + return gr_complex(real, imag); + } }; } /* namespace digital */ diff --git a/gr-digital/lib/clock_recovery_mm_ff_impl.cc b/gr-digital/lib/clock_recovery_mm_ff_impl.cc index 1c35c3c44e..ceff90a8e5 100644 --- a/gr-digital/lib/clock_recovery_mm_ff_impl.cc +++ b/gr-digital/lib/clock_recovery_mm_ff_impl.cc @@ -60,8 +60,6 @@ void clock_recovery_mm_ff_impl::forecast(int noutput_items, (int)ceil((noutput_items * d_omega) + d_interp->ntaps()); } -static inline float slice(float x) { return x < 0 ? -1.0F : 1.0F; } - void clock_recovery_mm_ff_impl::set_omega(float omega) { d_omega = omega; diff --git a/gr-digital/lib/clock_recovery_mm_ff_impl.h b/gr-digital/lib/clock_recovery_mm_ff_impl.h index 4a2b127134..f0361a8074 100644 --- a/gr-digital/lib/clock_recovery_mm_ff_impl.h +++ b/gr-digital/lib/clock_recovery_mm_ff_impl.h @@ -57,6 +57,8 @@ private: filter::mmse_fir_interpolator_ff* d_interp; bool d_verbose; + + float slice(float x) { return x < 0 ? -1.0F : 1.0F; } }; } /* namespace digital */ diff --git a/gr-digital/lib/clock_tracking_loop.cc b/gr-digital/lib/clock_tracking_loop.cc index 6c04d2d87e..2cb7c996c9 100644 --- a/gr-digital/lib/clock_tracking_loop.cc +++ b/gr-digital/lib/clock_tracking_loop.cc @@ -101,60 +101,6 @@ void clock_tracking_loop::update_gains() set_beta(beta); } -void clock_tracking_loop::advance_loop(float error) -{ - // So the loop can be reverted one step, if needed. - d_prev_avg_period = d_avg_period; - d_prev_inst_period = d_inst_period; - d_prev_phase = d_phase; - - // 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; -} - -void clock_tracking_loop::revert_loop() -{ - d_avg_period = d_prev_avg_period; - d_inst_period = d_prev_inst_period; - d_phase = d_prev_phase; -} - -void clock_tracking_loop::phase_wrap() -{ - float period = d_avg_period; // One could argue d_inst_period instead - float limit = period / 2.0f; - - while (d_phase > limit) - d_phase -= period; - - while (d_phase <= -limit) - d_phase += period; -} - -void clock_tracking_loop::period_limit() -{ - if (d_avg_period > d_max_avg_period) - d_avg_period = d_max_avg_period; - else if (d_avg_period < d_min_avg_period) - d_avg_period = d_min_avg_period; -} - /******************************************************************* * SET FUNCTIONS *******************************************************************/ diff --git a/gr-digital/lib/clock_tracking_loop.h b/gr-digital/lib/clock_tracking_loop.h index f215316a3e..981114117f 100644 --- a/gr-digital/lib/clock_tracking_loop.h +++ b/gr-digital/lib/clock_tracking_loop.h @@ -360,7 +360,32 @@ public: /*! \brief Advance the loop based on the current gain * settings and the input error signal. */ - void advance_loop(float error); + void advance_loop(float error) + { + // So the loop can be reverted one step, if needed. + d_prev_avg_period = d_avg_period; + d_prev_inst_period = d_inst_period; + d_prev_phase = d_phase; + + // 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; + } /*! \brief Undo a single, prior advance_loop() call. * @@ -373,7 +398,12 @@ public: * perform correctly given the constraints of GNURadio's streaming * engine, interpolation filtering, and tag propagation. */ - void revert_loop(); + void revert_loop() + { + d_avg_period = d_prev_avg_period; + d_inst_period = d_prev_inst_period; + d_phase = d_prev_phase; + } /*! \brief * Keep the clock phase estimate, tau, between -T_avg/2 and T_avg/2. @@ -391,7 +421,17 @@ public: * clock, and this class doesn't actually use the phase at all, * so calling this is optional. */ - void phase_wrap(); + void phase_wrap() + { + float period = d_avg_period; // One could argue d_inst_period instead + float limit = period / 2.0f; + + while (d_phase > limit) + d_phase -= period; + + while (d_phase <= -limit) + d_phase += period; + } /*! \brief * Keep the estimated average clock period, T_avg, between T_avg_min @@ -409,7 +449,13 @@ public: * It is set as a separate virtual method in case another way is desired * as this is fairly heavy-handed. */ - virtual void period_limit(); + virtual void period_limit() + { + if (d_avg_period > d_max_avg_period) + d_avg_period = d_max_avg_period; + else if (d_avg_period < d_min_avg_period) + d_avg_period = d_min_avg_period; + } /******************************************************************* * SET FUNCTIONS diff --git a/gr-dtv/lib/atsc/atsc_fpll_impl.cc b/gr-dtv/lib/atsc/atsc_fpll_impl.cc index b85a38207d..88d9940615 100644 --- a/gr-dtv/lib/atsc/atsc_fpll_impl.cc +++ b/gr-dtv/lib/atsc/atsc_fpll_impl.cc @@ -55,12 +55,7 @@ int atsc_fpll_impl::work(int noutput_items, d_nco.sincos(&a_sin, &a_cos); // compute cos and sin // Mix out carrier and output I-only signal - - // PR Merge Note: Once the Costas Optimization PR #3076 merges, this - // line below helps with performance when cx_limited_range is not available - // such as on Macs and Windows. Once the merge happens I'll push an update. - // gr::fast_cc_multiply(result, in[k], gr_complex(a_sin, a_cos)); - result = in[k] * gr_complex(a_sin, a_cos); + gr::fast_cc_multiply(result, in[k], gr_complex(a_sin, a_cos)); out[k] = result.real(); |