GNU Radio v3.6.2-149-ga6d285d9 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   // The orignal constellation points were multiplied by this factor to get a
00124   // constellation with average magnitude 1.
00125   float d_scalefactor;
00126 
00127   float get_distance(unsigned int index, const gr_complex *sample);
00128   unsigned int get_closest_point(const gr_complex *sample);
00129   void calc_arity ();
00130 };
00131 
00132 /************************************************************/
00133 /* digital_constellation_calcdist                           */
00134 /*                                                          */
00135 /************************************************************/
00136 
00137 class digital_constellation_calcdist;
00138 typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_calcdist_sptr;
00139 
00140 // public constructor
00141 DIGITAL_API digital_constellation_calcdist_sptr
00142 digital_make_constellation_calcdist (std::vector<gr_complex> constellation,
00143                                      std::vector<unsigned int> pre_diff_code,
00144                                      unsigned int rotational_symmetry,
00145                                      unsigned int dimensionality);
00146 
00147 
00148 /*! \brief Calculate Euclidian distance for any constellation
00149  *  \ingroup digital
00150  *
00151  * Constellation which calculates the distance to each point in the
00152  * constellation for decision making. Inefficient for large
00153  * constellations.
00154  */
00155 class DIGITAL_API digital_constellation_calcdist : public digital_constellation
00156 {
00157  public:
00158   digital_constellation_calcdist (std::vector<gr_complex> constellation,
00159                                   std::vector<unsigned int> pre_diff_code,
00160                                   unsigned int rotational_symmetry,
00161                                   unsigned int dimensionality);
00162   unsigned int decision_maker (const gr_complex *sample);
00163   // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
00164   // void calc_euclidean_metric(gr_complex *sample, float *metric);
00165   // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
00166   
00167  private:
00168   friend DIGITAL_API digital_constellation_calcdist_sptr
00169   digital_make_constellation_calcdist (std::vector<gr_complex> constellation);
00170 };
00171 
00172 
00173 /************************************************************/
00174 /*! digital_constellation_sector                             */
00175 /************************************************************/
00176 
00177 /*!
00178  * \brief Sectorized digital constellation
00179  * \ingroup digital
00180  *
00181  * Constellation space is divided into sectors. Each sector is
00182  * associated with the nearest constellation point.
00183  *
00184  */
00185 class DIGITAL_API digital_constellation_sector : public digital_constellation
00186 {
00187  public:
00188 
00189   digital_constellation_sector (std::vector<gr_complex> constellation,
00190                                 std::vector<unsigned int> pre_diff_code,
00191                                 unsigned int rotational_symmetry,
00192                                 unsigned int dimensionality,
00193                                 unsigned int n_sectors);
00194 
00195   unsigned int decision_maker (const gr_complex *sample);
00196 
00197  protected:
00198 
00199   virtual unsigned int get_sector (const gr_complex *sample) = 0;
00200   virtual unsigned int calc_sector_value (unsigned int sector) = 0;
00201   void find_sector_values ();
00202 
00203   unsigned int n_sectors;
00204 
00205  private:
00206 
00207   std::vector<unsigned int> sector_values;
00208 
00209 };
00210 
00211 /************************************************************/
00212 /* digital_constellation_rect                               */
00213 /************************************************************/
00214 
00215 /*!
00216  * \brief Rectangular digital constellation
00217  * \ingroup digital
00218  *
00219  * Only implemented for 1-(complex)dimensional constellation.
00220  *
00221  * Constellation space is divided into rectangular sectors. Each
00222  * sector is associated with the nearest constellation point.
00223  *
00224  * Works well for square QAM.
00225  *
00226  * Works for any generic constellation provided sectors are not too
00227  * large.
00228  */
00229 
00230 class digital_constellation_rect;
00231 typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect_sptr;
00232 
00233 // public constructor
00234 DIGITAL_API digital_constellation_rect_sptr 
00235 digital_make_constellation_rect (std::vector<gr_complex> constellation,
00236                                  std::vector<unsigned int> pre_diff_code,
00237                                  unsigned int rotational_symmetry,
00238                                  unsigned int real_sectors,
00239                                  unsigned int imag_sectors,
00240                                  float width_real_sectors,
00241                                  float width_imag_sectors);
00242 
00243 class DIGITAL_API digital_constellation_rect : public digital_constellation_sector
00244 {
00245  public:
00246 
00247   digital_constellation_rect (std::vector<gr_complex> constellation,
00248                               std::vector<unsigned int> pre_diff_code,
00249                               unsigned int rotational_symmetry,
00250                               unsigned int real_sectors,
00251                               unsigned int imag_sectors,
00252                               float width_real_sectors,
00253                               float width_imag_sectors);
00254 
00255  protected:
00256 
00257   unsigned int get_sector (const gr_complex *sample);
00258   
00259   unsigned int calc_sector_value (unsigned int sector);
00260 
00261  private:
00262 
00263   unsigned int n_real_sectors;
00264   unsigned int n_imag_sectors;
00265   float d_width_real_sectors;
00266   float d_width_imag_sectors;
00267 
00268   friend DIGITAL_API digital_constellation_rect_sptr
00269   digital_make_constellation_rect (std::vector<gr_complex> constellation,
00270                                    std::vector<unsigned int> pre_diff_code,
00271                                    unsigned int rotational_symmetry,
00272                                    unsigned int real_sectors,
00273                                    unsigned int imag_sectors,
00274                                    float width_real_sectors,
00275                                    float width_imag_sectors);
00276   
00277 };
00278 
00279 
00280 /************************************************************/
00281 /* digital_constellation_psk                                */
00282 /************************************************************/
00283 
00284 class digital_constellation_psk;
00285 typedef boost::shared_ptr<digital_constellation_psk> digital_constellation_psk_sptr;
00286 
00287 // public constructor
00288 DIGITAL_API digital_constellation_psk_sptr 
00289 digital_make_constellation_psk (std::vector<gr_complex> constellation,
00290                                 std::vector<unsigned int> pre_diff_code,
00291                                 unsigned int n_sectors);
00292 
00293 /*! 
00294  * \brief digital_constellation_psk
00295  * \ingroup digital
00296  *
00297  * Constellation space is divided into pie slices sectors.
00298  *
00299  * Each slice is associated with the nearest constellation point. 
00300  *
00301  * Works well for PSK but nothing else.  
00302  *
00303  * Assumes that there is a constellation point at 1.x 
00304  */
00305 class DIGITAL_API digital_constellation_psk : public digital_constellation_sector
00306 {
00307  public:
00308 
00309   digital_constellation_psk (std::vector<gr_complex> constellation,
00310                              std::vector<unsigned int> pre_diff_code,
00311                              unsigned int n_sectors);
00312 
00313  protected:
00314 
00315   unsigned int get_sector (const gr_complex *sample);
00316   
00317   unsigned int calc_sector_value (unsigned int sector);
00318 
00319  private:
00320 
00321   friend DIGITAL_API digital_constellation_psk_sptr
00322   digital_make_constellation_psk (std::vector<gr_complex> constellation,
00323                                   std::vector<unsigned int> pre_diff_code,
00324                                   unsigned int n_sectors);
00325   
00326 };
00327 
00328 
00329 /************************************************************/
00330 /* digital_constellation_bpsk                               */
00331 /*                                                          */
00332 /* Only works for BPSK.                                     */
00333 /*                                                          */
00334 /************************************************************/
00335 
00336 class digital_constellation_bpsk;
00337 typedef boost::shared_ptr<digital_constellation_bpsk> digital_constellation_bpsk_sptr;
00338 
00339 // public constructor
00340 DIGITAL_API digital_constellation_bpsk_sptr 
00341 digital_make_constellation_bpsk ();
00342 
00343 /*! 
00344  * \brief Digital constellation for BPSK 
00345  * \ingroup digital
00346  */
00347 class DIGITAL_API digital_constellation_bpsk : public digital_constellation
00348 {
00349  public:
00350 
00351   digital_constellation_bpsk ();
00352   unsigned int decision_maker (const gr_complex *sample);
00353 
00354   friend DIGITAL_API digital_constellation_bpsk_sptr
00355   digital_make_constellation_bpsk ();
00356   
00357 };
00358 
00359 
00360 /************************************************************/
00361 /* digital_constellation_qpsk                               */
00362 /*                                                          */
00363 /* Only works for QPSK.                                     */
00364 /*                                                          */
00365 /************************************************************/
00366 
00367 class digital_constellation_qpsk;
00368 typedef boost::shared_ptr<digital_constellation_qpsk> digital_constellation_qpsk_sptr;
00369 
00370 // public constructor
00371 DIGITAL_API digital_constellation_qpsk_sptr 
00372 digital_make_constellation_qpsk ();
00373 
00374 /*! 
00375  * \brief Digital constellation for QPSK
00376  * \ingroup digital
00377  */
00378 class DIGITAL_API digital_constellation_qpsk : public digital_constellation
00379 {
00380  public:
00381 
00382   digital_constellation_qpsk ();
00383   unsigned int decision_maker (const gr_complex *sample);
00384 
00385   friend DIGITAL_API digital_constellation_qpsk_sptr
00386   digital_make_constellation_qpsk ();
00387   
00388 };
00389 
00390 
00391 /************************************************************/
00392 /* digital_constellation_dqpsk                              */
00393 /*                                                          */
00394 /* Works with differential encoding; slower decisions.      */
00395 /*                                                          */
00396 /************************************************************/
00397 
00398 class digital_constellation_dqpsk;
00399 typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
00400 
00401 // public constructor
00402 DIGITAL_API digital_constellation_dqpsk_sptr 
00403 digital_make_constellation_dqpsk ();
00404 
00405 /*!
00406  * \brief Digital constellation for DQPSK
00407  * \ingroup digital
00408  */
00409 class DIGITAL_API digital_constellation_dqpsk : public digital_constellation
00410 {
00411  public:
00412 
00413   digital_constellation_dqpsk ();
00414   unsigned int decision_maker (const gr_complex *sample);
00415 
00416   friend DIGITAL_API digital_constellation_dqpsk_sptr
00417   digital_make_constellation_dqpsk ();
00418   
00419 };
00420 
00421 
00422 /************************************************************/
00423 /* digital_constellation_8psk                               */
00424 /*                                                          */
00425 /* Only works for 8PSK.                                     */
00426 /*                                                          */
00427 /************************************************************/
00428 
00429 class digital_constellation_8psk;
00430 typedef boost::shared_ptr<digital_constellation_8psk> digital_constellation_8psk_sptr;
00431 
00432 // public constructor
00433 DIGITAL_API digital_constellation_8psk_sptr 
00434 digital_make_constellation_8psk ();
00435 
00436 /*! 
00437  * \brief Digital constellation for 8PSK
00438  * \ingroup digital
00439  */
00440 class DIGITAL_API digital_constellation_8psk : public digital_constellation
00441 {
00442  public:
00443 
00444   digital_constellation_8psk ();
00445   unsigned int decision_maker (const gr_complex *sample);
00446 
00447   friend DIGITAL_API digital_constellation_8psk_sptr
00448   digital_make_constellation_8psk ();
00449   
00450 };
00451 
00452 #endif