GNU Radio 3.5.1 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   //! Returns the constellation points for a symbol value
00067   void map_to_points(unsigned int value, gr_complex *points);
00068   std::vector<gr_complex> map_to_points_v(unsigned int value);
00069 
00070   //! Returns the constellation point that matches best.
00071   virtual unsigned int decision_maker (const gr_complex *sample) = 0;
00072   //! Takes a vector rather than a pointer.  Better for SWIG wrapping.
00073   unsigned int decision_maker_v (std::vector<gr_complex> sample);
00074   //! Also calculates the phase error.
00075   unsigned int decision_maker_pe (const gr_complex *sample, float *phase_error);
00076   //! Calculates distance.
00077   unsigned int decision_maker_e (const gr_complex *sample, float *error);
00078   
00079   //! Calculates metrics for all points in the constellation.
00080   //! For use with the viterbi algorithm.
00081   virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type);
00082   virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
00083   virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
00084   
00085   //! Returns the set of points in this constellation.
00086   std::vector<gr_complex> points() { return d_constellation;}
00087   //! Returns the vector of points in this constellation.
00088   //! Raise error if dimensionality is not one.
00089   std::vector<gr_complex> s_points();
00090   //! Returns a vector of vectors of points.
00091   std::vector<std::vector<gr_complex> > v_points();
00092   //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
00093   bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
00094   //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
00095   void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
00096   //! Returns the encoding to apply before differential encoding.
00097   std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;}
00098   //! Returns the order of rotational symmetry.
00099   unsigned int rotational_symmetry() { return d_rotational_symmetry;}
00100   //! Returns the number of complex numbers in a single symbol.
00101   unsigned int dimensionality() {return d_dimensionality;}
00102 
00103   unsigned int bits_per_symbol () {
00104     return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
00105   }
00106   
00107   unsigned int arity () {
00108     return d_arity;
00109   }
00110 
00111   digital_constellation_sptr base() {
00112     return shared_from_this();
00113   }  
00114 
00115  protected:
00116 
00117   std::vector<gr_complex> d_constellation;
00118   std::vector<unsigned int> d_pre_diff_code; 
00119   bool d_apply_pre_diff_code;
00120   unsigned int d_rotational_symmetry;
00121   unsigned int d_dimensionality;
00122   unsigned int d_arity;
00123 
00124   float get_distance(unsigned int index, const gr_complex *sample);
00125   unsigned int get_closest_point(const gr_complex *sample);
00126   void calc_arity ();
00127 };
00128 
00129 /************************************************************/
00130 /* digital_constellation_calcdist                           */
00131 /*                                                          */
00132 /************************************************************/
00133 
00134 class digital_constellation_calcdist;
00135 typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_calcdist_sptr;
00136 
00137 // public constructor
00138 DIGITAL_API digital_constellation_calcdist_sptr
00139 digital_make_constellation_calcdist (std::vector<gr_complex> constellation,
00140                                      std::vector<unsigned int> pre_diff_code,
00141                                      unsigned int rotational_symmetry,
00142                                      unsigned int dimensionality);
00143 
00144 
00145 /*! \brief Calculate Euclidian distance for any constellation
00146  *  \ingroup digital
00147  *
00148  * Constellation which calculates the distance to each point in the
00149  * constellation for decision making. Inefficient for large
00150  * constellations.
00151  */
00152 class DIGITAL_API digital_constellation_calcdist : public digital_constellation
00153 {
00154  public:
00155   digital_constellation_calcdist (std::vector<gr_complex> constellation,
00156                                   std::vector<unsigned int> pre_diff_code,
00157                                   unsigned int rotational_symmetry,
00158                                   unsigned int dimensionality);
00159   unsigned int decision_maker (const gr_complex *sample);
00160   // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
00161   // void calc_euclidean_metric(gr_complex *sample, float *metric);
00162   // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
00163   
00164  private:
00165   friend DIGITAL_API digital_constellation_calcdist_sptr
00166   digital_make_constellation_calcdist (std::vector<gr_complex> constellation);
00167 };
00168 
00169 
00170 /************************************************************/
00171 /*! digital_constellation_sector                             */
00172 /************************************************************/
00173 
00174 /*!
00175  * \brief Sectorized digital constellation
00176  * \ingroup digital
00177  *
00178  * Constellation space is divided into sectors. Each sector is
00179  * associated with the nearest constellation point.
00180  *
00181  */
00182 class DIGITAL_API digital_constellation_sector : public digital_constellation
00183 {
00184  public:
00185 
00186   digital_constellation_sector (std::vector<gr_complex> constellation,
00187                                 std::vector<unsigned int> pre_diff_code,
00188                                 unsigned int rotational_symmetry,
00189                                 unsigned int dimensionality,
00190                                 unsigned int n_sectors);
00191 
00192   unsigned int decision_maker (const gr_complex *sample);
00193 
00194  protected:
00195 
00196   virtual unsigned int get_sector (const gr_complex *sample) = 0;
00197   virtual unsigned int calc_sector_value (unsigned int sector) = 0;
00198   void find_sector_values ();
00199 
00200   unsigned int n_sectors;
00201 
00202  private:
00203 
00204   std::vector<unsigned int> sector_values;
00205 
00206 };
00207 
00208 /************************************************************/
00209 /* digital_constellation_rect                               */
00210 /************************************************************/
00211 
00212 /*!
00213  * \brief Rectangular digital constellation
00214  * \ingroup digital
00215  *
00216  * Only implemented for 1-(complex)dimensional constellation.
00217  *
00218  * Constellation space is divided into rectangular sectors. Each
00219  * sector is associated with the nearest constellation point.
00220  *
00221  * Works well for square QAM.
00222  *
00223  * Works for any generic constellation provided sectors are not too
00224  * large.
00225  */
00226 
00227 class digital_constellation_rect;
00228 typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect_sptr;
00229 
00230 // public constructor
00231 DIGITAL_API digital_constellation_rect_sptr 
00232 digital_make_constellation_rect (std::vector<gr_complex> constellation,
00233                                  std::vector<unsigned int> pre_diff_code,
00234                                  unsigned int rotational_symmetry,
00235                                  unsigned int real_sectors,
00236                                  unsigned int imag_sectors,
00237                                  float width_real_sectors,
00238                                  float width_imag_sectors);
00239 
00240 class DIGITAL_API digital_constellation_rect : public digital_constellation_sector
00241 {
00242  public:
00243 
00244   digital_constellation_rect (std::vector<gr_complex> constellation,
00245                               std::vector<unsigned int> pre_diff_code,
00246                               unsigned int rotational_symmetry,
00247                               unsigned int real_sectors,
00248                               unsigned int imag_sectors,
00249                               float width_real_sectors,
00250                               float width_imag_sectors);
00251 
00252  protected:
00253 
00254   unsigned int get_sector (const gr_complex *sample);
00255   
00256   unsigned int calc_sector_value (unsigned int sector);
00257 
00258  private:
00259 
00260   unsigned int n_real_sectors;
00261   unsigned int n_imag_sectors;
00262   float d_width_real_sectors;
00263   float d_width_imag_sectors;
00264 
00265   friend DIGITAL_API digital_constellation_rect_sptr
00266   digital_make_constellation_rect (std::vector<gr_complex> constellation,
00267                                    std::vector<unsigned int> pre_diff_code,
00268                                    unsigned int rotational_symmetry,
00269                                    unsigned int real_sectors,
00270                                    unsigned int imag_sectors,
00271                                    float width_real_sectors,
00272                                    float width_imag_sectors);
00273   
00274 };
00275 
00276 
00277 /************************************************************/
00278 /* digital_constellation_psk                                */
00279 /************************************************************/
00280 
00281 class digital_constellation_psk;
00282 typedef boost::shared_ptr<digital_constellation_psk> digital_constellation_psk_sptr;
00283 
00284 // public constructor
00285 DIGITAL_API digital_constellation_psk_sptr 
00286 digital_make_constellation_psk (std::vector<gr_complex> constellation,
00287                                 std::vector<unsigned int> pre_diff_code,
00288                                 unsigned int n_sectors);
00289 
00290 /*! 
00291  * \brief digital_constellation_psk
00292  * \ingroup digital
00293  *
00294  * Constellation space is divided into pie slices sectors.
00295  *
00296  * Each slice is associated with the nearest constellation point. 
00297  *
00298  * Works well for PSK but nothing else.  
00299  *
00300  * Assumes that there is a constellation point at 1.x 
00301  */
00302 class DIGITAL_API digital_constellation_psk : public digital_constellation_sector
00303 {
00304  public:
00305 
00306   digital_constellation_psk (std::vector<gr_complex> constellation,
00307                              std::vector<unsigned int> pre_diff_code,
00308                              unsigned int n_sectors);
00309 
00310  protected:
00311 
00312   unsigned int get_sector (const gr_complex *sample);
00313   
00314   unsigned int calc_sector_value (unsigned int sector);
00315 
00316  private:
00317 
00318   friend DIGITAL_API digital_constellation_psk_sptr
00319   digital_make_constellation_psk (std::vector<gr_complex> constellation,
00320                                   std::vector<unsigned int> pre_diff_code,
00321                                   unsigned int n_sectors);
00322   
00323 };
00324 
00325 
00326 /************************************************************/
00327 /* digital_constellation_bpsk                               */
00328 /*                                                          */
00329 /* Only works for BPSK.                                     */
00330 /*                                                          */
00331 /************************************************************/
00332 
00333 class digital_constellation_bpsk;
00334 typedef boost::shared_ptr<digital_constellation_bpsk> digital_constellation_bpsk_sptr;
00335 
00336 // public constructor
00337 DIGITAL_API digital_constellation_bpsk_sptr 
00338 digital_make_constellation_bpsk ();
00339 
00340 /*! 
00341  * \brief Digital constellation for BPSK 
00342  * \ingroup digital
00343  */
00344 class DIGITAL_API digital_constellation_bpsk : public digital_constellation
00345 {
00346  public:
00347 
00348   digital_constellation_bpsk ();
00349   unsigned int decision_maker (const gr_complex *sample);
00350 
00351   friend DIGITAL_API digital_constellation_bpsk_sptr
00352   digital_make_constellation_bpsk ();
00353   
00354 };
00355 
00356 
00357 /************************************************************/
00358 /* digital_constellation_qpsk                               */
00359 /*                                                          */
00360 /* Only works for QPSK.                                     */
00361 /*                                                          */
00362 /************************************************************/
00363 
00364 class digital_constellation_qpsk;
00365 typedef boost::shared_ptr<digital_constellation_qpsk> digital_constellation_qpsk_sptr;
00366 
00367 // public constructor
00368 DIGITAL_API digital_constellation_qpsk_sptr 
00369 digital_make_constellation_qpsk ();
00370 
00371 /*! 
00372  * \brief Digital constellation for QPSK
00373  * \ingroup digital
00374  */
00375 class DIGITAL_API digital_constellation_qpsk : public digital_constellation
00376 {
00377  public:
00378 
00379   digital_constellation_qpsk ();
00380   unsigned int decision_maker (const gr_complex *sample);
00381 
00382   friend DIGITAL_API digital_constellation_qpsk_sptr
00383   digital_make_constellation_qpsk ();
00384   
00385 };
00386 
00387 
00388 /************************************************************/
00389 /* digital_constellation_dqpsk                              */
00390 /*                                                          */
00391 /* Works with differential encoding; slower decisions.      */
00392 /*                                                          */
00393 /************************************************************/
00394 
00395 class digital_constellation_dqpsk;
00396 typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
00397 
00398 // public constructor
00399 DIGITAL_API digital_constellation_dqpsk_sptr 
00400 digital_make_constellation_dqpsk ();
00401 
00402 /*!
00403  * \brief Digital constellation for DQPSK
00404  * \ingroup digital
00405  */
00406 class DIGITAL_API digital_constellation_dqpsk : public digital_constellation
00407 {
00408  public:
00409 
00410   digital_constellation_dqpsk ();
00411   unsigned int decision_maker (const gr_complex *sample);
00412 
00413   friend DIGITAL_API digital_constellation_dqpsk_sptr
00414   digital_make_constellation_dqpsk ();
00415   
00416 };
00417 
00418 
00419 /************************************************************/
00420 /* digital_constellation_8psk                               */
00421 /*                                                          */
00422 /* Only works for 8PSK.                                     */
00423 /*                                                          */
00424 /************************************************************/
00425 
00426 class digital_constellation_8psk;
00427 typedef boost::shared_ptr<digital_constellation_8psk> digital_constellation_8psk_sptr;
00428 
00429 // public constructor
00430 DIGITAL_API digital_constellation_8psk_sptr 
00431 digital_make_constellation_8psk ();
00432 
00433 /*! 
00434  * \brief Digital constellation for 8PSK
00435  * \ingroup digital
00436  */
00437 class DIGITAL_API digital_constellation_8psk : public digital_constellation
00438 {
00439  public:
00440 
00441   digital_constellation_8psk ();
00442   unsigned int decision_maker (const gr_complex *sample);
00443 
00444   friend DIGITAL_API digital_constellation_8psk_sptr
00445   digital_make_constellation_8psk ();
00446   
00447 };
00448 
00449 #endif