diff options
author | Tom Rondeau <trondeau@vt.edu> | 2012-08-11 11:04:03 -0400 |
---|---|---|
committer | Tom Rondeau <trondeau@vt.edu> | 2012-08-11 11:04:03 -0400 |
commit | a6e56683cf74054fad6774138bea9f844c76be09 (patch) | |
tree | 1749031397ac4ebdc117b05a753c82976e8aca62 | |
parent | af0a5780201c71c8f2d682cdab2274942e5771d5 (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.
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(§or_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(§or_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(§or_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(§or_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" |