/* -*- 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 #include #include #include #include #include /************************************************************/ /* digital_constellation */ /* */ /* Base class defining interface. */ /************************************************************/ class digital_constellation; typedef boost::shared_ptr 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 { public: digital_constellation (std::vector constellation, std::vector 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 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 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 points() { return d_constellation;} //! Returns the vector of points in this constellation. //! Raise error if dimensionality is not one. std::vector s_points(); //! Returns a vector of vectors of points. std::vector > 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 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 d_constellation; std::vector d_pre_diff_code; bool d_apply_pre_diff_code; unsigned int d_rotational_symmetry; unsigned int d_dimensionality; unsigned int d_arity; // The orignal constellation points were multiplied by this factor to get a // constellation with average magnitude 1. float d_scalefactor; 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_sptr; // public constructor DIGITAL_API digital_constellation_calcdist_sptr digital_make_constellation_calcdist (std::vector constellation, std::vector 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 constellation, std::vector 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 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 constellation, std::vector 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 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_sptr; // public constructor DIGITAL_API digital_constellation_rect_sptr digital_make_constellation_rect (std::vector constellation, std::vector 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 constellation, std::vector 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 constellation, std::vector 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_sptr; // public constructor DIGITAL_API digital_constellation_psk_sptr digital_make_constellation_psk (std::vector constellation, std::vector 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 constellation, std::vector 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 constellation, std::vector 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_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_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_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_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