summaryrefslogtreecommitdiff
path: root/gr-digital/lib
diff options
context:
space:
mode:
Diffstat (limited to 'gr-digital/lib')
-rw-r--r--gr-digital/lib/CMakeLists.txt13
-rw-r--r--gr-digital/lib/constellation.cc610
-rw-r--r--gr-digital/lib/constellation_decoder_cb_impl.cc84
-rw-r--r--gr-digital/lib/constellation_decoder_cb_impl.h53
-rw-r--r--gr-digital/lib/constellation_receiver_cb_impl.cc130
-rw-r--r--gr-digital/lib/constellation_receiver_cb_impl.h70
-rw-r--r--gr-digital/lib/digital_constellation.cc552
-rw-r--r--gr-digital/lib/digital_constellation_decoder_cb.cc77
-rw-r--r--gr-digital/lib/digital_constellation_receiver_cb.cc123
9 files changed, 953 insertions, 759 deletions
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index 2fffa15905..955c1eaddd 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -91,8 +91,9 @@ endmacro(expand_cc)
########################################################################
# Setup library
########################################################################
-list(APPEND gr_digital_sources
+list(APPEND digital_sources
${generated_sources}
+ constellation.cc
#impl_glfsr.cc
#impl_mpsk_snr_est.cc
additive_scrambler_bb_impl.cc
@@ -100,9 +101,8 @@ list(APPEND gr_digital_sources
clock_recovery_mm_cc_impl.cc
clock_recovery_mm_ff_impl.cc
cma_equalizer_cc_impl.cc
- #constellation_impl.cc
- #constellation_receiver_cb_impl.cc
- #constellation_decoder_cb_impl.cc
+ constellation_receiver_cb_impl.cc
+ constellation_decoder_cb_impl.cc
#correlate_access_code_bb_impl.cc
#correlate_access_code_tag_bb_impl.cc
#costas_loop_cc_impl.cc
@@ -145,8 +145,7 @@ list(APPEND digital_libs
${Boost_LIBRARIES}
)
-add_library(gnuradio-digital SHARED ${gr_digital_sources})
+add_library(gnuradio-digital SHARED ${digital_sources})
target_link_libraries(gnuradio-digital ${digital_libs})
GR_LIBRARY_FOO(gnuradio-digital RUNTIME_COMPONENT "digital_runtime" DEVEL_COMPONENT "digital_devel")
-
-add_dependencies(gnuradio-digital digital_generated_includes digital_generated_swigs)
+add_dependencies(gnuradio-digital digital_generated_includes digital_generated_swigs gnuradio-filter)
diff --git a/gr-digital/lib/constellation.cc b/gr-digital/lib/constellation.cc
new file mode 100644
index 0000000000..5cee6f477e
--- /dev/null
+++ b/gr-digital/lib/constellation.cc
@@ -0,0 +1,610 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include <digital/constellation.h>
+#include <digital_metric_type.h>
+#include <gr_math.h>
+#include <gr_complex.h>
+#include <math.h>
+#include <iostream>
+#include <stdlib.h>
+#include <float.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace digital {
+
+#define M_TWOPI (2*M_PI)
+#define SQRT_TWO 0.707107
+
+ // Base Constellation Class
+ constellation::constellation(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality) :
+ d_constellation(constell),
+ d_pre_diff_code(pre_diff_code),
+ d_rotational_symmetry(rotational_symmetry),
+ d_dimensionality(dimensionality)
+ {
+ if(pre_diff_code.size() == 0)
+ d_apply_pre_diff_code = false;
+ else if(pre_diff_code.size() != constell.size())
+ throw std::runtime_error("The constellation and pre-diff code must be of the same length.");
+ else
+ d_apply_pre_diff_code = true;
+ calc_arity();
+ }
+
+ constellation::constellation() :
+ d_apply_pre_diff_code(false),
+ d_rotational_symmetry(0),
+ d_dimensionality(1)
+ {
+ calc_arity();
+ }
+
+ constellation::~constellation()
+ {
+ }
+
+ //! Returns the constellation points for a symbol value
+ void
+ constellation::map_to_points(unsigned int value, gr_complex *points)
+ {
+ for(unsigned int i=0; i<d_dimensionality; i++)
+ points[i] = d_constellation[value*d_dimensionality + i];
+ }
+
+ std::vector<gr_complex>
+ constellation::map_to_points_v(unsigned int value)
+ {
+ std::vector<gr_complex> points_v;
+ points_v.resize(d_dimensionality);
+ map_to_points(value, &(points_v[0]));
+ return points_v;
+ }
+
+ float
+ constellation::get_distance(unsigned int index, const gr_complex *sample)
+ {
+ float dist = 0;
+ for(unsigned int i=0; i<d_dimensionality; i++) {
+ dist += norm(sample[i] - d_constellation[index*d_dimensionality + i]);
+ }
+ return dist;
+ }
+
+ unsigned int
+ constellation::get_closest_point(const gr_complex *sample)
+ {
+ unsigned int min_index = 0;
+ float min_euclid_dist;
+ float euclid_dist;
+
+ min_euclid_dist = get_distance(0, sample);
+ min_index = 0;
+ for(unsigned int j = 1; j < d_arity; j++){
+ euclid_dist = get_distance(j, sample);
+ if(euclid_dist < min_euclid_dist){
+ min_euclid_dist = euclid_dist;
+ min_index = j;
+ }
+ }
+ return min_index;
+ }
+
+ unsigned int
+ constellation::decision_maker_pe(const gr_complex *sample, float *phase_error)
+ {
+ unsigned int index = decision_maker(sample);
+ *phase_error = 0;
+ for(unsigned int d=0; d<d_dimensionality; d++)
+ *phase_error += -arg(sample[d]*conj(d_constellation[index+d]));
+ return index;
+ }
+
+ /*
+ unsigned int constellation::decision_maker_e(const gr_complex *sample, float *error)
+ {
+ unsigned int index = decision_maker(sample);
+ *error = 0;
+ for(unsigned int d=0; d<d_dimensionality; d++)
+ *error += sample[d]*conj(d_constellation[index+d]);
+ return index;
+ }
+ */
+
+ std::vector<gr_complex> constellation::s_points()
+ {
+ if(d_dimensionality != 1)
+ throw std::runtime_error("s_points only works for dimensionality 1 constellations.");
+ else
+ return d_constellation;
+ }
+
+ std::vector<std::vector<gr_complex> >
+ constellation::v_points()
+ {
+ std::vector<std::vector<gr_complex> > vv_const;
+ vv_const.resize(d_arity);
+ for(unsigned int p=0; p<d_arity; p++) {
+ std::vector<gr_complex> v_const;
+ v_const.resize(d_dimensionality);
+ for(unsigned int d=0; d<d_dimensionality; d++) {
+ v_const[d] = d_constellation[p*d_dimensionality+d];
+ }
+ vv_const[p] = v_const;
+ }
+ return vv_const;
+ }
+
+ void
+ constellation::calc_metric(const gr_complex *sample, float *metric,
+ trellis_metric_type_t type)
+ {
+ switch(type){
+ case TRELLIS_EUCLIDEAN:
+ calc_euclidean_metric(sample, metric);
+ break;
+ case TRELLIS_HARD_SYMBOL:
+ calc_hard_symbol_metric(sample, metric);
+ break;
+ case TRELLIS_HARD_BIT:
+ throw std::runtime_error("Invalid metric type (not yet implemented).");
+ break;
+ default:
+ throw std::runtime_error("Invalid metric type.");
+ }
+ }
+
+ void
+ constellation::calc_euclidean_metric(const gr_complex *sample, float *metric)
+ {
+ for(unsigned int o=0; o<d_arity; o++) {
+ metric[o] = get_distance(o, sample);
+ }
+ }
+
+ void
+ constellation::calc_hard_symbol_metric(const gr_complex *sample, float *metric)
+ {
+ float minm = FLT_MAX;
+ unsigned int minmi = 0;
+ for(unsigned int o=0; o<d_arity; o++) {
+ float dist = get_distance(o, sample);
+ if(dist < minm) {
+ minm = dist;
+ minmi = o;
+ }
+ }
+ for(unsigned int o=0; o<d_arity; o++) {
+ metric[o] = (o==minmi?0.0:1.0);
+ }
+ }
+
+ void
+ constellation::calc_arity()
+ {
+ if(d_constellation.size() % d_dimensionality != 0)
+ throw std::runtime_error("Constellation vector size must be a multiple of the dimensionality.");
+ d_arity = d_constellation.size()/d_dimensionality;
+ }
+
+ unsigned int
+ constellation::decision_maker_v(std::vector<gr_complex> sample)
+ {
+ assert(sample.size() == d_dimensionality);
+ return decision_maker(&(sample[0]));
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_calcdist::sptr
+ constellation_calcdist::make(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality)
+ {
+ return constellation_calcdist::sptr(new constellation_calcdist
+ (constell, pre_diff_code,
+ rotational_symmetry, dimensionality));
+ }
+
+ constellation_calcdist::constellation_calcdist(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality)
+ : constellation(constell, pre_diff_code, rotational_symmetry, dimensionality)
+ {}
+
+ // Chooses points base on shortest distance.
+ // Inefficient.
+ unsigned int
+ constellation_calcdist::decision_maker(const gr_complex *sample)
+ {
+ return get_closest_point(sample);
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_sector::constellation_sector(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality,
+ unsigned int n_sectors) :
+ constellation(constell, pre_diff_code, rotational_symmetry, dimensionality),
+ n_sectors(n_sectors)
+ {
+ }
+
+ unsigned int
+ constellation_sector::decision_maker(const gr_complex *sample)
+ {
+ unsigned int sector;
+ sector = get_sector(sample);
+ return sector_values[sector];
+ }
+
+ void
+ constellation_sector::find_sector_values()
+ {
+ unsigned int i;
+ sector_values.clear();
+ for(i=0; i<n_sectors; i++) {
+ sector_values.push_back(calc_sector_value(i));
+ }
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_rect::sptr
+ constellation_rect::make(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors,
+ unsigned int imag_sectors,
+ float width_real_sectors,
+ float width_imag_sectors)
+ {
+ return constellation_rect::sptr(new constellation_rect
+ (constell, pre_diff_code,
+ rotational_symmetry,
+ real_sectors, imag_sectors,
+ width_real_sectors,
+ width_imag_sectors));
+ }
+
+ constellation_rect::constellation_rect(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors, unsigned int imag_sectors,
+ float width_real_sectors, float width_imag_sectors) :
+ constellation_sector(constell, pre_diff_code, rotational_symmetry,
+ 1, real_sectors * imag_sectors),
+ n_real_sectors(real_sectors), n_imag_sectors(imag_sectors),
+ d_width_real_sectors(width_real_sectors), d_width_imag_sectors(width_imag_sectors)
+ {
+ find_sector_values();
+ }
+
+ unsigned int
+ constellation_rect::get_sector(const gr_complex *sample)
+ {
+ int real_sector, imag_sector;
+ unsigned int sector;
+
+ real_sector = int(real(*sample)/d_width_real_sectors + n_real_sectors/2.0);
+ if(real_sector < 0)
+ real_sector = 0;
+ if(real_sector >= (int)n_real_sectors)
+ real_sector = n_real_sectors-1;
+
+ imag_sector = int(imag(*sample)/d_width_imag_sectors + n_imag_sectors/2.0);
+ if(imag_sector < 0)
+ imag_sector = 0;
+ if(imag_sector >= (int)n_imag_sectors)
+ imag_sector = n_imag_sectors-1;
+
+ sector = real_sector * n_imag_sectors + imag_sector;
+ return sector;
+ }
+
+ unsigned int
+ constellation_rect::calc_sector_value(unsigned int sector)
+ {
+ unsigned int real_sector, imag_sector;
+ gr_complex sector_center;
+ unsigned int closest_point;
+ real_sector = float(sector)/n_imag_sectors;
+ imag_sector = sector - real_sector * n_imag_sectors;
+ sector_center = gr_complex((real_sector + 0.5 - n_real_sectors/2.0) * d_width_real_sectors,
+ (imag_sector + 0.5 - n_imag_sectors/2.0) * d_width_imag_sectors);
+ closest_point = get_closest_point(&sector_center);
+ return closest_point;
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_psk::sptr
+ constellation_psk::make(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors)
+ {
+ return constellation_psk::sptr(new constellation_psk
+ (constell, pre_diff_code,
+ n_sectors));
+ }
+
+ constellation_psk::constellation_psk(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors) :
+ constellation_sector(constell, pre_diff_code, constell.size(), 1, n_sectors)
+ {
+ find_sector_values();
+ }
+
+ constellation_psk::~constellation_psk()
+ {
+ }
+
+ unsigned int
+ constellation_psk::get_sector(const gr_complex *sample)
+ {
+ float phase = arg(*sample);
+ float width = M_TWOPI / n_sectors;
+ int sector = floor(phase/width + 0.5);
+ if(sector < 0)
+ sector += n_sectors;
+ return sector;
+ }
+
+ unsigned int
+ constellation_psk::calc_sector_value(unsigned int sector)
+ {
+ float phase = sector * M_TWOPI / n_sectors;
+ gr_complex sector_center = gr_complex(cos(phase), sin(phase));
+ unsigned int closest_point = get_closest_point(&sector_center);
+ return closest_point;
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_bpsk::sptr
+ constellation_bpsk::make()
+ {
+ return constellation_bpsk::sptr(new constellation_bpsk());
+ }
+
+ constellation_bpsk::constellation_bpsk()
+ {
+ d_constellation.resize(2);
+ d_constellation[0] = gr_complex(-1, 0);
+ d_constellation[1] = gr_complex(1, 0);
+ d_rotational_symmetry = 2;
+ d_dimensionality = 1;
+ calc_arity();
+ }
+
+ constellation_bpsk::~constellation_bpsk()
+ {
+ }
+
+ unsigned int
+ constellation_bpsk::decision_maker(const gr_complex *sample)
+ {
+ return (real(*sample) > 0);
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_qpsk::sptr
+ constellation_qpsk::make()
+ {
+ return constellation_qpsk::sptr(new constellation_qpsk());
+ }
+
+ constellation_qpsk::constellation_qpsk()
+ {
+ d_constellation.resize(4);
+ // Gray-coded
+ d_constellation[0] = gr_complex(-SQRT_TWO, -SQRT_TWO);
+ d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO);
+ d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO);
+
+ /*
+ d_constellation[0] = gr_complex(SQRT_TWO, SQRT_TWO);
+ d_constellation[1] = gr_complex(-SQRT_TWO, SQRT_TWO);
+ d_constellation[2] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ d_constellation[3] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ */
+
+ d_pre_diff_code.resize(4);
+ d_pre_diff_code[0] = 0x0;
+ d_pre_diff_code[1] = 0x2;
+ d_pre_diff_code[2] = 0x3;
+ d_pre_diff_code[3] = 0x1;
+
+ d_rotational_symmetry = 4;
+ d_dimensionality = 1;
+ calc_arity();
+ }
+
+ constellation_qpsk::~constellation_qpsk()
+ {
+ }
+
+ unsigned int
+ constellation_qpsk::decision_maker(const gr_complex *sample)
+ {
+ // Real component determines small bit.
+ // Imag component determines big bit.
+ return 2*(imag(*sample)>0) + (real(*sample)>0);
+
+ /*
+ bool a = real(*sample) > 0;
+ bool b = imag(*sample) > 0;
+ if(a) {
+ if(b)
+ return 0x0;
+ else
+ return 0x1;
+ }
+ else {
+ if(b)
+ return 0x2;
+ else
+ return 0x3;
+ }
+ */
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_dqpsk::sptr
+ constellation_dqpsk::make()
+ {
+ return constellation_dqpsk::sptr(new constellation_dqpsk());
+ }
+
+ constellation_dqpsk::constellation_dqpsk()
+ {
+ // This constellation is not gray coded, which allows
+ // us to use differential encodings (through diff_encode and
+ // diff_decode) on the symbols.
+ d_constellation.resize(4);
+ d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO);
+ d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO);
+ d_constellation[2] = gr_complex(-SQRT_TWO, -SQRT_TWO);
+ d_constellation[3] = gr_complex(+SQRT_TWO, -SQRT_TWO);
+
+ // Use this mapping to convert to gray code before diff enc.
+ d_pre_diff_code.resize(4);
+ d_pre_diff_code[0] = 0x0;
+ d_pre_diff_code[1] = 0x1;
+ d_pre_diff_code[2] = 0x3;
+ d_pre_diff_code[3] = 0x2;
+ d_apply_pre_diff_code = true;
+
+ d_rotational_symmetry = 4;
+ d_dimensionality = 1;
+ calc_arity();
+ }
+
+ constellation_dqpsk::~constellation_dqpsk()
+ {
+ }
+
+ unsigned int
+ constellation_dqpsk::decision_maker(const gr_complex *sample)
+ {
+ // Slower deicison maker as we can't slice along one axis.
+ // Maybe there's a better way to do this, still.
+
+ bool a = real(*sample) > 0;
+ bool b = imag(*sample) > 0;
+ if(a) {
+ if(b)
+ return 0x0;
+ else
+ return 0x3;
+ }
+ else {
+ if(b)
+ return 0x1;
+ else
+ return 0x2;
+ }
+ }
+
+
+ /********************************************************************/
+
+
+ constellation_8psk::sptr
+ constellation_8psk::make()
+ {
+ return constellation_8psk::sptr(new constellation_8psk());
+ }
+
+ constellation_8psk::constellation_8psk()
+ {
+ float angle = M_PI/8.0;
+ d_constellation.resize(8);
+ // Gray-coded
+ d_constellation[0] = gr_complex(cos( 1*angle), sin( 1*angle));
+ d_constellation[1] = gr_complex(cos( 7*angle), sin( 7*angle));
+ d_constellation[2] = gr_complex(cos(15*angle), sin(15*angle));
+ d_constellation[3] = gr_complex(cos( 9*angle), sin( 9*angle));
+ d_constellation[4] = gr_complex(cos( 3*angle), sin( 3*angle));
+ d_constellation[5] = gr_complex(cos( 5*angle), sin( 5*angle));
+ d_constellation[6] = gr_complex(cos(13*angle), sin(13*angle));
+ d_constellation[7] = gr_complex(cos(11*angle), sin(11*angle));
+ d_rotational_symmetry = 8;
+ d_dimensionality = 1;
+ calc_arity();
+ }
+
+ constellation_8psk::~constellation_8psk()
+ {
+ }
+
+ unsigned int
+ constellation_8psk::decision_maker(const gr_complex *sample)
+ {
+ unsigned int ret = 0;
+
+ float re = sample->real();
+ float im = sample->imag();
+
+ if(fabsf(re) <= fabsf(im))
+ ret = 4;
+ if(re <= 0)
+ ret |= 1;
+ if(im <= 0)
+ ret |= 2;
+
+ return ret;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/constellation_decoder_cb_impl.cc b/gr-digital/lib/constellation_decoder_cb_impl.cc
new file mode 100644
index 0000000000..e764ccc629
--- /dev/null
+++ b/gr-digital/lib/constellation_decoder_cb_impl.cc
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "constellation_decoder_cb_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace digital {
+
+ constellation_decoder_cb::sptr
+ constellation_decoder_cb::make(constellation_sptr constellation)
+ {
+ return gnuradio::get_initial_sptr
+ (new constellation_decoder_cb_impl(constellation));
+ }
+
+ constellation_decoder_cb_impl::
+ constellation_decoder_cb_impl(constellation_sptr constellation)
+ : gr_block("constellation_decoder_cb",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(unsigned char))),
+ d_constellation(constellation),
+ d_dim(constellation->dimensionality())
+ {
+ set_relative_rate(1.0 / ((double)d_dim));
+ }
+
+ constellation_decoder_cb_impl::~constellation_decoder_cb_impl()
+ {
+ }
+
+ void
+ constellation_decoder_cb_impl::forecast(int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ unsigned int input_required = noutput_items * d_dim;
+
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned int i = 0; i < ninputs; i++)
+ ninput_items_required[i] = input_required;
+ }
+
+ int
+ constellation_decoder_cb_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex const *in = (const gr_complex*)input_items[0];
+ unsigned char *out = (unsigned char*)output_items[0];
+
+ for(int i = 0; i < noutput_items; i++) {
+ out[i] = d_constellation->decision_maker(&(in[i*d_dim]));
+ }
+
+ consume_each(noutput_items * d_dim);
+ return noutput_items;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/constellation_decoder_cb_impl.h b/gr-digital/lib/constellation_decoder_cb_impl.h
new file mode 100644
index 0000000000..5972760507
--- /dev/null
+++ b/gr-digital/lib/constellation_decoder_cb_impl.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_IMPL_H
+#define INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_IMPL_H
+
+#include <digital/constellation_decoder_cb.h>
+
+namespace gr {
+ namespace digital {
+
+ class constellation_decoder_cb_impl : public constellation_decoder_cb
+ {
+ private:
+ constellation_sptr d_constellation;
+ unsigned int d_dim;
+
+ public:
+ constellation_decoder_cb_impl(constellation_sptr constellation);
+ ~constellation_decoder_cb_impl();
+
+ void forecast(int noutput_items,
+ gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_IMPL_H */
diff --git a/gr-digital/lib/constellation_receiver_cb_impl.cc b/gr-digital/lib/constellation_receiver_cb_impl.cc
new file mode 100644
index 0000000000..f01e15ea8b
--- /dev/null
+++ b/gr-digital/lib/constellation_receiver_cb_impl.cc
@@ -0,0 +1,130 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "constellation_receiver_cb_impl.h"
+#include <gr_io_signature.h>
+#include <gr_prefs.h>
+#include <gr_math.h>
+#include <gr_expj.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace digital {
+
+#define M_TWOPI (2*M_PI)
+#define VERBOSE_MM 0 // Used for debugging symbol timing loop
+#define VERBOSE_COSTAS 0 // Used for debugging phase and frequency tracking
+
+ constellation_receiver_cb::sptr
+ constellation_receiver_cb::make(constellation_sptr constell,
+ float loop_bw, float fmin, float fmax)
+ {
+ return gnuradio::get_initial_sptr
+ (new constellation_receiver_cb_impl(constell, loop_bw,
+ fmin, fmax));
+ }
+
+ static int ios[] = {sizeof(char), sizeof(float), sizeof(float), sizeof(float)};
+ static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int));
+ constellation_receiver_cb_impl::constellation_receiver_cb_impl(constellation_sptr constellation,
+ float loop_bw, float fmin, float fmax)
+ : gr_block("constellation_receiver_cb",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signaturev(1, 4, iosig)),
+ gri_control_loop(loop_bw, fmax, fmin),
+ d_constellation(constellation),
+ d_current_const_point(0)
+ {
+ if(d_constellation->dimensionality() != 1)
+ throw std::runtime_error("This receiver only works with constellations of dimension 1.");
+ }
+
+ constellation_receiver_cb_impl::~constellation_receiver_cb_impl()
+ {
+ }
+
+ void
+ constellation_receiver_cb_impl::phase_error_tracking(float phase_error)
+ {
+ advance_loop(phase_error);
+ phase_wrap();
+ frequency_limit();
+
+#if VERBOSE_COSTAS
+ printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n",
+ phase_error, d_phase, d_freq, sample.real(), sample.imag(),
+ d_constellation->points()[d_current_const_point].real(),
+ d_constellation->points()[d_current_const_point].imag());
+#endif
+ }
+
+ int
+ constellation_receiver_cb_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex *)input_items[0];
+ unsigned char *out = (unsigned char *)output_items[0];
+
+ int i=0;
+
+ float phase_error;
+ unsigned int sym_value;
+ gr_complex sample, nco;
+
+ float *out_err = 0, *out_phase = 0, *out_freq = 0;
+ if(output_items.size() == 4) {
+ out_err = (float*)output_items[1];
+ out_phase = (float*)output_items[2];
+ out_freq = (float*)output_items[3];
+ }
+
+ while((i < noutput_items) && (i < ninput_items[0])) {
+ sample = in[i];
+ nco = gr_expj(d_phase); // get the NCO value for derotating the current sample
+ sample = nco*sample; // get the downconverted symbol
+
+ sym_value = d_constellation->decision_maker_pe(&sample, &phase_error);
+ phase_error_tracking(phase_error); // corrects phase and frequency offsets
+
+ out[i] = sym_value;
+
+ if(output_items.size() == 4) {
+ out_err[i] = phase_error;
+ out_phase[i] = d_phase;
+ out_freq[i] = d_freq;
+ }
+ i++;
+ }
+
+ consume_each(i);
+ return i;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/constellation_receiver_cb_impl.h b/gr-digital/lib/constellation_receiver_cb_impl.h
new file mode 100644
index 0000000000..50946840ae
--- /dev/null
+++ b/gr-digital/lib/constellation_receiver_cb_impl.h
@@ -0,0 +1,70 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_IMPL_H
+#define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_IMPL_H
+
+#include <digital/constellation_receiver_cb.h>
+#include <gruel/attributes.h>
+#include <gr_complex.h>
+#include <gri_control_loop.h>
+
+namespace gr {
+ namespace digital {
+
+ class constellation_receiver_cb_impl
+ : public constellation_receiver_cb, gri_control_loop
+ {
+ public:
+ constellation_receiver_cb_impl(constellation_sptr constell,
+ float loop_bw, float fmin, float fmax);
+
+ ~constellation_receiver_cb_impl();
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ protected:
+ void phase_error_tracking(float phase_error);
+
+ private:
+ unsigned int d_M;
+
+ constellation_sptr d_constellation;
+ unsigned int d_current_const_point;
+
+ //! delay line length.
+ static const unsigned int DLLEN = 8;
+
+ //! delay line plus some length for overflow protection
+ __GR_ATTR_ALIGNED(8) gr_complex d_dl[2*DLLEN];
+
+ //! index to delay line
+ unsigned int d_dl_idx;
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_IMPL_H */
diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc
deleted file mode 100644
index 383c73c30d..0000000000
--- a/gr-digital/lib/digital_constellation.cc
+++ /dev/null
@@ -1,552 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2010, 2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_io_signature.h>
-#include <digital_constellation.h>
-#include <digital_metric_type.h>
-#include <gr_math.h>
-#include <gr_complex.h>
-#include <math.h>
-#include <iostream>
-#include <stdlib.h>
-#include <float.h>
-#include <stdexcept>
-
-#define M_TWOPI (2*M_PI)
-#define SQRT_TWO 0.707107
-
-// Base Constellation Class
-
-digital_constellation::digital_constellation (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality) :
- d_constellation(constellation),
- d_pre_diff_code(pre_diff_code),
- d_rotational_symmetry(rotational_symmetry),
- d_dimensionality(dimensionality)
-{
- if (pre_diff_code.size() == 0)
- d_apply_pre_diff_code = false;
- else if (pre_diff_code.size() != constellation.size())
- throw std::runtime_error ("The constellation and pre-diff code must be of the same length.");
- else
- d_apply_pre_diff_code = true;
- calc_arity();
-}
-
-digital_constellation::digital_constellation () :
- d_apply_pre_diff_code(false),
- d_rotational_symmetry(0),
- d_dimensionality(1)
-{
- calc_arity();
-}
-
-//! Returns the constellation points for a symbol value
-void
-digital_constellation::map_to_points(unsigned int value, gr_complex *points)
-{
- for (unsigned int i=0; i<d_dimensionality; i++)
- points[i] = d_constellation[value*d_dimensionality + i];
-}
-
-std::vector<gr_complex>
-digital_constellation::map_to_points_v(unsigned int value)
-{
- std::vector<gr_complex> points_v;
- points_v.resize(d_dimensionality);
- map_to_points(value, &(points_v[0]));
- return points_v;
-}
-
-float
-digital_constellation::get_distance(unsigned int index, const gr_complex *sample)
-{
- float dist = 0;
- for (unsigned int i=0; i<d_dimensionality; i++) {
- dist += norm(sample[i] - d_constellation[index*d_dimensionality + i]);
- }
- return dist;
-}
-
-unsigned int
-digital_constellation::get_closest_point(const gr_complex *sample)
-{
- unsigned int min_index = 0;
- float min_euclid_dist;
- float euclid_dist;
-
- min_euclid_dist = get_distance(0, sample);
- min_index = 0;
- for (unsigned int j = 1; j < d_arity; j++){
- euclid_dist = get_distance(j, sample);
- if (euclid_dist < min_euclid_dist){
- min_euclid_dist = euclid_dist;
- min_index = j;
- }
- }
- return min_index;
-}
-
-unsigned int
-digital_constellation::decision_maker_pe(const gr_complex *sample, float *phase_error)
-{
- unsigned int index = decision_maker(sample);
- *phase_error = 0;
- for (unsigned int d=0; d<d_dimensionality; d++)
- *phase_error += -arg(sample[d]*conj(d_constellation[index+d]));
- return index;
-}
-
-/*
-unsigned int digital_constellation::decision_maker_e(const gr_complex *sample, float *error)
-{
- unsigned int index = decision_maker(sample);
- *error = 0;
- for (unsigned int d=0; d<d_dimensionality; d++)
- *error += sample[d]*conj(d_constellation[index+d]);
- return index;
-}
-*/
-
-std::vector<gr_complex> digital_constellation::s_points () {
- if (d_dimensionality != 1)
- throw std::runtime_error ("s_points only works for dimensionality 1 constellations.");
- else
- return d_constellation;
-}
-
-std::vector<std::vector<gr_complex> >
-digital_constellation::v_points ()
-{
- std::vector<std::vector<gr_complex> > vv_const;
- vv_const.resize(d_arity);
- for (unsigned int p=0; p<d_arity; p++) {
- std::vector<gr_complex> v_const;
- v_const.resize(d_dimensionality);
- for (unsigned int d=0; d<d_dimensionality; d++) {
- v_const[d] = d_constellation[p*d_dimensionality+d];
- }
- vv_const[p] = v_const;
- }
- return vv_const;
-}
-
-void
-digital_constellation::calc_metric(const gr_complex *sample, float *metric,
- trellis_metric_type_t type)
-{
- switch (type){
- case TRELLIS_EUCLIDEAN:
- calc_euclidean_metric(sample, metric);
- break;
- case TRELLIS_HARD_SYMBOL:
- calc_hard_symbol_metric(sample, metric);
- break;
- case TRELLIS_HARD_BIT:
- throw std::runtime_error ("Invalid metric type (not yet implemented).");
- break;
- default:
- throw std::runtime_error ("Invalid metric type.");
- }
-}
-
-void
-digital_constellation::calc_euclidean_metric(const gr_complex *sample, float *metric)
-{
- for (unsigned int o=0; o<d_arity; o++) {
- metric[o] = get_distance(o, sample);
- }
-}
-
-void
-digital_constellation::calc_hard_symbol_metric(const gr_complex *sample, float *metric)
-{
- float minm = FLT_MAX;
- unsigned int minmi = 0;
- for (unsigned int o=0; o<d_arity; o++) {
- float dist = get_distance(o, sample);
- if (dist < minm) {
- minm = dist;
- minmi = o;
- }
- }
- for(unsigned int o=0; o<d_arity; o++) {
- metric[o] = (o==minmi?0.0:1.0);
- }
-}
-
-void
-digital_constellation::calc_arity ()
-{
- if (d_constellation.size() % d_dimensionality != 0)
- throw std::runtime_error ("Constellation vector size must be a multiple of the dimensionality.");
- d_arity = d_constellation.size()/d_dimensionality;
-}
-
-unsigned int
-digital_constellation::decision_maker_v (std::vector<gr_complex> sample)
-{
- assert(sample.size() == d_dimensionality);
- return decision_maker (&(sample[0]));
-}
-
-digital_constellation_calcdist_sptr
-digital_make_constellation_calcdist(std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality)
-{
- return digital_constellation_calcdist_sptr(new digital_constellation_calcdist
- (constellation, pre_diff_code,
- rotational_symmetry, dimensionality));
-}
-
-digital_constellation_calcdist::digital_constellation_calcdist(std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality) :
- digital_constellation(constellation, pre_diff_code, rotational_symmetry, dimensionality)
-{}
-
-// Chooses points base on shortest distance.
-// Inefficient.
-unsigned int
-digital_constellation_calcdist::decision_maker(const gr_complex *sample)
-{
- return get_closest_point(sample);
-}
-
-digital_constellation_sector::digital_constellation_sector (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality,
- unsigned int n_sectors) :
- digital_constellation(constellation, pre_diff_code, rotational_symmetry, dimensionality),
- n_sectors(n_sectors)
-{
-}
-
-unsigned int
-digital_constellation_sector::decision_maker (const gr_complex *sample)
-{
- unsigned int sector;
- sector = get_sector(sample);
- return sector_values[sector];
-}
-
-void
-digital_constellation_sector::find_sector_values ()
-{
- unsigned int i;
- sector_values.clear();
- for (i=0; i<n_sectors; i++) {
- sector_values.push_back(calc_sector_value(i));
- }
-}
-
-digital_constellation_rect_sptr
-digital_make_constellation_rect(std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors)
-{
- return digital_constellation_rect_sptr(new digital_constellation_rect
- (constellation, pre_diff_code,
- rotational_symmetry,
- real_sectors, imag_sectors,
- width_real_sectors,
- width_imag_sectors));
- }
-
-digital_constellation_rect::digital_constellation_rect (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors) :
- digital_constellation_sector(constellation, pre_diff_code, rotational_symmetry, 1, real_sectors * imag_sectors),
- n_real_sectors(real_sectors), n_imag_sectors(imag_sectors),
- d_width_real_sectors(width_real_sectors), d_width_imag_sectors(width_imag_sectors)
-{
- find_sector_values();
-}
-
-unsigned int
-digital_constellation_rect::get_sector (const gr_complex *sample)
-{
- int real_sector, imag_sector;
- unsigned int sector;
-
- real_sector = int(real(*sample)/d_width_real_sectors + n_real_sectors/2.0);
- if(real_sector < 0)
- real_sector = 0;
- if(real_sector >= (int)n_real_sectors)
- real_sector = n_real_sectors-1;
-
- imag_sector = int(imag(*sample)/d_width_imag_sectors + n_imag_sectors/2.0);
- if(imag_sector < 0)
- imag_sector = 0;
- if(imag_sector >= (int)n_imag_sectors)
- imag_sector = n_imag_sectors-1;
-
- sector = real_sector * n_imag_sectors + imag_sector;
- return sector;
-}
-
-unsigned int
-digital_constellation_rect::calc_sector_value (unsigned int sector)
-{
- unsigned int real_sector, imag_sector;
- gr_complex sector_center;
- unsigned int closest_point;
- real_sector = float(sector)/n_imag_sectors;
- imag_sector = sector - real_sector * n_imag_sectors;
- sector_center = gr_complex((real_sector + 0.5 - n_real_sectors/2.0) * d_width_real_sectors,
- (imag_sector + 0.5 - n_imag_sectors/2.0) * d_width_imag_sectors);
- closest_point = get_closest_point(&sector_center);
- return closest_point;
-}
-
-
-digital_constellation_psk_sptr
-digital_make_constellation_psk(std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int n_sectors)
-{
- return digital_constellation_psk_sptr(new digital_constellation_psk
- (constellation, pre_diff_code,
- n_sectors));
-}
-
-digital_constellation_psk::digital_constellation_psk (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int n_sectors) :
- digital_constellation_sector(constellation, pre_diff_code, constellation.size(), 1, n_sectors)
-{
- find_sector_values();
-}
-
-unsigned int
-digital_constellation_psk::get_sector (const gr_complex *sample)
-{
- float phase = arg(*sample);
- float width = M_TWOPI / n_sectors;
- int sector = floor(phase/width + 0.5);
- if (sector < 0)
- sector += n_sectors;
- return sector;
-}
-
-unsigned int
-digital_constellation_psk::calc_sector_value (unsigned int sector)
-{
- float phase = sector * M_TWOPI / n_sectors;
- gr_complex sector_center = gr_complex(cos(phase), sin(phase));
- unsigned int closest_point = get_closest_point(&sector_center);
- return closest_point;
-}
-
-
-digital_constellation_bpsk_sptr
-digital_make_constellation_bpsk()
-{
- return digital_constellation_bpsk_sptr(new digital_constellation_bpsk ());
-}
-
-digital_constellation_bpsk::digital_constellation_bpsk ()
-{
- d_constellation.resize(2);
- d_constellation[0] = gr_complex(-1, 0);
- d_constellation[1] = gr_complex(1, 0);
- d_rotational_symmetry = 2;
- d_dimensionality = 1;
- calc_arity();
-}
-
-unsigned int
-digital_constellation_bpsk::decision_maker(const gr_complex *sample)
-{
- return (real(*sample) > 0);
-}
-
-
-digital_constellation_qpsk_sptr
-digital_make_constellation_qpsk()
-{
- return digital_constellation_qpsk_sptr(new digital_constellation_qpsk ());
-}
-
-digital_constellation_qpsk::digital_constellation_qpsk ()
-{
- d_constellation.resize(4);
- // Gray-coded
- d_constellation[0] = gr_complex(-SQRT_TWO, -SQRT_TWO);
- d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO);
- d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO);
- d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO);
-
- /*
- d_constellation[0] = gr_complex(SQRT_TWO, SQRT_TWO);
- d_constellation[1] = gr_complex(-SQRT_TWO, SQRT_TWO);
- d_constellation[2] = gr_complex(SQRT_TWO, -SQRT_TWO);
- d_constellation[3] = gr_complex(SQRT_TWO, -SQRT_TWO);
- */
-
- d_pre_diff_code.resize(4);
- d_pre_diff_code[0] = 0x0;
- d_pre_diff_code[1] = 0x2;
- d_pre_diff_code[2] = 0x3;
- d_pre_diff_code[3] = 0x1;
-
- d_rotational_symmetry = 4;
- d_dimensionality = 1;
- calc_arity();
-}
-
-unsigned int
-digital_constellation_qpsk::decision_maker(const gr_complex *sample)
-{
- // Real component determines small bit.
- // Imag component determines big bit.
- return 2*(imag(*sample)>0) + (real(*sample)>0);
-
- /*
- bool a = real(*sample) > 0;
- bool b = imag(*sample) > 0;
- if(a) {
- if(b)
- return 0x0;
- else
- return 0x1;
- }
- else {
- if(b)
- return 0x2;
- else
- return 0x3;
- }
- */
-}
-
-
-/********************************************************************/
-
-
-digital_constellation_dqpsk_sptr
-digital_make_constellation_dqpsk()
-{
- return digital_constellation_dqpsk_sptr(new digital_constellation_dqpsk ());
-}
-
-digital_constellation_dqpsk::digital_constellation_dqpsk ()
-{
- // This constellation is not gray coded, which allows
- // us to use differential encodings (through digital_diff_encode and
- // digital_diff_decode) on the symbols.
- d_constellation.resize(4);
- d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO);
- d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO);
- d_constellation[2] = gr_complex(-SQRT_TWO, -SQRT_TWO);
- d_constellation[3] = gr_complex(+SQRT_TWO, -SQRT_TWO);
-
- // Use this mapping to convert to gray code before diff enc.
- d_pre_diff_code.resize(4);
- d_pre_diff_code[0] = 0x0;
- d_pre_diff_code[1] = 0x1;
- d_pre_diff_code[2] = 0x3;
- d_pre_diff_code[3] = 0x2;
- d_apply_pre_diff_code = true;
-
- d_rotational_symmetry = 4;
- d_dimensionality = 1;
- calc_arity();
-}
-
-unsigned int
-digital_constellation_dqpsk::decision_maker(const gr_complex *sample)
-{
- // Slower deicison maker as we can't slice along one axis.
- // Maybe there's a better way to do this, still.
-
- bool a = real(*sample) > 0;
- bool b = imag(*sample) > 0;
- if(a) {
- if(b)
- return 0x0;
- else
- return 0x3;
- }
- else {
- if(b)
- return 0x1;
- else
- return 0x2;
- }
-}
-
-digital_constellation_8psk_sptr
-digital_make_constellation_8psk()
-{
- return digital_constellation_8psk_sptr(new digital_constellation_8psk ());
-}
-
-digital_constellation_8psk::digital_constellation_8psk ()
-{
- float angle = M_PI/8.0;
- d_constellation.resize(8);
- // Gray-coded
- d_constellation[0] = gr_complex(cos( 1*angle), sin( 1*angle));
- d_constellation[1] = gr_complex(cos( 7*angle), sin( 7*angle));
- d_constellation[2] = gr_complex(cos(15*angle), sin(15*angle));
- d_constellation[3] = gr_complex(cos( 9*angle), sin( 9*angle));
- d_constellation[4] = gr_complex(cos( 3*angle), sin( 3*angle));
- d_constellation[5] = gr_complex(cos( 5*angle), sin( 5*angle));
- d_constellation[6] = gr_complex(cos(13*angle), sin(13*angle));
- d_constellation[7] = gr_complex(cos(11*angle), sin(11*angle));
- d_rotational_symmetry = 8;
- d_dimensionality = 1;
- calc_arity();
-}
-
-unsigned int
-digital_constellation_8psk::decision_maker(const gr_complex *sample)
-{
- unsigned int ret = 0;
-
- float re = sample->real();
- float im = sample->imag();
-
- if(fabsf(re) <= fabsf(im))
- ret = 4;
- if(re <= 0)
- ret |= 1;
- if(im <= 0)
- ret |= 2;
-
- return ret;
-}
diff --git a/gr-digital/lib/digital_constellation_decoder_cb.cc b/gr-digital/lib/digital_constellation_decoder_cb.cc
deleted file mode 100644
index 4638790f61..0000000000
--- a/gr-digital/lib/digital_constellation_decoder_cb.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <digital_constellation_decoder_cb.h>
-#include <digital_constellation.h>
-#include <gr_io_signature.h>
-#include <iostream>
-
-digital_constellation_decoder_cb_sptr
-digital_make_constellation_decoder_cb (digital_constellation_sptr constellation)
-{
- return gnuradio::get_initial_sptr
- (new digital_constellation_decoder_cb(constellation));
-}
-
-digital_constellation_decoder_cb::
-digital_constellation_decoder_cb (digital_constellation_sptr constellation)
- : gr_block ("constellation_decoder_cb",
- gr_make_io_signature (1, 1, sizeof (gr_complex)),
- gr_make_io_signature (1, 1, sizeof (unsigned char))),
- d_constellation(constellation),
- d_dim(constellation->dimensionality())
-{
- set_relative_rate (1.0 / ((double) d_dim));
-}
-
-void
-digital_constellation_decoder_cb::forecast (int noutput_items,
- gr_vector_int &ninput_items_required)
-{
- unsigned int input_required = noutput_items * d_dim;
-
- unsigned ninputs = ninput_items_required.size();
- for (unsigned int i = 0; i < ninputs; i++)
- ninput_items_required[i] = input_required;
-}
-
-
-int
-digital_constellation_decoder_cb::general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- gr_complex const *in = (const gr_complex *) input_items[0];
- unsigned char *out = (unsigned char *) output_items[0];
-
- for(int i = 0; i < noutput_items; i++){
- out[i] = d_constellation->decision_maker(&(in[i*d_dim]));
- }
-
- consume_each (noutput_items * d_dim);
- return noutput_items;
-}
diff --git a/gr-digital/lib/digital_constellation_receiver_cb.cc b/gr-digital/lib/digital_constellation_receiver_cb.cc
deleted file mode 100644
index b9239962a7..0000000000
--- a/gr-digital/lib/digital_constellation_receiver_cb.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_io_signature.h>
-#include <gr_prefs.h>
-#include <digital_constellation_receiver_cb.h>
-#include <stdexcept>
-#include <gr_math.h>
-#include <gr_expj.h>
-
-
-#define M_TWOPI (2*M_PI)
-#define VERBOSE_MM 0 // Used for debugging symbol timing loop
-#define VERBOSE_COSTAS 0 // Used for debugging phase and frequency tracking
-
-// Public constructor
-
-digital_constellation_receiver_cb_sptr
-digital_make_constellation_receiver_cb(digital_constellation_sptr constell,
- float loop_bw, float fmin, float fmax)
-{
- return gnuradio::get_initial_sptr(new digital_constellation_receiver_cb (constell,
- loop_bw,
- fmin, fmax));
-}
-
-static int ios[] = {sizeof(char), sizeof(float), sizeof(float), sizeof(float)};
-static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int));
-digital_constellation_receiver_cb::digital_constellation_receiver_cb (digital_constellation_sptr constellation,
- float loop_bw, float fmin, float fmax)
- : gr_block ("constellation_receiver_cb",
- gr_make_io_signature (1, 1, sizeof (gr_complex)),
- gr_make_io_signaturev (1, 4, iosig)),
- gri_control_loop(loop_bw, fmax, fmin),
- d_constellation(constellation),
- d_current_const_point(0)
-{
- if (d_constellation->dimensionality() != 1)
- throw std::runtime_error ("This receiver only works with constellations of dimension 1.");
-}
-
-void
-digital_constellation_receiver_cb::phase_error_tracking(float phase_error)
-{
- advance_loop(phase_error);
- phase_wrap();
- frequency_limit();
-
-#if VERBOSE_COSTAS
- printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n",
- phase_error, d_phase, d_freq, sample.real(), sample.imag(),
- d_constellation->points()[d_current_const_point].real(),
- d_constellation->points()[d_current_const_point].imag());
-#endif
-}
-
-int
-digital_constellation_receiver_cb::general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- const gr_complex *in = (const gr_complex *) input_items[0];
- unsigned char *out = (unsigned char *) output_items[0];
-
- int i=0;
-
- float phase_error;
- unsigned int sym_value;
- gr_complex sample, nco;
-
- float *out_err = 0, *out_phase = 0, *out_freq = 0;
- if(output_items.size() == 4) {
- out_err = (float *) output_items[1];
- out_phase = (float *) output_items[2];
- out_freq = (float *) output_items[3];
- }
-
- while((i < noutput_items) && (i < ninput_items[0])) {
- sample = in[i];
- nco = gr_expj(d_phase); // get the NCO value for derotating the current sample
- sample = nco*sample; // get the downconverted symbol
-
- sym_value = d_constellation->decision_maker_pe(&sample, &phase_error);
- phase_error_tracking(phase_error); // corrects phase and frequency offsets
-
- out[i] = sym_value;
-
- if(output_items.size() == 4) {
- out_err[i] = phase_error;
- out_phase[i] = d_phase;
- out_freq[i] = d_freq;
- }
- i++;
- }
-
- consume_each(i);
- return i;
-}
-