GNU Radio 3.6.5 C++ API

digital_constellation.h

Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2010, 2011 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 <digital_api.h>
00027 #include <vector>
00028 #include <math.h>
00029 #include <gr_complex.h>
00030 #include <boost/enable_shared_from_this.hpp>
00031 #include <digital_metric_type.h>
00032 
00033 /************************************************************/
00034 /* digital_constellation                                    */
00035 /*                                                          */
00036 /* Base class defining interface.                           */
00037 /************************************************************/
00038 
00039 class digital_constellation;
00040 typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr;
00041 
00042 /*!
00043  * \brief An abstracted constellation object
00044  * \ingroup digital
00045  *
00046  * The constellation objects hold the necessary information to pass
00047  * around constellation information for modulators and
00048  * demodulators. These objects contain the mapping between the bits
00049  * and the constellation points used to represent them as well as
00050  * methods for slicing the symbol space. Various implementations are
00051  * possible for efficiency and ease of use.
00052  *
00053  * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
00054  * from this class and overloaded to perform optimized slicing and
00055  * constellation mappings.
00056  */
00057 class DIGITAL_API digital_constellation : public boost::enable_shared_from_this<digital_constellation>
00058 {
00059 public:
00060   digital_constellation (std::vector<gr_complex> constellation,
00061                          std::vector<unsigned int> pre_diff_code,
00062                          unsigned int rotational_symmetry,
00063                          unsigned int dimensionality);
00064   digital_constellation ();
00065 
00066   virtual ~digital_constellation();
00067 
00068   //! Returns the constellation points for a symbol value
00069   void map_to_points(unsigned int value, gr_complex *points);
00070   std::vector<gr_complex> map_to_points_v(unsigned int value);
00071 
00072   //! Returns the constellation point that matches best.
00073   virtual unsigned int decision_maker (const gr_complex *sample) = 0;
00074   //! Takes a vector rather than a pointer.  Better for SWIG wrapping.
00075   unsigned int decision_maker_v (std::vector<gr_complex> sample);
00076   //! Also calculates the phase error.
00077   unsigned int decision_maker_pe (const gr_complex *sample, float *phase_error);
00078   //! Calculates distance.
00079   unsigned int decision_maker_e (const gr_complex *sample, float *error);
00080   
00081   //! Calculates metrics for all points in the constellation.
00082   //! For use with the viterbi algorithm.
00083   virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type);
00084   virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
00085   virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
00086   
00087   //! Returns the set of points in this constellation.
00088   std::vector<gr_complex> points() { return d_constellation;}
00089   //! Returns the vector of points in this constellation.
00090   //! Raise error if dimensionality is not one.
00091   std::vector<gr_complex> s_points();
00092   //! Returns a vector of vectors of points.
00093   std::vector<std::vector<gr_complex> > v_points();
00094   //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
00095   bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
00096   //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
00097   void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
00098   //! Returns the encoding to apply before differential encoding.
00099   std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;}
00100   //! Returns the order of rotational symmetry.
00101   unsigned int rotational_symmetry() { return d_rotational_symmetry;}
00102   //! Returns the number of complex numbers in a single symbol.
00103   unsigned int dimensionality() {return d_dimensionality;}
00104 
00105   unsigned int bits_per_symbol () {
00106     return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
00107   }
00108   
00109   unsigned int arity () {
00110     return d_arity;
00111   }
00112 
00113   digital_constellation_sptr base() {
00114     return shared_from_this();
00115   }  
00116 
00117  protected:
00118 
00119   std::vector<gr_complex> d_constellation;
00120   std::vector<unsigned int> d_pre_diff_code; 
00121   bool d_apply_pre_diff_code;
00122   unsigned int d_rotational_symmetry;
00123   unsigned int d_dimensionality;
00124   unsigned int d_arity;
00125   // The orignal constellation points were multiplied by this factor to get a
00126   // constellation with average magnitude 1.
00127   float d_scalefactor;
00128 
00129   float get_distance(unsigned int index, const gr_complex *sample);
00130   unsigned int get_closest_point(const gr_complex *sample);
00131   void calc_arity ();
00132 };
00133 
00134 /************************************************************/
00135 /* digital_constellation_calcdist                           */
00136 /*                                                          */
00137 /************************************************************/
00138 
00139 class digital_constellation_calcdist;
00140 typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_calcdist_sptr;
00141 
00142 // public constructor
00143 DIGITAL_API digital_constellation_calcdist_sptr
00144 digital_make_constellation_calcdist (std::vector<gr_complex> constellation,
00145                                      std::vector<unsigned int> pre_diff_code,
00146                                      unsigned int rotational_symmetry,
00147                                      unsigned int dimensionality);
00148 
00149 
00150 /*! \brief Calculate Euclidian distance for any constellation
00151  *  \ingroup digital
00152  *
00153  * Constellation which calculates the distance to each point in the
00154  * constellation for decision making. Inefficient for large
00155  * constellations.
00156  */
00157 class DIGITAL_API digital_constellation_calcdist : public digital_constellation
00158 {
00159  public:
00160   digital_constellation_calcdist (std::vector<gr_complex> constellation,
00161                                   std::vector<unsigned int> pre_diff_code,
00162                                   unsigned int rotational_symmetry,
00163                                   unsigned int dimensionality);
00164   unsigned int decision_maker (const gr_complex *sample);
00165   // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
00166   // void calc_euclidean_metric(gr_complex *sample, float *metric);
00167   // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
00168   
00169  private:
00170   friend DIGITAL_API digital_constellation_calcdist_sptr
00171   digital_make_constellation_calcdist (std::vector<gr_complex> constellation);
00172 };
00173 
00174 
00175 /************************************************************/
00176 /*! digital_constellation_sector                             */
00177 /************************************************************/
00178 
00179 /*!
00180  * \brief Sectorized digital constellation
00181  * \ingroup digital
00182  *
00183  * Constellation space is divided into sectors. Each sector is
00184  * associated with the nearest constellation point.
00185  *
00186  */
00187 class DIGITAL_API digital_constellation_sector : public digital_constellation
00188 {
00189  public:
00190 
00191   digital_constellation_sector (std::vector<gr_complex> constellation,
00192                                 std::vector<unsigned int> pre_diff_code,
00193                                 unsigned int rotational_symmetry,
00194                                 unsigned int dimensionality,
00195                                 unsigned int n_sectors);
00196 
00197   unsigned int decision_maker (const gr_complex *sample);
00198 
00199  protected:
00200 
00201   virtual unsigned int get_sector (const gr_complex *sample) = 0;
00202   virtual unsigned int calc_sector_value (unsigned int sector) = 0;
00203   void find_sector_values ();
00204 
00205   unsigned int n_sectors;
00206 
00207  private:
00208 
00209   std::vector<unsigned int> sector_values;
00210 
00211 };
00212 
00213 /************************************************************/
00214 /* digital_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 too
00229  * large.
00230  */
00231 
00232 class digital_constellation_rect;
00233 typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect_sptr;
00234 
00235 // public constructor
00236 DIGITAL_API digital_constellation_rect_sptr 
00237 digital_make_constellation_rect (std::vector<gr_complex> constellation,
00238                                  std::vector<unsigned int> pre_diff_code,
00239                                  unsigned int rotational_symmetry,
00240                                  unsigned int real_sectors,
00241                                  unsigned int imag_sectors,
00242                                  float width_real_sectors,
00243                                  float width_imag_sectors);
00244 
00245 class DIGITAL_API digital_constellation_rect : public digital_constellation_sector
00246 {
00247  public:
00248 
00249   digital_constellation_rect (std::vector<gr_complex> constellation,
00250                               std::vector<unsigned int> pre_diff_code,
00251                               unsigned int rotational_symmetry,
00252                               unsigned int real_sectors,
00253                               unsigned int imag_sectors,
00254                               float width_real_sectors,
00255                               float width_imag_sectors);
00256 
00257  protected:
00258 
00259   unsigned int get_sector (const gr_complex *sample);
00260   
00261   unsigned int calc_sector_value (unsigned int sector);
00262 
00263  private:
00264 
00265   unsigned int n_real_sectors;
00266   unsigned int n_imag_sectors;
00267   float d_width_real_sectors;
00268   float d_width_imag_sectors;
00269 
00270   friend DIGITAL_API digital_constellation_rect_sptr
00271   digital_make_constellation_rect (std::vector<gr_complex> constellation,
00272                                    std::vector<unsigned int> pre_diff_code,
00273                                    unsigned int rotational_symmetry,
00274                                    unsigned int real_sectors,
00275                                    unsigned int imag_sectors,
00276                                    float width_real_sectors,
00277                                    float width_imag_sectors);
00278   
00279 };
00280 
00281 /************************************************************/
00282 /* digital_constellation_expl_rect                               */
00283 /************************************************************/
00284 
00285 /*!
00286  * \brief Rectangular digital constellation
00287  * \ingroup digital
00288  *
00289  * Only implemented for 1-(complex)dimensional constellation.
00290  *
00291  * Constellation space is divided into rectangular sectors. Each
00292  * sector is associated with the nearest constellation point.
00293  *
00294  * This class is different from constellation_rect in that the mapping
00295  * from sector to constellation point is explicitly passed into the
00296  * constructor as sector_values.  Usually we do not need this, since
00297  * we want each sector to be automatically mapped to the closest
00298  * constellation point, however sometimes it's nice to have the
00299  * flexibility.
00300  */
00301 
00302 class digital_constellation_expl_rect;
00303 typedef boost::shared_ptr<digital_constellation_expl_rect> digital_constellation_expl_rect_sptr;
00304 
00305 // public constructor
00306 DIGITAL_API digital_constellation_expl_rect_sptr 
00307 digital_make_constellation_expl_rect (
00308   std::vector<gr_complex> constellation,
00309   std::vector<unsigned 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 
00318 class DIGITAL_API digital_constellation_expl_rect : public digital_constellation_rect
00319 {
00320  public:
00321 
00322   digital_constellation_expl_rect (
00323     std::vector<gr_complex> constellation,
00324     std::vector<unsigned int> pre_diff_code,
00325     unsigned int rotational_symmetry,
00326     unsigned int real_sectors,
00327     unsigned int imag_sectors,
00328     float width_real_sectors,
00329     float width_imag_sectors,
00330     std::vector<unsigned int> sector_values
00331   );
00332 
00333  protected:
00334   unsigned int calc_sector_value (unsigned int sector) {
00335     return d_sector_values[sector];
00336   }
00337 
00338  private:
00339   std::vector<unsigned int> d_sector_values;
00340 
00341   friend DIGITAL_API digital_constellation_expl_rect_sptr
00342   digital_make_constellation_expl_rect (
00343     std::vector<gr_complex> constellation,
00344     std::vector<unsigned int> pre_diff_code,
00345     unsigned int rotational_symmetry,
00346     unsigned int real_sectors,
00347     unsigned int imag_sectors,
00348     float width_real_sectors,
00349     float width_imag_sectors,
00350     std::vector<unsigned int> sector_values
00351   );
00352   
00353 };
00354 
00355 
00356 /************************************************************/
00357 /* digital_constellation_psk                                */
00358 /************************************************************/
00359 
00360 class digital_constellation_psk;
00361 typedef boost::shared_ptr<digital_constellation_psk> digital_constellation_psk_sptr;
00362 
00363 // public constructor
00364 DIGITAL_API digital_constellation_psk_sptr 
00365 digital_make_constellation_psk (std::vector<gr_complex> constellation,
00366                                 std::vector<unsigned int> pre_diff_code,
00367                                 unsigned int n_sectors);
00368 
00369 /*! 
00370  * \brief digital_constellation_psk
00371  * \ingroup digital
00372  *
00373  * Constellation space is divided into pie slices sectors.
00374  *
00375  * Each slice is associated with the nearest constellation point. 
00376  *
00377  * Works well for PSK but nothing else.  
00378  *
00379  * Assumes that there is a constellation point at 1.x 
00380  */
00381 class DIGITAL_API digital_constellation_psk : public digital_constellation_sector
00382 {
00383  public:
00384 
00385   digital_constellation_psk (std::vector<gr_complex> constellation,
00386                              std::vector<unsigned int> pre_diff_code,
00387                              unsigned int n_sectors);
00388 
00389  protected:
00390 
00391   unsigned int get_sector (const gr_complex *sample);
00392   
00393   unsigned int calc_sector_value (unsigned int sector);
00394 
00395  private:
00396 
00397   friend DIGITAL_API digital_constellation_psk_sptr
00398   digital_make_constellation_psk (std::vector<gr_complex> constellation,
00399                                   std::vector<unsigned int> pre_diff_code,
00400                                   unsigned int n_sectors);
00401   
00402 };
00403 
00404 
00405 /************************************************************/
00406 /* digital_constellation_bpsk                               */
00407 /*                                                          */
00408 /* Only works for BPSK.                                     */
00409 /*                                                          */
00410 /************************************************************/
00411 
00412 class digital_constellation_bpsk;
00413 typedef boost::shared_ptr<digital_constellation_bpsk> digital_constellation_bpsk_sptr;
00414 
00415 // public constructor
00416 DIGITAL_API digital_constellation_bpsk_sptr 
00417 digital_make_constellation_bpsk ();
00418 
00419 /*! 
00420  * \brief Digital constellation for BPSK 
00421  * \ingroup digital
00422  */
00423 class DIGITAL_API digital_constellation_bpsk : public digital_constellation
00424 {
00425  public:
00426 
00427   digital_constellation_bpsk ();
00428   unsigned int decision_maker (const gr_complex *sample);
00429 
00430   friend DIGITAL_API digital_constellation_bpsk_sptr
00431   digital_make_constellation_bpsk ();
00432   
00433 };
00434 
00435 
00436 /************************************************************/
00437 /* digital_constellation_qpsk                               */
00438 /*                                                          */
00439 /* Only works for QPSK.                                     */
00440 /*                                                          */
00441 /************************************************************/
00442 
00443 class digital_constellation_qpsk;
00444 typedef boost::shared_ptr<digital_constellation_qpsk> digital_constellation_qpsk_sptr;
00445 
00446 // public constructor
00447 DIGITAL_API digital_constellation_qpsk_sptr 
00448 digital_make_constellation_qpsk ();
00449 
00450 /*! 
00451  * \brief Digital constellation for QPSK
00452  * \ingroup digital
00453  */
00454 class DIGITAL_API digital_constellation_qpsk : public digital_constellation
00455 {
00456  public:
00457 
00458   digital_constellation_qpsk ();
00459   unsigned int decision_maker (const gr_complex *sample);
00460 
00461   friend DIGITAL_API digital_constellation_qpsk_sptr
00462   digital_make_constellation_qpsk ();
00463   
00464 };
00465 
00466 
00467 /************************************************************/
00468 /* digital_constellation_dqpsk                              */
00469 /*                                                          */
00470 /* Works with differential encoding; slower decisions.      */
00471 /*                                                          */
00472 /************************************************************/
00473 
00474 class digital_constellation_dqpsk;
00475 typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
00476 
00477 // public constructor
00478 DIGITAL_API digital_constellation_dqpsk_sptr 
00479 digital_make_constellation_dqpsk ();
00480 
00481 /*!
00482  * \brief Digital constellation for DQPSK
00483  * \ingroup digital
00484  */
00485 class DIGITAL_API digital_constellation_dqpsk : public digital_constellation
00486 {
00487  public:
00488 
00489   digital_constellation_dqpsk ();
00490   unsigned int decision_maker (const gr_complex *sample);
00491 
00492   friend DIGITAL_API digital_constellation_dqpsk_sptr
00493   digital_make_constellation_dqpsk ();
00494   
00495 };
00496 
00497 
00498 /************************************************************/
00499 /* digital_constellation_8psk                               */
00500 /*                                                          */
00501 /* Only works for 8PSK.                                     */
00502 /*                                                          */
00503 /************************************************************/
00504 
00505 class digital_constellation_8psk;
00506 typedef boost::shared_ptr<digital_constellation_8psk> digital_constellation_8psk_sptr;
00507 
00508 // public constructor
00509 DIGITAL_API digital_constellation_8psk_sptr 
00510 digital_make_constellation_8psk ();
00511 
00512 /*! 
00513  * \brief Digital constellation for 8PSK
00514  * \ingroup digital
00515  */
00516 class DIGITAL_API digital_constellation_8psk : public digital_constellation
00517 {
00518  public:
00519 
00520   digital_constellation_8psk ();
00521   unsigned int decision_maker (const gr_complex *sample);
00522 
00523   friend DIGITAL_API digital_constellation_8psk_sptr
00524   digital_make_constellation_8psk ();
00525   
00526 };
00527 
00528 #endif