diff options
-rw-r--r-- | gr-digital/lib/digital_costas_loop_cc.cc | 34 | ||||
-rw-r--r-- | gr-digital/lib/digital_costas_loop_cc.h | 2 | ||||
-rw-r--r-- | gr-digital/python/qa_costas_loop_cc.py | 3 |
3 files changed, 23 insertions, 16 deletions
diff --git a/gr-digital/lib/digital_costas_loop_cc.cc b/gr-digital/lib/digital_costas_loop_cc.cc index b41b08cba..5d98bde4c 100644 --- a/gr-digital/lib/digital_costas_loop_cc.cc +++ b/gr-digital/lib/digital_costas_loop_cc.cc @@ -28,7 +28,7 @@ #include <gr_io_signature.h> #include <gr_expj.h> #include <gr_sincos.h> -#include <math.h> +#include <gr_math.h> #define M_TWOPI (2*M_PI) @@ -48,7 +48,6 @@ digital_costas_loop_cc::digital_costas_loop_cc (float damping, float nat_freq, : gr_sync_block ("costas_loop_cc", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature2 (1, 2, sizeof (gr_complex), sizeof(float))), - d_max_freq(1.0), d_min_freq(-1.0), d_phase(0), d_freq(0.0), d_nat_freq(nat_freq), d_damping(damping), d_order(order), d_phase_detector(NULL) @@ -78,8 +77,21 @@ digital_costas_loop_cc::digital_costas_loop_cc (float damping, float nat_freq, float digital_costas_loop_cc::phase_detector_8(gr_complex sample) const { - float K = sqrt(2.0) - 1; - if(abs(sample.real()) >= abs(sample.imag())) { + /* This technique splits the 8PSK constellation into 2 squashed + QPSK constellations, one when I is larger than Q and one where + Q is larger than I. The error is then calculated proportionally + to these squashed constellations by the const K = sqrt(2)-1. + + The signal magnitude must be > 1 or K will incorrectly bias + the error value. + + Ref: Z. Huang, Z. Yi, M. Zhang, K. Wang, "8PSK demodulation for + new generation DVB-S2", IEEE Proc. Int. Conf. Communications, + Circuits and Systems, Vol. 2, pp. 1447 - 1450, 2004. + */ + + float K = (sqrt(2.0) - 1); + if(fabsf(sample.real()) >= fabsf(sample.imag())) { return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - (sample.imag()>0 ? 1.0 : -1.0) * sample.real() * K); } @@ -145,10 +157,7 @@ digital_costas_loop_cc::work (int noutput_items, optr[i] = iptr[i] * nco_out; error = (*this.*d_phase_detector)(optr[i]); - if (error > 1) - error = 1; - else if (error < -1) - error = -1; + error = gr_branchless_clip(error, 1.0); d_freq = d_freq + d_beta * error; d_phase = d_phase + d_freq + d_alpha * error; @@ -171,10 +180,7 @@ digital_costas_loop_cc::work (int noutput_items, optr[i] = iptr[i] * nco_out; error = (*this.*d_phase_detector)(optr[i]); - if (error > 1) - error = 1; - else if (error < -1) - error = -1; + error = gr_branchless_clip(error, 1.0); d_freq = d_freq + d_beta * error; d_phase = d_phase + d_freq + d_alpha * error; @@ -185,9 +191,9 @@ digital_costas_loop_cc::work (int noutput_items, d_phase += M_TWOPI; if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) d_freq = d_min_freq; + else if (d_freq < d_min_freq) + d_freq = d_max_freq; } } diff --git a/gr-digital/lib/digital_costas_loop_cc.h b/gr-digital/lib/digital_costas_loop_cc.h index 9c112d328..2c4c38e8b 100644 --- a/gr-digital/lib/digital_costas_loop_cc.h +++ b/gr-digital/lib/digital_costas_loop_cc.h @@ -81,7 +81,7 @@ class digital_costas_loop_cc : public gr_sync_block ) throw (std::invalid_argument); float d_alpha, d_beta, d_max_freq, d_min_freq, d_phase, d_freq; - float d_nat_freq, d_damping; + float d_damping, d_nat_freq; int d_order; digital_costas_loop_cc (float damping, float nat_freq, diff --git a/gr-digital/python/qa_costas_loop_cc.py b/gr-digital/python/qa_costas_loop_cc.py index 0a1f4a97d..2d8ce6726 100644 --- a/gr-digital/python/qa_costas_loop_cc.py +++ b/gr-digital/python/qa_costas_loop_cc.py @@ -135,6 +135,7 @@ class test_digital(gr_unittest.TestCase): data = [2*rot*const[d] for d in data] N = 40 # settling time + data = [rot1*const[d] for d in data] # rotate to align with sync expected_result = data[N:] rot = cmath.exp(0.1j) # some small rotation @@ -148,7 +149,7 @@ class test_digital(gr_unittest.TestCase): dst_data = self.snk.data()[N:] - # generously compare results; the loop will converge near to, but + # generously compare results; the loop will converge near to, but # not exactly on, the target data self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 2) |