summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-digital/lib/digital_costas_loop_cc.cc34
-rw-r--r--gr-digital/lib/digital_costas_loop_cc.h2
-rw-r--r--gr-digital/python/qa_costas_loop_cc.py3
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)