summaryrefslogtreecommitdiff
path: root/gr-digital/lib/costas_loop_cc_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-digital/lib/costas_loop_cc_impl.cc')
-rw-r--r--gr-digital/lib/costas_loop_cc_impl.cc68
1 files changed, 61 insertions, 7 deletions
diff --git a/gr-digital/lib/costas_loop_cc_impl.cc b/gr-digital/lib/costas_loop_cc_impl.cc
index 36f95ac022..a53045ac55 100644
--- a/gr-digital/lib/costas_loop_cc_impl.cc
+++ b/gr-digital/lib/costas_loop_cc_impl.cc
@@ -35,37 +35,52 @@ namespace gr {
namespace digital {
costas_loop_cc::sptr
- costas_loop_cc::make(float loop_bw, int order)
+ costas_loop_cc::make(float loop_bw, int order, bool use_snr)
{
return gnuradio::get_initial_sptr
- (new costas_loop_cc_impl(loop_bw, order));
+ (new costas_loop_cc_impl(loop_bw, order, use_snr));
}
- costas_loop_cc_impl::costas_loop_cc_impl(float loop_bw, int order)
+ costas_loop_cc_impl::costas_loop_cc_impl(float loop_bw, int order, bool use_snr)
: sync_block("costas_loop_cc",
io_signature::make(1, 1, sizeof(gr_complex)),
io_signature::make2(1, 2, sizeof(gr_complex), sizeof(float))),
blocks::control_loop(loop_bw, 1.0, -1.0),
- d_order(order), d_error(0), d_phase_detector(NULL)
+ d_order(order), d_error(0), d_noise(1.0), d_phase_detector(NULL)
{
// Set up the phase detector to use based on the constellation order
switch(d_order) {
case 2:
- d_phase_detector = &costas_loop_cc_impl::phase_detector_2;
+ if(use_snr)
+ d_phase_detector = &costas_loop_cc_impl::phase_detector_snr_2;
+ else
+ d_phase_detector = &costas_loop_cc_impl::phase_detector_2;
break;
case 4:
- d_phase_detector = &costas_loop_cc_impl::phase_detector_4;
+ if(use_snr)
+ d_phase_detector = &costas_loop_cc_impl::phase_detector_snr_4;
+ else
+ d_phase_detector = &costas_loop_cc_impl::phase_detector_4;
break;
case 8:
- d_phase_detector = &costas_loop_cc_impl::phase_detector_8;
+ if(use_snr)
+ d_phase_detector = &costas_loop_cc_impl::phase_detector_snr_8;
+ else
+ d_phase_detector = &costas_loop_cc_impl::phase_detector_8;
break;
default:
throw std::invalid_argument("order must be 2, 4, or 8");
break;
}
+
+ message_port_register_in(pmt::mp("noise"));
+ set_msg_handler(
+ pmt::mp("noise"),
+ boost::bind(&costas_loop_cc_impl::handle_set_noise,
+ this, _1));
}
costas_loop_cc_impl::~costas_loop_cc_impl()
@@ -114,11 +129,50 @@ namespace gr {
}
float
+ costas_loop_cc_impl::phase_detector_snr_8(gr_complex sample) const
+ {
+ float K = (sqrt(2.0) - 1);
+ float snr = abs(sample)*abs(sample) / d_noise;
+ if(fabsf(sample.real()) >= fabsf(sample.imag())) {
+ return ((blocks::tanhf_lut(snr*sample.real()) * sample.imag()) -
+ (blocks::tanhf_lut(snr*sample.imag()) * sample.real() * K));
+ }
+ else {
+ return ((blocks::tanhf_lut(snr*sample.real()) * sample.imag() * K) -
+ (blocks::tanhf_lut(snr*sample.imag()) * sample.real()));
+ }
+ }
+
+ float
+ costas_loop_cc_impl::phase_detector_snr_4(gr_complex sample) const
+ {
+ float snr = abs(sample)*abs(sample) / d_noise;
+ return ((blocks::tanhf_lut(snr*sample.real()) * sample.imag()) -
+ (blocks::tanhf_lut(snr*sample.imag()) * sample.real()));
+ }
+
+ float
+ costas_loop_cc_impl::phase_detector_snr_2(gr_complex sample) const
+ {
+ float snr = abs(sample)*abs(sample) / d_noise;
+ return blocks::tanhf_lut(snr*sample.real()) * sample.imag();
+ }
+
+ float
costas_loop_cc_impl::error() const
{
return d_error;
}
+ void
+ costas_loop_cc_impl::handle_set_noise(pmt::pmt_t msg)
+ {
+ if(pmt::is_real(msg)) {
+ d_noise = pmt::to_double(msg);
+ d_noise = powf(10.0f, d_noise/10.0f);
+ }
+ }
+
int
costas_loop_cc_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,