summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2012-08-11 11:04:03 -0400
committerTom Rondeau <trondeau@vt.edu>2012-08-11 11:04:03 -0400
commita6e56683cf74054fad6774138bea9f844c76be09 (patch)
tree1749031397ac4ebdc117b05a753c82976e8aca62
parentaf0a5780201c71c8f2d682cdab2274942e5771d5 (diff)
digital: converted over constellation and related blocks.
Possibly still a work-in-progress. Need to convert over some more before QA can be run.
-rw-r--r--gr-digital/include/digital/CMakeLists.txt6
-rw-r--r--gr-digital/include/digital/constellation.h417
-rw-r--r--gr-digital/include/digital/constellation_decoder_cb.h55
-rw-r--r--gr-digital/include/digital/constellation_receiver_cb.h93
-rw-r--r--gr-digital/include/digital_constellation.h449
-rw-r--r--gr-digital/include/digital_constellation_decoder_cb.h66
-rw-r--r--gr-digital/include/digital_constellation_receiver_cb.h123
-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
-rw-r--r--gr-digital/python/generic_mod_demod.py4
-rw-r--r--gr-digital/swig/CMakeLists.txt5
-rw-r--r--gr-digital/swig/constellation.i57
-rw-r--r--gr-digital/swig/digital_constellation.i208
-rw-r--r--gr-digital/swig/digital_constellation_decoder_cb.i38
-rw-r--r--gr-digital/swig/digital_constellation_receiver_cb.i36
-rw-r--r--gr-digital/swig/digital_swig.i14
23 files changed, 1595 insertions, 1688 deletions
diff --git a/gr-digital/include/digital/CMakeLists.txt b/gr-digital/include/digital/CMakeLists.txt
index 0f009f1fa8..0fdc0dd008 100644
--- a/gr-digital/include/digital/CMakeLists.txt
+++ b/gr-digital/include/digital/CMakeLists.txt
@@ -84,9 +84,9 @@ install(FILES
clock_recovery_mm_ff.h
cma_equalizer_cc.h
# cpmmod_bc.h
-# constellation.h
-# constellation_receiver_cb.h
-# constellation_decoder_cb.h
+ constellation.h
+ constellation_receiver_cb.h
+ constellation_decoder_cb.h
# correlate_access_code_bb.h
# correlate_access_code_tag_bb.h
# costas_loop_cc.h
diff --git a/gr-digital/include/digital/constellation.h b/gr-digital/include/digital/constellation.h
new file mode 100644
index 0000000000..49da76f70d
--- /dev/null
+++ b/gr-digital/include/digital/constellation.h
@@ -0,0 +1,417 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_DIGITAL_CONSTELLATION_H
+#define INCLUDED_DIGITAL_CONSTELLATION_H
+
+#include <digital/api.h>
+#include <digital_metric_type.h>
+#include <boost/enable_shared_from_this.hpp>
+#include <gr_complex.h>
+#include <vector>
+
+namespace gr {
+ namespace digital {
+
+ /************************************************************/
+ /* constellation */
+ /* */
+ /* Base class defining interface. */
+ /************************************************************/
+
+ class constellation;
+ typedef boost::shared_ptr<constellation> constellation_sptr;
+
+ /*!
+ * \brief An abstracted constellation object
+ * \ingroup digital
+ *
+ * The constellation objects hold the necessary information to pass
+ * around constellation information for modulators and
+ * demodulators. These objects contain the mapping between the bits
+ * and the constellation points used to represent them as well as
+ * methods for slicing the symbol space. Various implementations are
+ * possible for efficiency and ease of use.
+ *
+ * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
+ * from this class and overloaded to perform optimized slicing and
+ * constellation mappings.
+ */
+ class DIGITAL_API constellation
+ : public boost::enable_shared_from_this<constellation>
+ {
+ public:
+ constellation(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
+ constellation();
+ ~constellation();
+
+ //! Returns the constellation points for a symbol value
+ void map_to_points(unsigned int value, gr_complex *points);
+ std::vector<gr_complex> map_to_points_v(unsigned int value);
+
+ //! Returns the constellation point that matches best.
+ virtual unsigned int decision_maker(const gr_complex *sample) = 0;
+ //! Takes a vector rather than a pointer. Better for SWIG wrapping.
+ unsigned int decision_maker_v(std::vector<gr_complex> sample);
+ //! Also calculates the phase error.
+ unsigned int decision_maker_pe(const gr_complex *sample, float *phase_error);
+ //! Calculates distance.
+ //unsigned int decision_maker_e(const gr_complex *sample, float *error);
+
+ //! Calculates metrics for all points in the constellation.
+ //! For use with the viterbi algorithm.
+ virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type);
+ virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
+ virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
+
+ //! Returns the set of points in this constellation.
+ std::vector<gr_complex> points() { return d_constellation;}
+ //! Returns the vector of points in this constellation.
+ //! Raise error if dimensionality is not one.
+ std::vector<gr_complex> s_points();
+ //! Returns a vector of vectors of points.
+ std::vector<std::vector<gr_complex> > v_points();
+ //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
+ bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
+ //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
+ void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
+ //! Returns the encoding to apply before differential encoding.
+ std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;}
+ //! Returns the order of rotational symmetry.
+ unsigned int rotational_symmetry() { return d_rotational_symmetry;}
+ //! Returns the number of complex numbers in a single symbol.
+ unsigned int dimensionality() {return d_dimensionality;}
+
+ unsigned int bits_per_symbol()
+ {
+ return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
+ }
+
+ unsigned int arity()
+ {
+ return d_arity;
+ }
+
+ constellation_sptr base()
+ {
+ return shared_from_this();
+ }
+
+ protected:
+ std::vector<gr_complex> d_constellation;
+ std::vector<unsigned int> d_pre_diff_code;
+ bool d_apply_pre_diff_code;
+ unsigned int d_rotational_symmetry;
+ unsigned int d_dimensionality;
+ unsigned int d_arity;
+
+ float get_distance(unsigned int index, const gr_complex *sample);
+ unsigned int get_closest_point(const gr_complex *sample);
+ void calc_arity();
+ };
+
+ /************************************************************/
+ /* constellation_calcdist */
+ /* */
+ /************************************************************/
+
+ /*! \brief Calculate Euclidian distance for any constellation
+ * \ingroup digital
+ *
+ * Constellation which calculates the distance to each point in the
+ * constellation for decision making. Inefficient for large
+ * constellations.
+ */
+ class DIGITAL_API constellation_calcdist
+ : public constellation
+ {
+ public:
+ typedef boost::shared_ptr<constellation_calcdist> sptr;
+
+ // public constructor
+ static sptr make(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
+
+ unsigned int decision_maker(const gr_complex *sample);
+ // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
+ // void calc_euclidean_metric(gr_complex *sample, float *metric);
+ // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
+
+ private:
+ constellation_calcdist(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
+ };
+
+
+ /************************************************************/
+ /*! constellation_sector */
+ /************************************************************/
+
+ /*!
+ * \brief Sectorized digital constellation
+ * \ingroup digital
+ *
+ * Constellation space is divided into sectors. Each sector is
+ * associated with the nearest constellation point.
+ *
+ */
+ class DIGITAL_API constellation_sector : public constellation
+ {
+ public:
+
+ 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);
+
+ unsigned int decision_maker(const gr_complex *sample);
+
+ protected:
+ virtual unsigned int get_sector(const gr_complex *sample) = 0;
+ virtual unsigned int calc_sector_value(unsigned int sector) = 0;
+ void find_sector_values();
+
+ unsigned int n_sectors;
+
+ private:
+ std::vector<unsigned int> sector_values;
+ };
+
+ /************************************************************/
+ /* constellation_rect */
+ /************************************************************/
+
+ /*!
+ * \brief Rectangular digital constellation
+ * \ingroup digital
+ *
+ * Only implemented for 1-(complex)dimensional constellation.
+ *
+ * Constellation space is divided into rectangular sectors. Each
+ * sector is associated with the nearest constellation point.
+ *
+ * Works well for square QAM.
+ *
+ * Works for any generic constellation provided sectors are not
+ * too large.
+ */
+
+
+ class DIGITAL_API constellation_rect
+ : public constellation_sector
+ {
+ public:
+ typedef boost::shared_ptr<constellation_rect> sptr;
+
+ // public constructor
+ static constellation_rect::sptr 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);
+
+ protected:
+ unsigned int get_sector(const gr_complex *sample);
+
+ unsigned int calc_sector_value(unsigned int sector);
+
+ private:
+ unsigned int n_real_sectors;
+ unsigned int n_imag_sectors;
+ float d_width_real_sectors;
+ float d_width_imag_sectors;
+
+ 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_psk */
+ /************************************************************/
+
+ /*!
+ * \brief constellation_psk
+ * \ingroup digital
+ *
+ * Constellation space is divided into pie slices sectors.
+ *
+ * Each slice is associated with the nearest constellation point.
+ *
+ * Works well for PSK but nothing else.
+ *
+ * Assumes that there is a constellation point at 1.x
+ */
+ class DIGITAL_API constellation_psk : public constellation_sector
+ {
+ public:
+ typedef boost::shared_ptr<constellation_psk> sptr;
+
+ // public constructor
+ static sptr make(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+
+ ~constellation_psk();
+
+ protected:
+ unsigned int get_sector(const gr_complex *sample);
+
+ unsigned int calc_sector_value(unsigned int sector);
+
+ private:
+ constellation_psk(std::vector<gr_complex> constell,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+ };
+
+
+ /************************************************************/
+ /* constellation_bpsk */
+ /* */
+ /* Only works for BPSK. */
+ /* */
+ /************************************************************/
+
+ /*!
+ * \brief Digital constellation for BPSK
+ * \ingroup digital
+ */
+ class DIGITAL_API constellation_bpsk : public constellation
+ {
+ public:
+ typedef boost::shared_ptr<constellation_bpsk> sptr;
+
+ // public constructor
+ static sptr make();
+
+ ~constellation_bpsk();
+
+ unsigned int decision_maker(const gr_complex *sample);
+
+ private:
+ constellation_bpsk();
+ };
+
+
+ /************************************************************/
+ /* constellation_qpsk */
+ /* */
+ /* Only works for QPSK. */
+ /* */
+ /************************************************************/
+
+ /*!
+ * \brief Digital constellation for QPSK
+ * \ingroup digital
+ */
+ class DIGITAL_API constellation_qpsk : public constellation
+ {
+ public:
+ typedef boost::shared_ptr<constellation_qpsk> sptr;
+
+ // public constructor
+ static sptr make();
+
+ ~constellation_qpsk();
+
+ unsigned int decision_maker(const gr_complex *sample);
+
+ private:
+ constellation_qpsk();
+ };
+
+
+ /************************************************************/
+ /* constellation_dqpsk */
+ /* */
+ /* Works with differential encoding; slower decisions. */
+ /* */
+ /************************************************************/
+
+ /*!
+ * \brief Digital constellation for DQPSK
+ * \ingroup digital
+ */
+ class DIGITAL_API constellation_dqpsk : public constellation
+ {
+ public:
+ typedef boost::shared_ptr<constellation_dqpsk> sptr;
+
+ // public constructor
+ static sptr make();
+
+ ~constellation_dqpsk();
+
+ unsigned int decision_maker(const gr_complex *sample);
+
+ private:
+ constellation_dqpsk();
+ };
+
+
+ /************************************************************/
+ /* constellation_8psk */
+ /* */
+ /* Only works for 8PSK. */
+ /* */
+ /************************************************************/
+
+ /*!
+ * \brief Digital constellation for 8PSK
+ * \ingroup digital
+ */
+ class DIGITAL_API constellation_8psk : public constellation
+ {
+ public:
+ typedef boost::shared_ptr<constellation_8psk> sptr;
+
+ // public constructor
+ static sptr make();
+
+ ~constellation_8psk();
+
+ unsigned int decision_maker(const gr_complex *sample);
+
+ private:
+ constellation_8psk();
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CONSTELLATION_H */
diff --git a/gr-digital/include/digital/constellation_decoder_cb.h b/gr-digital/include/digital/constellation_decoder_cb.h
new file mode 100644
index 0000000000..2a98cae643
--- /dev/null
+++ b/gr-digital/include/digital/constellation_decoder_cb.h
@@ -0,0 +1,55 @@
+/* -*- 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_H
+#define INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_H
+
+#include <digital/api.h>
+#include <digital/constellation.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Constellation Decoder
+ * \ingroup coding_blk
+ * \ingroup digital
+ *
+ */
+ class DIGITAL_API constellation_decoder_cb
+ : virtual public gr_block
+ {
+ public:
+ // gr::digital::constellation_decoder_cb::sptr
+ typedef boost::shared_ptr<constellation_decoder_cb> sptr;
+
+ /*!
+ * \brief Make constellation decoder block.
+ */
+ static sptr make(constellation_sptr constellation);
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_H */
diff --git a/gr-digital/include/digital/constellation_receiver_cb.h b/gr-digital/include/digital/constellation_receiver_cb.h
new file mode 100644
index 0000000000..b1c415ea09
--- /dev/null
+++ b/gr-digital/include/digital/constellation_receiver_cb.h
@@ -0,0 +1,93 @@
+/* -*- 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_H
+#define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H
+
+#include <digital/api.h>
+#include <digital/constellation.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief This block takes care of receiving generic modulated signals
+ * through phase, frequency, and symbol synchronization.
+ * \ingroup sync_blk
+ * \ingroup demod_blk
+ * \ingroup digital
+ *
+ * This block takes care of receiving generic modulated signals
+ * through phase, frequency, and symbol synchronization. It
+ * performs carrier frequency and phase locking as well as symbol
+ * timing recovery.
+ *
+ * The phase and frequency synchronization are based on a Costas
+ * loop that finds the error of the incoming signal point compared
+ * to its nearest constellation point. The frequency and phase of
+ * the NCO are updated according to this error.
+ *
+ * The symbol synchronization is done using a modified Mueller and
+ * Muller circuit from the paper:
+ *
+ * "G. R. Danesfahani, T.G. Jeans, "Optimisation of modified
+ * Mueller and Muller algorithm," Electronics Letters, Vol. 31,
+ * no. 13, 22 June 1995, pp. 1032 - 1033."
+ *
+ * This circuit interpolates the downconverted sample (using the
+ * NCO developed by the Costas loop) every mu samples, then it
+ * finds the sampling error based on this and the past symbols and
+ * the decision made on the samples. Like the phase error
+ * detector, there are optimized decision algorithms for BPSK and
+ * QPKS, but 8PSK uses another brute force computation against all
+ * possible symbols. The modifications to the M&M used here reduce
+ * self-noise.
+ */
+ class DIGITAL_API constellation_receiver_cb
+ : virtual public gr_block
+ {
+ public:
+ // gr::digital::constellation_receiver_cb::sptr
+ typedef boost::shared_ptr<constellation_receiver_cb> sptr;
+
+ /*!
+ * \brief Constructor to synchronize incoming M-PSK symbols
+ *
+ * \param constellation constellation of points for generic modulation
+ * \param loop_bw Loop bandwidth of the Costas Loop (~ 2pi/100)
+ * \param fmin minimum normalized frequency value the loop can achieve
+ * \param fmax maximum normalized frequency value the loop can achieve
+ *
+ * The constructor chooses which phase detector and decision
+ * maker to use in the work loop based on the value of M.
+ */
+ static sptr make(constellation_sptr constellation,
+ float loop_bw, float fmin, float fmax);
+
+ virtual void phase_error_tracking(float phase_error) = 0;
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H */
diff --git a/gr-digital/include/digital_constellation.h b/gr-digital/include/digital_constellation.h
deleted file mode 100644
index 0e0c817d7a..0000000000
--- a/gr-digital/include/digital_constellation.h
+++ /dev/null
@@ -1,449 +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.
- */
-
-#ifndef INCLUDED_DIGITAL_CONSTELLATION_H
-#define INCLUDED_DIGITAL_CONSTELLATION_H
-
-#include <digital/api.h>
-#include <vector>
-#include <math.h>
-#include <gr_complex.h>
-#include <boost/enable_shared_from_this.hpp>
-#include <digital_metric_type.h>
-
-/************************************************************/
-/* digital_constellation */
-/* */
-/* Base class defining interface. */
-/************************************************************/
-
-class digital_constellation;
-typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr;
-
-/*!
- * \brief An abstracted constellation object
- * \ingroup digital
- *
- * The constellation objects hold the necessary information to pass
- * around constellation information for modulators and
- * demodulators. These objects contain the mapping between the bits
- * and the constellation points used to represent them as well as
- * methods for slicing the symbol space. Various implementations are
- * possible for efficiency and ease of use.
- *
- * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
- * from this class and overloaded to perform optimized slicing and
- * constellation mappings.
- */
-class DIGITAL_API digital_constellation : public boost::enable_shared_from_this<digital_constellation>
-{
-public:
- digital_constellation (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality);
- digital_constellation ();
-
- //! Returns the constellation points for a symbol value
- void map_to_points(unsigned int value, gr_complex *points);
- std::vector<gr_complex> map_to_points_v(unsigned int value);
-
- //! Returns the constellation point that matches best.
- virtual unsigned int decision_maker (const gr_complex *sample) = 0;
- //! Takes a vector rather than a pointer. Better for SWIG wrapping.
- unsigned int decision_maker_v (std::vector<gr_complex> sample);
- //! Also calculates the phase error.
- unsigned int decision_maker_pe (const gr_complex *sample, float *phase_error);
- //! Calculates distance.
- unsigned int decision_maker_e (const gr_complex *sample, float *error);
-
- //! Calculates metrics for all points in the constellation.
- //! For use with the viterbi algorithm.
- virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type);
- virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
- virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
-
- //! Returns the set of points in this constellation.
- std::vector<gr_complex> points() { return d_constellation;}
- //! Returns the vector of points in this constellation.
- //! Raise error if dimensionality is not one.
- std::vector<gr_complex> s_points();
- //! Returns a vector of vectors of points.
- std::vector<std::vector<gr_complex> > v_points();
- //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
- bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
- //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
- void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
- //! Returns the encoding to apply before differential encoding.
- std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;}
- //! Returns the order of rotational symmetry.
- unsigned int rotational_symmetry() { return d_rotational_symmetry;}
- //! Returns the number of complex numbers in a single symbol.
- unsigned int dimensionality() {return d_dimensionality;}
-
- unsigned int bits_per_symbol () {
- return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
- }
-
- unsigned int arity () {
- return d_arity;
- }
-
- digital_constellation_sptr base() {
- return shared_from_this();
- }
-
- protected:
-
- std::vector<gr_complex> d_constellation;
- std::vector<unsigned int> d_pre_diff_code;
- bool d_apply_pre_diff_code;
- unsigned int d_rotational_symmetry;
- unsigned int d_dimensionality;
- unsigned int d_arity;
-
- float get_distance(unsigned int index, const gr_complex *sample);
- unsigned int get_closest_point(const gr_complex *sample);
- void calc_arity ();
-};
-
-/************************************************************/
-/* digital_constellation_calcdist */
-/* */
-/************************************************************/
-
-class digital_constellation_calcdist;
-typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_calcdist_sptr;
-
-// public constructor
-DIGITAL_API 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);
-
-
-/*! \brief Calculate Euclidian distance for any constellation
- * \ingroup digital
- *
- * Constellation which calculates the distance to each point in the
- * constellation for decision making. Inefficient for large
- * constellations.
- */
-class DIGITAL_API digital_constellation_calcdist : public digital_constellation
-{
- public:
- digital_constellation_calcdist (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality);
- unsigned int decision_maker (const gr_complex *sample);
- // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
- // void calc_euclidean_metric(gr_complex *sample, float *metric);
- // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
-
- private:
- friend DIGITAL_API digital_constellation_calcdist_sptr
- digital_make_constellation_calcdist (std::vector<gr_complex> constellation);
-};
-
-
-/************************************************************/
-/*! digital_constellation_sector */
-/************************************************************/
-
-/*!
- * \brief Sectorized digital constellation
- * \ingroup digital
- *
- * Constellation space is divided into sectors. Each sector is
- * associated with the nearest constellation point.
- *
- */
-class DIGITAL_API digital_constellation_sector : public digital_constellation
-{
- public:
-
- 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);
-
- unsigned int decision_maker (const gr_complex *sample);
-
- protected:
-
- virtual unsigned int get_sector (const gr_complex *sample) = 0;
- virtual unsigned int calc_sector_value (unsigned int sector) = 0;
- void find_sector_values ();
-
- unsigned int n_sectors;
-
- private:
-
- std::vector<unsigned int> sector_values;
-
-};
-
-/************************************************************/
-/* digital_constellation_rect */
-/************************************************************/
-
-/*!
- * \brief Rectangular digital constellation
- * \ingroup digital
- *
- * Only implemented for 1-(complex)dimensional constellation.
- *
- * Constellation space is divided into rectangular sectors. Each
- * sector is associated with the nearest constellation point.
- *
- * Works well for square QAM.
- *
- * Works for any generic constellation provided sectors are not too
- * large.
- */
-
-class digital_constellation_rect;
-typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect_sptr;
-
-// public constructor
-DIGITAL_API 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);
-
-class DIGITAL_API digital_constellation_rect : public digital_constellation_sector
-{
- public:
-
- 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);
-
- protected:
-
- unsigned int get_sector (const gr_complex *sample);
-
- unsigned int calc_sector_value (unsigned int sector);
-
- private:
-
- unsigned int n_real_sectors;
- unsigned int n_imag_sectors;
- float d_width_real_sectors;
- float d_width_imag_sectors;
-
- friend DIGITAL_API 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);
-
-};
-
-
-/************************************************************/
-/* digital_constellation_psk */
-/************************************************************/
-
-class digital_constellation_psk;
-typedef boost::shared_ptr<digital_constellation_psk> digital_constellation_psk_sptr;
-
-// public constructor
-DIGITAL_API digital_constellation_psk_sptr
-digital_make_constellation_psk (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int n_sectors);
-
-/*!
- * \brief digital_constellation_psk
- * \ingroup digital
- *
- * Constellation space is divided into pie slices sectors.
- *
- * Each slice is associated with the nearest constellation point.
- *
- * Works well for PSK but nothing else.
- *
- * Assumes that there is a constellation point at 1.x
- */
-class DIGITAL_API digital_constellation_psk : public digital_constellation_sector
-{
- public:
-
- digital_constellation_psk (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int n_sectors);
-
- protected:
-
- unsigned int get_sector (const gr_complex *sample);
-
- unsigned int calc_sector_value (unsigned int sector);
-
- private:
-
- friend DIGITAL_API digital_constellation_psk_sptr
- digital_make_constellation_psk (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int n_sectors);
-
-};
-
-
-/************************************************************/
-/* digital_constellation_bpsk */
-/* */
-/* Only works for BPSK. */
-/* */
-/************************************************************/
-
-class digital_constellation_bpsk;
-typedef boost::shared_ptr<digital_constellation_bpsk> digital_constellation_bpsk_sptr;
-
-// public constructor
-DIGITAL_API digital_constellation_bpsk_sptr
-digital_make_constellation_bpsk ();
-
-/*!
- * \brief Digital constellation for BPSK
- * \ingroup digital
- */
-class DIGITAL_API digital_constellation_bpsk : public digital_constellation
-{
- public:
-
- digital_constellation_bpsk ();
- unsigned int decision_maker (const gr_complex *sample);
-
- friend DIGITAL_API digital_constellation_bpsk_sptr
- digital_make_constellation_bpsk ();
-
-};
-
-
-/************************************************************/
-/* digital_constellation_qpsk */
-/* */
-/* Only works for QPSK. */
-/* */
-/************************************************************/
-
-class digital_constellation_qpsk;
-typedef boost::shared_ptr<digital_constellation_qpsk> digital_constellation_qpsk_sptr;
-
-// public constructor
-DIGITAL_API digital_constellation_qpsk_sptr
-digital_make_constellation_qpsk ();
-
-/*!
- * \brief Digital constellation for QPSK
- * \ingroup digital
- */
-class DIGITAL_API digital_constellation_qpsk : public digital_constellation
-{
- public:
-
- digital_constellation_qpsk ();
- unsigned int decision_maker (const gr_complex *sample);
-
- friend DIGITAL_API digital_constellation_qpsk_sptr
- digital_make_constellation_qpsk ();
-
-};
-
-
-/************************************************************/
-/* digital_constellation_dqpsk */
-/* */
-/* Works with differential encoding; slower decisions. */
-/* */
-/************************************************************/
-
-class digital_constellation_dqpsk;
-typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
-
-// public constructor
-DIGITAL_API digital_constellation_dqpsk_sptr
-digital_make_constellation_dqpsk ();
-
-/*!
- * \brief Digital constellation for DQPSK
- * \ingroup digital
- */
-class DIGITAL_API digital_constellation_dqpsk : public digital_constellation
-{
- public:
-
- digital_constellation_dqpsk ();
- unsigned int decision_maker (const gr_complex *sample);
-
- friend DIGITAL_API digital_constellation_dqpsk_sptr
- digital_make_constellation_dqpsk ();
-
-};
-
-
-/************************************************************/
-/* digital_constellation_8psk */
-/* */
-/* Only works for 8PSK. */
-/* */
-/************************************************************/
-
-class digital_constellation_8psk;
-typedef boost::shared_ptr<digital_constellation_8psk> digital_constellation_8psk_sptr;
-
-// public constructor
-DIGITAL_API digital_constellation_8psk_sptr
-digital_make_constellation_8psk ();
-
-/*!
- * \brief Digital constellation for 8PSK
- * \ingroup digital
- */
-class DIGITAL_API digital_constellation_8psk : public digital_constellation
-{
- public:
-
- digital_constellation_8psk ();
- unsigned int decision_maker (const gr_complex *sample);
-
- friend DIGITAL_API digital_constellation_8psk_sptr
- digital_make_constellation_8psk ();
-
-};
-
-#endif
diff --git a/gr-digital/include/digital_constellation_decoder_cb.h b/gr-digital/include/digital_constellation_decoder_cb.h
deleted file mode 100644
index cce3a564f3..0000000000
--- a/gr-digital/include/digital_constellation_decoder_cb.h
+++ /dev/null
@@ -1,66 +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.
- */
-
-#ifndef INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_H
-#define INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_H
-
-#include <digital_api.h>
-#include <gr_block.h>
-#include <digital_constellation.h>
-#include <vector>
-
-class digital_constellation_decoder_cb;
-typedef boost::shared_ptr<digital_constellation_decoder_cb>digital_constellation_decoder_cb_sptr;
-
-DIGITAL_API digital_constellation_decoder_cb_sptr
-digital_make_constellation_decoder_cb (digital_constellation_sptr constellation);
-
-/*!
- * \brief Constellation Decoder
- * \ingroup coding_blk
- * \ingroup digital
- *
- */
-class DIGITAL_API digital_constellation_decoder_cb : public gr_block
-{
-
- private:
- digital_constellation_sptr d_constellation;
- unsigned int d_dim;
-
- friend DIGITAL_API digital_constellation_decoder_cb_sptr
- digital_make_constellation_decoder_cb (digital_constellation_sptr constellation);
-
- digital_constellation_decoder_cb (digital_constellation_sptr constellation);
-
- public:
-
- 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);
-};
-
-#endif
diff --git a/gr-digital/include/digital_constellation_receiver_cb.h b/gr-digital/include/digital_constellation_receiver_cb.h
deleted file mode 100644
index 3a14bb5dee..0000000000
--- a/gr-digital/include/digital_constellation_receiver_cb.h
+++ /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.
- */
-
-#ifndef INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H
-#define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H
-
-#include <digital_api.h>
-#include <gr_block.h>
-#include <digital_constellation.h>
-#include <gruel/attributes.h>
-#include <gri_control_loop.h>
-#include <gr_complex.h>
-#include <math.h>
-#include <fstream>
-
-class digital_constellation_receiver_cb;
-typedef boost::shared_ptr<digital_constellation_receiver_cb> digital_constellation_receiver_cb_sptr;
-
-// public constructor
-DIGITAL_API digital_constellation_receiver_cb_sptr
-digital_make_constellation_receiver_cb (digital_constellation_sptr constellation,
- float loop_bw, float fmin, float fmax);
-
-/*!
- * \brief This block takes care of receiving generic modulated signals
- * through phase, frequency, and symbol synchronization.
- * \ingroup sync_blk
- * \ingroup demod_blk
- * \ingroup digital
- *
- * This block takes care of receiving generic modulated signals
- * through phase, frequency, and symbol synchronization. It performs
- * carrier frequency and phase locking as well as symbol timing
- * recovery.
- *
- * The phase and frequency synchronization are based on a Costas loop
- * that finds the error of the incoming signal point compared to its
- * nearest constellation point. The frequency and phase of the NCO are
- * updated according to this error.
- *
- * The symbol synchronization is done using a modified Mueller and
- * Muller circuit from the paper:
- *
- * "G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller
- * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22
- * June 1995, pp. 1032 - 1033."
- *
- * This circuit interpolates the downconverted sample (using the NCO
- * developed by the Costas loop) every mu samples, then it finds the
- * sampling error based on this and the past symbols and the decision
- * made on the samples. Like the phase error detector, there are
- * optimized decision algorithms for BPSK and QPKS, but 8PSK uses
- * another brute force computation against all possible symbols. The
- * modifications to the M&M used here reduce self-noise.
- *
- */
-
-class DIGITAL_API digital_constellation_receiver_cb : public gr_block, public gri_control_loop
-{
-public:
- 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:
-
- /*!
- * \brief Constructor to synchronize incoming M-PSK symbols
- *
- * \param constellation constellation of points for generic modulation
- * \param loop_bw Loop bandwidth of the Costas Loop (~ 2pi/100)
- * \param fmin minimum normalized frequency value the loop can achieve
- * \param fmax maximum normalized frequency value the loop can achieve
- *
- * The constructor also chooses which phase detector and decision maker to use in the
- * work loop based on the value of M.
- */
- digital_constellation_receiver_cb (digital_constellation_sptr constellation,
- float loop_bw, float fmin, float fmax);
-
- void phase_error_tracking(float phase_error);
-
-private:
- unsigned int d_M;
-
- digital_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;
-
- friend DIGITAL_API digital_constellation_receiver_cb_sptr
- digital_make_constellation_receiver_cb (digital_constellation_sptr constell,
- float loop_bw, float fmin, float fmax);
-};
-
-#endif
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;
-}
-
diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py
index 8d350e8454..3d4a6bfbc2 100644
--- a/gr-digital/python/generic_mod_demod.py
+++ b/gr-digital/python/generic_mod_demod.py
@@ -113,7 +113,7 @@ class generic_mod(gr.hier_block2):
gr.io_signature(1, 1, gr.sizeof_char), # Input signature
gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
- self._constellation = constellation.base()
+ self._constellation = constellation
self._samples_per_symbol = samples_per_symbol
self._excess_bw = excess_bw
self._differential = differential
@@ -258,7 +258,7 @@ class generic_demod(gr.hier_block2):
gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
- self._constellation = constellation.base()
+ self._constellation = constellation
self._samples_per_symbol = samples_per_symbol
self._excess_bw = excess_bw
self._phase_bw = phase_bw
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index fab11ab56a..299fd1c1d9 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -29,13 +29,10 @@ set(GR_SWIG_INCLUDE_DIRS
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
)
-# Setup swig docs to depend on includes and pull in from build directory
-set(GR_SWIG_LIBRARIES gnuradio-digital gnuradio-filter)
-set(GR_SWIG_TARGET_DEPS digital_generated_includes core_swig)
set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i)
set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
-set(GR_SWIG_LIBRARIES gnuradio-digital)
+set(GR_SWIG_LIBRARIES gnuradio-digital gnuradio-filter)
GR_SWIG_MAKE(digital_swig digital_swig.i)
diff --git a/gr-digital/swig/constellation.i b/gr-digital/swig/constellation.i
new file mode 100644
index 0000000000..8039c4c8f1
--- /dev/null
+++ b/gr-digital/swig/constellation.i
@@ -0,0 +1,57 @@
+/* -*- 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.
+ */
+
+%template(constellation_calcdist_sptr) boost::shared_ptr<gr::digital::constellation_calcdist>;
+%pythoncode %{
+constellation_calcdist_sptr.__repr__ = lambda self: "<constellation calcdist (m=%d)>" % (len(self.points()))
+constellation_calcdist = constellation_calcdist.make;
+%}
+
+%template(constellation_psk_sptr) boost::shared_ptr<gr::digital::constellation_psk>;
+%pythoncode %{
+constellation_psk_sptr.__repr__ = lambda self: "<constellation PSK (m=%d)>" % (len(self.points()))
+constellation_psk = constellation_psk.make;
+%}
+
+%template(constellation_bpsk_sptr) boost::shared_ptr<gr::digital::constellation_bpsk>;
+%pythoncode %{
+constellation_bpsk_sptr.__repr__ = lambda self: "<constellation BPSK>"
+constellation_bpsk = constellation_bpsk.make;
+%}
+
+%template(constellation_qpsk_sptr) boost::shared_ptr<gr::digital::constellation_qpsk>;
+%pythoncode %{
+constellation_qpsk_sptr.__repr__ = lambda self: "<constellation QPSK>"
+constellation_qpsk = constellation_qpsk.make;
+%}
+
+%template(constellation_dqpsk_sptr) boost::shared_ptr<gr::digital::constellation_dqpsk>;
+%pythoncode %{
+constellation_dqpsk_sptr.__repr__ = lambda self: "<constellation DQPSK>"
+constellation_dqpsk = constellation_dqpsk.make;
+%}
+
+%template(constellation_8psk_sptr) boost::shared_ptr<gr::digital::constellation_8psk>;
+%pythoncode %{
+constellation_8psk_sptr.__repr__ = lambda self: "<constellation 8PSK>"
+constellation_8psk = constellation_8psk.make;
+%}
diff --git a/gr-digital/swig/digital_constellation.i b/gr-digital/swig/digital_constellation.i
deleted file mode 100644
index 248f900149..0000000000
--- a/gr-digital/swig/digital_constellation.i
+++ /dev/null
@@ -1,208 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2010,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.
- */
-
-%template(gr_complex_vector) std::vector<gr_complex>;
-%template(unsigned_int_vector) std::vector<unsigned int>;
-
-// Make sure metric types get SWIGed.
-%include "digital_metric_type.h"
-
-class digital_constellation;
-typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr;
-%template(digital_constellation_sptr) boost::shared_ptr<digital_constellation>;
-
-class digital_constellation
-{
-public:
- digital_constellation (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality);
- std::vector<gr_complex> points();
- std::vector<gr_complex> s_points();
- std::vector<std::vector<gr_complex> > v_points();
- virtual unsigned int decision_maker (gr_complex *sample) = 0;
- unsigned int decision_maker_v (std::vector<gr_complex> sample);
- // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
- // void calc_euclidean_metric(gr_complex *sample, float *metric);
- // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
- std::vector<gr_complex> map_to_points_v(unsigned int value);
- unsigned int bits_per_symbol ();
- unsigned int arity ();
- digital_constellation_sptr base ();
- bool apply_pre_diff_code();
- void set_pre_diff_code(bool a);
- std::vector<unsigned int> pre_diff_code();
- unsigned int rotational_symmetry();
- unsigned int dimensionality();
-};
-
-class digital_constellation_calcdist;
-typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_calcdist_sptr;
-%template(digital_constellation_calcdist_sptr) boost::shared_ptr<digital_constellation_calcdist>;
-%rename(constellation_calcdist) digital_make_constellation_calcdist;
-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);
-%ignore digital_constellation_calcdist;
-
-class digital_constellation_calcdist: public digital_constellation
-{
- public:
- digital_constellation_calcdist (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality);
- unsigned int decision_maker (const gr_complex *sample);
-};
-
-class digital_constellation_sector: public digital_constellation
-{
-};
-
-class digital_constellation_rect;
-typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect_sptr;
-%template(digital_constellation_rect_sptr) boost::shared_ptr<digital_constellation_rect>;
-%rename(constellation_rect) digital_make_constellation_rect;
-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);
-%ignore digital_constellation_rect;
-
-class digital_constellation_rect : public digital_constellation_sector
-{
-public:
- 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);
-};
-
-class digital_constellation_psk;
-typedef boost::shared_ptr<digital_constellation_psk> digital_constellation_psk_sptr;
-%template(digital_constellation_psk_sptr) boost::shared_ptr<digital_constellation_psk>;
-%rename(constellation_psk) digital_make_constellation_psk;
-digital_constellation_psk_sptr digital_make_constellation_psk(std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int n_sectors);
-%ignore digital_constellation_psk;
-
-class digital_constellation_psk : public digital_constellation_sector
-{
-public:
- digital_constellation_psk (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int n_sectors);
-};
-
-/*
- BPSK Constellation
-*/
-
-class digital_constellation_bpsk;
-typedef boost::shared_ptr<digital_constellation_bpsk> digital_constellation_bpsk_sptr;
-%template(digital_constellation_bpsk_sptr) boost::shared_ptr<digital_constellation_bpsk>;
-%rename(constellation_bpsk) digital_make_constellation_bpsk;
-digital_constellation_bpsk_sptr digital_make_constellation_bpsk();
-%ignore digital_constellation_bpsk;
-
-class digital_constellation_bpsk : public digital_constellation
-{
-public:
- digital_constellation_bpsk ();
-};
-
-/*
- QPSK Constellation
-*/
-
-class digital_constellation_qpsk;
-typedef boost::shared_ptr<digital_constellation_qpsk> digital_constellation_qpsk_sptr;
-%template(digital_constellation_qpsk_sptr) boost::shared_ptr<digital_constellation_qpsk>;
-%rename(constellation_qpsk) digital_make_constellation_qpsk;
-digital_constellation_qpsk_sptr digital_make_constellation_qpsk();
-%ignore digital_constellation_qpsk;
-
-class digital_constellation_qpsk : public digital_constellation
-{
-public:
- digital_constellation_qpsk ();
-};
-
-/*
- DQPSK Constellation
-*/
-
-class digital_constellation_dqpsk;
-typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
-%template(digital_constellation_dqpsk_sptr) boost::shared_ptr<digital_constellation_dqpsk>;
-%rename(constellation_dqpsk) digital_make_constellation_dqpsk;
-digital_constellation_dqpsk_sptr digital_make_constellation_dqpsk();
-%ignore digital_constellation_dqpsk;
-
-class digital_constellation_dqpsk : public digital_constellation
-{
-public:
- digital_constellation_dqpsk ();
-};
-
-
-/*
- 8PSK Constellation
-*/
-
-class digital_constellation_8psk;
-typedef boost::shared_ptr<digital_constellation_8psk> digital_constellation_8psk_sptr;
-%template(digital_constellation_8psk_sptr) boost::shared_ptr<digital_constellation_8psk>;
-%rename(constellation_8psk) digital_make_constellation_8psk;
-digital_constellation_8psk_sptr digital_make_constellation_8psk();
-%ignore digital_constellation_8psk;
-
-class digital_constellation_8psk : public digital_constellation
-{
-public:
- digital_constellation_8psk ();
-};
-
-#if SWIGPYTHON
-/*
- We want print(constellation) in python to produce nice useful output so
- we include code at the end of the generated python file that overrides
- the SWIG-generated __repr__ method.
- */
-%pythoncode %{
-
-digital_constellation_calcdist_sptr.__repr__ = lambda self: '<constellation calcdist (m=%s)>' % str(len(self.points()))
-digital_constellation_rect_sptr.__repr__ = lambda self: '<constellation rect (m=%s)>' % str(len(self.points()))
-digital_constellation_psk_sptr.__repr__ = lambda self: '<constellation psk (m=%s)>' % str(len(self.points()))
-digital_constellation_bpsk_sptr.__repr__ = lambda self: '<constellation bpsk>'
-digital_constellation_qpsk_sptr.__repr__ = lambda self: '<constellation qpsk>'
-digital_constellation_dqpsk_sptr.__repr__ = lambda self: '<constellation dqpsk>'
-digital_constellation_8psk_sptr.__repr__ = lambda self: '<constellation 8psk>'
-
-%}
-#endif
diff --git a/gr-digital/swig/digital_constellation_decoder_cb.i b/gr-digital/swig/digital_constellation_decoder_cb.i
deleted file mode 100644
index 547f57ee6a..0000000000
--- a/gr-digital/swig/digital_constellation_decoder_cb.i
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006, 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.
- */
-
-GR_SWIG_BLOCK_MAGIC(digital,constellation_decoder_cb)
-
-digital_constellation_decoder_cb_sptr
-digital_make_constellation_decoder_cb (digital_constellation_sptr constellation);
-
-class digital_constellation_decoder_cb : public gr_sync_block
-{
- private:
- digital_constellation_decoder_cb (digital_constellation_sptr constellation);
-
- friend digital_constellation_decoder_cb_sptr
- digital_make_constellation_decoder_cb (digital_constellation_sptr constellation);
-
- public:
- ~digital_constellation_decoder_cb();
-};
diff --git a/gr-digital/swig/digital_constellation_receiver_cb.i b/gr-digital/swig/digital_constellation_receiver_cb.i
deleted file mode 100644
index 9c4ba645e0..0000000000
--- a/gr-digital/swig/digital_constellation_receiver_cb.i
+++ /dev/null
@@ -1,36 +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.
- */
-
-GR_SWIG_BLOCK_MAGIC(digital,constellation_receiver_cb);
-
-%include "digital_constellation.i"
-
-digital_constellation_receiver_cb_sptr
-digital_make_constellation_receiver_cb (digital_constellation_sptr constellation,
- float loop_bw, float fmin, float fmax);
-
-class digital_constellation_receiver_cb : public gr_block, public gri_control_loop
-{
- private:
- digital_constellation_receiver_cb (digital_contellation_sptr constellation,
- float loop_bw, float fmin, float fmax);
-};
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index c648db68f2..f5fe83ff82 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -37,12 +37,18 @@
//%include <gri_control_loop.i>
+// Used in the constellation objects
+%template(unsigned_int_vector) std::vector<unsigned int>;
+
%{
#include "digital/additive_scrambler_bb.h"
#include "digital/binary_slicer_fb.h"
#include "digital/clock_recovery_mm_cc.h"
#include "digital/clock_recovery_mm_ff.h"
#include "digital/cma_equalizer_cc.h"
+#include "digital/constellation.h"
+#include "digital/constellation_receiver_cb.h"
+#include "digital/constellation_decoder_cb.h"
%}
%include "digital/additive_scrambler_bb.h"
@@ -50,9 +56,17 @@
%include "digital/clock_recovery_mm_cc.h"
%include "digital/clock_recovery_mm_ff.h"
%include "digital/cma_equalizer_cc.h"
+%include "digital/constellation.h"
+%include "digital/constellation_receiver_cb.h"
+%include "digital/constellation_decoder_cb.h"
GR_SWIG_BLOCK_MAGIC2(digital, additive_scrambler_bb);
GR_SWIG_BLOCK_MAGIC2(digital, binary_slicer_fb);
GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_cc);
GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_ff);
GR_SWIG_BLOCK_MAGIC2(digital, cma_equalizer_cc);
+GR_SWIG_BLOCK_MAGIC2(digital, constellation_receiver_cb);
+GR_SWIG_BLOCK_MAGIC2(digital, constellation_decoder_cb);
+
+// Properly package up constellation objects
+%include "constellation.i"