GNU Radio 3.7.0 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       // public constructor
00158       static sptr make(std::vector<gr_complex> constell,
00159                        std::vector<int> pre_diff_code,
00160                        unsigned int rotational_symmetry,
00161                        unsigned int dimensionality);
00162 
00163       unsigned int decision_maker(const gr_complex *sample);
00164       // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
00165       // void calc_euclidean_metric(gr_complex *sample, float *metric);
00166       // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
00167 
00168     protected:
00169       constellation_calcdist(std::vector<gr_complex> constell,
00170                              std::vector<int> pre_diff_code,
00171                              unsigned int rotational_symmetry,
00172                              unsigned int dimensionality);
00173     };
00174 
00175 
00176     /************************************************************/
00177     /*! constellation_sector                                    */
00178     /************************************************************/
00179 
00180     /*!
00181      * \brief Sectorized digital constellation
00182      * \ingroup digital
00183      *
00184      * Constellation space is divided into sectors. Each sector is
00185      * associated with the nearest constellation point.
00186      *
00187      */
00188     class DIGITAL_API constellation_sector : public constellation
00189     {
00190     public:
00191 
00192       constellation_sector(std::vector<gr_complex> constell,
00193                            std::vector<int> pre_diff_code,
00194                            unsigned int rotational_symmetry,
00195                            unsigned int dimensionality,
00196                            unsigned int n_sectors);
00197 
00198       ~constellation_sector();
00199 
00200       unsigned int decision_maker(const gr_complex *sample);
00201 
00202     protected:
00203       virtual unsigned int get_sector(const gr_complex *sample) = 0;
00204       virtual unsigned int calc_sector_value(unsigned int sector) = 0;
00205       void find_sector_values();
00206 
00207       unsigned int n_sectors;
00208 
00209     private:
00210       std::vector<int> sector_values;
00211     };
00212 
00213     /************************************************************/
00214     /* constellation_rect                                       */
00215     /************************************************************/
00216 
00217     /*!
00218      * \brief Rectangular digital constellation
00219      * \ingroup digital
00220      *
00221      * Only implemented for 1-(complex)dimensional constellation.
00222      *
00223      * Constellation space is divided into rectangular sectors. Each
00224      * sector is associated with the nearest constellation point.
00225      *
00226      * Works well for square QAM.
00227      *
00228      * Works for any generic constellation provided sectors are not
00229      * too large.
00230      */
00231 
00232 
00233     class DIGITAL_API constellation_rect
00234       : public constellation_sector
00235     {
00236     public:
00237       typedef boost::shared_ptr<constellation_rect> sptr;
00238 
00239       // public constructor
00240       static constellation_rect::sptr make(std::vector<gr_complex> constell,
00241                                            std::vector<int> pre_diff_code,
00242                                            unsigned int rotational_symmetry,
00243                                            unsigned int real_sectors,
00244                                            unsigned int imag_sectors,
00245                                            float width_real_sectors,
00246                                            float width_imag_sectors);
00247       ~constellation_rect();
00248 
00249     protected:
00250 
00251       constellation_rect(std::vector<gr_complex> constell,
00252                          std::vector<int> pre_diff_code,
00253                          unsigned int rotational_symmetry,
00254                          unsigned int real_sectors,
00255                          unsigned int imag_sectors,
00256                          float width_real_sectors,
00257                          float width_imag_sectors);
00258 
00259       unsigned int get_sector(const gr_complex *sample);
00260   
00261       unsigned int calc_sector_value(unsigned int sector);
00262 
00263     private:
00264       unsigned int n_real_sectors;
00265       unsigned int n_imag_sectors;
00266       float d_width_real_sectors;
00267       float d_width_imag_sectors;
00268     };
00269 
00270 
00271     /************************************************************/
00272     /* constellation_expl_rect                                  */
00273     /************************************************************/
00274 
00275     /*!
00276      * \brief Rectangular digital constellation
00277      * \ingroup digital
00278      *
00279      * Only implemented for 1-(complex)dimensional constellation.
00280      *
00281      * Constellation space is divided into rectangular sectors. Each
00282      * sector is associated with the nearest constellation point.
00283      *
00284      * This class is different from constellation_rect in that the
00285      * mapping from sector to constellation point is explicitly passed
00286      * into the constructor as sector_values.  Usually we do not need
00287      * this, since we want each sector to be automatically mapped to
00288      * the closest constellation point, however sometimes it's nice to
00289      * have the flexibility.
00290      */
00291     class DIGITAL_API constellation_expl_rect 
00292       : public constellation_rect
00293     {
00294     public:
00295       typedef boost::shared_ptr<constellation_expl_rect> sptr;
00296 
00297       static sptr make(std::vector<gr_complex> constellation,
00298                        std::vector<int> pre_diff_code,
00299                        unsigned int rotational_symmetry,
00300                        unsigned int real_sectors,
00301                        unsigned int imag_sectors,
00302                        float width_real_sectors,
00303                        float width_imag_sectors,
00304                        std::vector<unsigned int> sector_values);
00305       ~constellation_expl_rect();
00306 
00307     protected:
00308       constellation_expl_rect(std::vector<gr_complex> constellation,
00309                               std::vector<int> pre_diff_code,
00310                               unsigned int rotational_symmetry,
00311                               unsigned int real_sectors,
00312                               unsigned int imag_sectors,
00313                               float width_real_sectors,
00314                               float width_imag_sectors,
00315                               std::vector<unsigned int> sector_values);
00316 
00317       unsigned int calc_sector_value (unsigned int sector) {
00318         return d_sector_values[sector];
00319       }
00320 
00321     private:
00322       std::vector<unsigned int> d_sector_values;
00323     };
00324 
00325     /************************************************************/
00326     /* constellation_psk                                        */
00327     /************************************************************/
00328 
00329     /*! 
00330      * \brief constellation_psk
00331      * \ingroup digital
00332      *
00333      * Constellation space is divided into pie slices sectors.
00334      *
00335      * Each slice is associated with the nearest constellation point. 
00336      *
00337      * Works well for PSK but nothing else.  
00338      *
00339      * Assumes that there is a constellation point at 1.x 
00340      */
00341     class DIGITAL_API constellation_psk : public constellation_sector
00342     {
00343     public:
00344       typedef boost::shared_ptr<constellation_psk> sptr;
00345 
00346       // public constructor
00347       static sptr make(std::vector<gr_complex> constell,
00348                        std::vector<int> pre_diff_code,
00349                        unsigned int n_sectors);
00350 
00351       ~constellation_psk();
00352 
00353     protected:
00354       unsigned int get_sector(const gr_complex *sample);
00355   
00356       unsigned int calc_sector_value(unsigned int sector);
00357 
00358       constellation_psk(std::vector<gr_complex> constell,
00359                         std::vector<int> pre_diff_code,
00360                         unsigned int n_sectors);
00361     };
00362 
00363 
00364     /************************************************************/
00365     /* constellation_bpsk                                       */
00366     /*                                                          */
00367     /* Only works for BPSK.                                     */
00368     /*                                                          */
00369     /************************************************************/
00370 
00371     /*! 
00372      * \brief Digital constellation for BPSK 
00373      * \ingroup digital
00374      */
00375     class DIGITAL_API constellation_bpsk : public constellation
00376     {
00377     public:
00378       typedef boost::shared_ptr<constellation_bpsk> sptr;
00379 
00380       // public constructor
00381       static sptr make();
00382 
00383       ~constellation_bpsk();
00384 
00385       unsigned int decision_maker(const gr_complex *sample);
00386 
00387     protected:
00388       constellation_bpsk();
00389     };
00390 
00391 
00392     /************************************************************/
00393     /* constellation_qpsk                                       */
00394     /*                                                          */
00395     /* Only works for QPSK.                                     */
00396     /*                                                          */
00397     /************************************************************/
00398 
00399     /*! 
00400      * \brief Digital constellation for QPSK
00401      * \ingroup digital
00402      */
00403     class DIGITAL_API constellation_qpsk : public constellation
00404     {
00405     public:
00406       typedef boost::shared_ptr<constellation_qpsk> sptr;
00407 
00408       // public constructor
00409       static sptr make();
00410 
00411       ~constellation_qpsk();
00412 
00413       unsigned int decision_maker(const gr_complex *sample);
00414 
00415     protected:
00416       constellation_qpsk();
00417     };
00418 
00419 
00420     /************************************************************/
00421     /* constellation_dqpsk                                      */
00422     /*                                                          */
00423     /* Works with differential encoding; slower decisions.      */
00424     /*                                                          */
00425     /************************************************************/
00426 
00427     /*!
00428      * \brief Digital constellation for DQPSK
00429      * \ingroup digital
00430      */
00431     class DIGITAL_API constellation_dqpsk : public constellation
00432     {
00433     public:
00434       typedef boost::shared_ptr<constellation_dqpsk> sptr;
00435 
00436       // public constructor
00437       static sptr make();
00438 
00439       ~constellation_dqpsk();
00440 
00441       unsigned int decision_maker(const gr_complex *sample);
00442 
00443     protected:
00444       constellation_dqpsk();
00445     };
00446 
00447 
00448     /************************************************************/
00449     /* constellation_8psk                                       */
00450     /*                                                          */
00451     /* Only works for 8PSK.                                     */
00452     /*                                                          */
00453     /************************************************************/
00454 
00455     /*! 
00456      * \brief Digital constellation for 8PSK
00457      * \ingroup digital
00458      */
00459     class DIGITAL_API constellation_8psk : public constellation
00460     {
00461     public:
00462       typedef boost::shared_ptr<constellation_8psk> sptr;
00463 
00464       // public constructor
00465       static sptr make();
00466 
00467       ~constellation_8psk();
00468 
00469       unsigned int decision_maker(const gr_complex *sample);
00470 
00471     protected:
00472       constellation_8psk();
00473     };
00474 
00475   } /* namespace digital */
00476 } /* namespace gr */
00477 
00478 #endif /* INCLUDED_DIGITAL_CONSTELLATION_H */