GNU Radio 3.7.1 C++ API
|
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 */