GNU Radio 3.7.1 C++ API
constellation.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2010-2012 Free Software Foundation, Inc.
00004  *
00005  * This file is part of GNU Radio
00006  *
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  *
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #ifndef INCLUDED_DIGITAL_CONSTELLATION_H
00024 #define INCLUDED_DIGITAL_CONSTELLATION_H
00025 
00026 #include <gnuradio/digital/api.h>
00027 #include <gnuradio/digital/metric_type.h>
00028 #include <boost/enable_shared_from_this.hpp>
00029 #include <gnuradio/gr_complex.h>
00030 #include <vector>
00031 
00032 namespace gr {
00033   namespace digital {
00034 
00035     /************************************************************/
00036     /* constellation                                            */
00037     /*                                                          */
00038     /* Base class defining interface.                           */
00039     /************************************************************/
00040     
00041     class constellation;
00042     typedef boost::shared_ptr<constellation> constellation_sptr;
00043 
00044     /*!
00045      * \brief An abstracted constellation object
00046      * \ingroup symbol_coding_blk
00047      *
00048      * \details
00049      * The constellation objects hold the necessary information to pass
00050      * around constellation information for modulators and
00051      * demodulators. These objects contain the mapping between the bits
00052      * and the constellation points used to represent them as well as
00053      * methods for slicing the symbol space. Various implementations are
00054      * possible for efficiency and ease of use.
00055      *
00056      * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
00057      * from this class and overloaded to perform optimized slicing and
00058      * constellation mappings.
00059      */
00060     class DIGITAL_API constellation
00061       : public boost::enable_shared_from_this<constellation>
00062     {
00063     public:
00064       constellation(std::vector<gr_complex> constell,
00065                     std::vector<int> pre_diff_code,
00066                     unsigned int rotational_symmetry,
00067                     unsigned int dimensionality);
00068       constellation();
00069       virtual ~constellation();
00070 
00071       //! Returns the constellation points for a symbol value
00072       void map_to_points(unsigned int value, gr_complex *points);
00073       std::vector<gr_complex> map_to_points_v(unsigned int value);
00074 
00075       //! Returns the constellation point that matches best.
00076       virtual unsigned int decision_maker(const gr_complex *sample) = 0;
00077       //! Takes a vector rather than a pointer.  Better for SWIG wrapping.
00078       unsigned int decision_maker_v(std::vector<gr_complex> sample);
00079       //! Also calculates the phase error.
00080       unsigned int decision_maker_pe(const gr_complex *sample, float *phase_error);
00081       //! Calculates distance.
00082       //unsigned int decision_maker_e(const gr_complex *sample, float *error);
00083   
00084       //! Calculates metrics for all points in the constellation.
00085       //! For use with the viterbi algorithm.
00086       virtual void calc_metric(const gr_complex *sample, float *metric, gr::digital::trellis_metric_type_t type);
00087       virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
00088       virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
00089   
00090       //! Returns the set of points in this constellation.
00091       std::vector<gr_complex> points() { return d_constellation;}
00092       //! Returns the vector of points in this constellation.
00093       //! Raise error if dimensionality is not one.
00094       std::vector<gr_complex> s_points();
00095       //! Returns a vector of vectors of points.
00096       std::vector<std::vector<gr_complex> > v_points();
00097       //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
00098       bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
00099       //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
00100       void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
00101       //! Returns the encoding to apply before differential encoding.
00102       std::vector<int> pre_diff_code() { return d_pre_diff_code;}
00103       //! Returns the order of rotational symmetry.
00104       unsigned int rotational_symmetry() { return d_rotational_symmetry;}
00105       //! Returns the number of complex numbers in a single symbol.
00106       unsigned int dimensionality() {return d_dimensionality;}
00107 
00108       unsigned int bits_per_symbol()
00109       {
00110         return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
00111       }
00112   
00113       unsigned int arity()
00114       {
00115         return d_arity;
00116       }
00117 
00118       constellation_sptr base()
00119       {
00120         return shared_from_this();
00121       }  
00122 
00123     protected:
00124       std::vector<gr_complex> d_constellation;
00125       std::vector<int> d_pre_diff_code; 
00126       bool d_apply_pre_diff_code;
00127       unsigned int d_rotational_symmetry;
00128       unsigned int d_dimensionality;
00129       unsigned int d_arity;
00130       //! The factor by which the user given constellation points were
00131       //! scaled by to achieve an average amplitude of 1.
00132       float d_scalefactor;
00133 
00134       float get_distance(unsigned int index, const gr_complex *sample);
00135       unsigned int get_closest_point(const gr_complex *sample);
00136       void calc_arity();
00137     };
00138 
00139     /************************************************************/
00140     /* constellation_calcdist                                   */
00141     /*                                                          */
00142     /************************************************************/
00143 
00144     /*! \brief Calculate Euclidian distance for any constellation
00145      *  \ingroup digital
00146      *
00147      * Constellation which calculates the distance to each point in the
00148      * constellation for decision making. Inefficient for large
00149      * constellations.
00150      */
00151     class DIGITAL_API constellation_calcdist
00152       : public constellation
00153     {
00154     public:
00155       typedef boost::shared_ptr<constellation_calcdist> sptr;
00156 
00157       /*!
00158        * Make a general constellation object that calculates the Euclidean distance for hard decisions.
00159        *
00160        * \param constell List of constellation points (order of list matches pre_diff_code)
00161        * \param pre_diff_code List of alphabet symbols (before applying any differential 
00162        *                      coding) (order of list matches constell)
00163        * \param rotational_symmetry Number of rotations around unit circle that have the same representation.
00164        * \param dimensionality Number of dimensions to the constellation.
00165        */
00166       static sptr make(std::vector<gr_complex> constell,
00167                        std::vector<int> pre_diff_code,
00168                        unsigned int rotational_symmetry,
00169                        unsigned int dimensionality);
00170 
00171       unsigned int decision_maker(const gr_complex *sample);
00172       // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
00173       // void calc_euclidean_metric(gr_complex *sample, float *metric);
00174       // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
00175 
00176     protected:
00177       constellation_calcdist(std::vector<gr_complex> constell,
00178                              std::vector<int> pre_diff_code,
00179                              unsigned int rotational_symmetry,
00180                              unsigned int dimensionality);
00181     };
00182 
00183 
00184     /************************************************************/
00185     /*! constellation_sector                                    */
00186     /************************************************************/
00187 
00188     /*!
00189      * \brief Sectorized digital constellation
00190      * \ingroup digital
00191      *
00192      * Constellation space is divided into sectors. Each sector is
00193      * associated with the nearest constellation point.
00194      *
00195      */
00196     class DIGITAL_API constellation_sector : public constellation
00197     {
00198     public:
00199 
00200       constellation_sector(std::vector<gr_complex> constell,
00201                            std::vector<int> pre_diff_code,
00202                            unsigned int rotational_symmetry,
00203                            unsigned int dimensionality,
00204                            unsigned int n_sectors);
00205 
00206       ~constellation_sector();
00207 
00208       unsigned int decision_maker(const gr_complex *sample);
00209 
00210     protected:
00211       virtual unsigned int get_sector(const gr_complex *sample) = 0;
00212       virtual unsigned int calc_sector_value(unsigned int sector) = 0;
00213       void find_sector_values();
00214 
00215       unsigned int n_sectors;
00216 
00217     private:
00218       std::vector<int> sector_values;
00219     };
00220 
00221     /************************************************************/
00222     /* constellation_rect                                       */
00223     /************************************************************/
00224 
00225     /*!
00226      * \brief Rectangular digital constellation
00227      * \ingroup digital
00228      *
00229      * Only implemented for 1-(complex)dimensional constellation.
00230      *
00231      * Constellation space is divided into rectangular sectors. Each
00232      * sector is associated with the nearest constellation point.
00233      *
00234      * Works well for square QAM.
00235      *
00236      * Works for any generic constellation provided sectors are not
00237      * too large.
00238      */
00239 
00240 
00241     class DIGITAL_API constellation_rect
00242       : public constellation_sector
00243     {
00244     public:
00245       typedef boost::shared_ptr<constellation_rect> sptr;
00246 
00247       /*!
00248        * Make a rectangular constellation object.
00249        *
00250        * \param constell List of constellation points (order of list matches pre_diff_code)
00251        * \param pre_diff_code List of alphabet symbols (before applying any differential 
00252        *                      coding) (order of list matches constell)
00253        * \param rotational_symmetry Number of rotations around unit circle that have the same representation.
00254        * \param real_sectors Number of sectors the real axis is split in to.
00255        * \param imag_sectors Number of sectors the imag axis is split in to.
00256        * \param width_real_sectors width of each real sector to calculate decision boundaries.
00257        * \param width_imag_sectors width of each imag sector to calculate decision boundaries. 
00258        */
00259       static constellation_rect::sptr make(std::vector<gr_complex> constell,
00260                                            std::vector<int> pre_diff_code,
00261                                            unsigned int rotational_symmetry,
00262                                            unsigned int real_sectors,
00263                                            unsigned int imag_sectors,
00264                                            float width_real_sectors,
00265                                            float width_imag_sectors);
00266       ~constellation_rect();
00267 
00268     protected:
00269 
00270       constellation_rect(std::vector<gr_complex> constell,
00271                          std::vector<int> pre_diff_code,
00272                          unsigned int rotational_symmetry,
00273                          unsigned int real_sectors,
00274                          unsigned int imag_sectors,
00275                          float width_real_sectors,
00276                          float width_imag_sectors);
00277 
00278       unsigned int get_sector(const gr_complex *sample);
00279   
00280       unsigned int calc_sector_value(unsigned int sector);
00281 
00282     private:
00283       unsigned int n_real_sectors;
00284       unsigned int n_imag_sectors;
00285       float d_width_real_sectors;
00286       float d_width_imag_sectors;
00287     };
00288 
00289 
00290     /************************************************************/
00291     /* constellation_expl_rect                                  */
00292     /************************************************************/
00293 
00294     /*!
00295      * \brief Rectangular digital constellation
00296      * \ingroup digital
00297      *
00298      * Only implemented for 1-(complex)dimensional constellation.
00299      *
00300      * Constellation space is divided into rectangular sectors. Each
00301      * sector is associated with the nearest constellation point.
00302      *
00303      * This class is different from constellation_rect in that the
00304      * mapping from sector to constellation point is explicitly passed
00305      * into the constructor as sector_values.  Usually we do not need
00306      * this, since we want each sector to be automatically mapped to
00307      * the closest constellation point, however sometimes it's nice to
00308      * have the flexibility.
00309      */
00310     class DIGITAL_API constellation_expl_rect 
00311       : public constellation_rect
00312     {
00313     public:
00314       typedef boost::shared_ptr<constellation_expl_rect> sptr;
00315 
00316       static sptr make(std::vector<gr_complex> constellation,
00317                        std::vector<int> pre_diff_code,
00318                        unsigned int rotational_symmetry,
00319                        unsigned int real_sectors,
00320                        unsigned int imag_sectors,
00321                        float width_real_sectors,
00322                        float width_imag_sectors,
00323                        std::vector<unsigned int> sector_values);
00324       ~constellation_expl_rect();
00325 
00326     protected:
00327       constellation_expl_rect(std::vector<gr_complex> constellation,
00328                               std::vector<int> pre_diff_code,
00329                               unsigned int rotational_symmetry,
00330                               unsigned int real_sectors,
00331                               unsigned int imag_sectors,
00332                               float width_real_sectors,
00333                               float width_imag_sectors,
00334                               std::vector<unsigned int> sector_values);
00335 
00336       unsigned int calc_sector_value (unsigned int sector) {
00337         return d_sector_values[sector];
00338       }
00339 
00340     private:
00341       std::vector<unsigned int> d_sector_values;
00342     };
00343 
00344     /************************************************************/
00345     /* constellation_psk                                        */
00346     /************************************************************/
00347 
00348     /*! 
00349      * \brief constellation_psk
00350      * \ingroup digital
00351      *
00352      * Constellation space is divided into pie slices sectors.
00353      *
00354      * Each slice is associated with the nearest constellation point. 
00355      *
00356      * Works well for PSK but nothing else.  
00357      *
00358      * Assumes that there is a constellation point at 1.x 
00359      */
00360     class DIGITAL_API constellation_psk : public constellation_sector
00361     {
00362     public:
00363       typedef boost::shared_ptr<constellation_psk> sptr;
00364 
00365       // public constructor
00366       static sptr make(std::vector<gr_complex> constell,
00367                        std::vector<int> pre_diff_code,
00368                        unsigned int n_sectors);
00369 
00370       ~constellation_psk();
00371 
00372     protected:
00373       unsigned int get_sector(const gr_complex *sample);
00374   
00375       unsigned int calc_sector_value(unsigned int sector);
00376 
00377       constellation_psk(std::vector<gr_complex> constell,
00378                         std::vector<int> pre_diff_code,
00379                         unsigned int n_sectors);
00380     };
00381 
00382 
00383     /************************************************************/
00384     /* constellation_bpsk                                       */
00385     /*                                                          */
00386     /* Only works for BPSK.                                     */
00387     /*                                                          */
00388     /************************************************************/
00389 
00390     /*! 
00391      * \brief Digital constellation for BPSK 
00392      * \ingroup digital
00393      */
00394     class DIGITAL_API constellation_bpsk : public constellation
00395     {
00396     public:
00397       typedef boost::shared_ptr<constellation_bpsk> sptr;
00398 
00399       // public constructor
00400       static sptr make();
00401 
00402       ~constellation_bpsk();
00403 
00404       unsigned int decision_maker(const gr_complex *sample);
00405 
00406     protected:
00407       constellation_bpsk();
00408     };
00409 
00410 
00411     /************************************************************/
00412     /* constellation_qpsk                                       */
00413     /*                                                          */
00414     /* Only works for QPSK.                                     */
00415     /*                                                          */
00416     /************************************************************/
00417 
00418     /*! 
00419      * \brief Digital constellation for QPSK
00420      * \ingroup digital
00421      */
00422     class DIGITAL_API constellation_qpsk : public constellation
00423     {
00424     public:
00425       typedef boost::shared_ptr<constellation_qpsk> sptr;
00426 
00427       // public constructor
00428       static sptr make();
00429 
00430       ~constellation_qpsk();
00431 
00432       unsigned int decision_maker(const gr_complex *sample);
00433 
00434     protected:
00435       constellation_qpsk();
00436     };
00437 
00438 
00439     /************************************************************/
00440     /* constellation_dqpsk                                      */
00441     /*                                                          */
00442     /* Works with differential encoding; slower decisions.      */
00443     /*                                                          */
00444     /************************************************************/
00445 
00446     /*!
00447      * \brief Digital constellation for DQPSK
00448      * \ingroup digital
00449      */
00450     class DIGITAL_API constellation_dqpsk : public constellation
00451     {
00452     public:
00453       typedef boost::shared_ptr<constellation_dqpsk> sptr;
00454 
00455       // public constructor
00456       static sptr make();
00457 
00458       ~constellation_dqpsk();
00459 
00460       unsigned int decision_maker(const gr_complex *sample);
00461 
00462     protected:
00463       constellation_dqpsk();
00464     };
00465 
00466 
00467     /************************************************************/
00468     /* constellation_8psk                                       */
00469     /*                                                          */
00470     /* Only works for 8PSK.                                     */
00471     /*                                                          */
00472     /************************************************************/
00473 
00474     /*! 
00475      * \brief Digital constellation for 8PSK
00476      * \ingroup digital
00477      */
00478     class DIGITAL_API constellation_8psk : public constellation
00479     {
00480     public:
00481       typedef boost::shared_ptr<constellation_8psk> sptr;
00482 
00483       // public constructor
00484       static sptr make();
00485 
00486       ~constellation_8psk();
00487 
00488       unsigned int decision_maker(const gr_complex *sample);
00489 
00490     protected:
00491       constellation_8psk();
00492     };
00493 
00494   } /* namespace digital */
00495 } /* namespace gr */
00496 
00497 #endif /* INCLUDED_DIGITAL_CONSTELLATION_H */