GNU Radio 3.6.5 C++ API
|
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