GNU Radio 3.7.0 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 // public constructor 00158 static sptr make(std::vector<gr_complex> constell, 00159 std::vector<int> pre_diff_code, 00160 unsigned int rotational_symmetry, 00161 unsigned int dimensionality); 00162 00163 unsigned int decision_maker(const gr_complex *sample); 00164 // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type); 00165 // void calc_euclidean_metric(gr_complex *sample, float *metric); 00166 // void calc_hard_symbol_metric(gr_complex *sample, float *metric); 00167 00168 protected: 00169 constellation_calcdist(std::vector<gr_complex> constell, 00170 std::vector<int> pre_diff_code, 00171 unsigned int rotational_symmetry, 00172 unsigned int dimensionality); 00173 }; 00174 00175 00176 /************************************************************/ 00177 /*! constellation_sector */ 00178 /************************************************************/ 00179 00180 /*! 00181 * \brief Sectorized digital constellation 00182 * \ingroup digital 00183 * 00184 * Constellation space is divided into sectors. Each sector is 00185 * associated with the nearest constellation point. 00186 * 00187 */ 00188 class DIGITAL_API constellation_sector : public constellation 00189 { 00190 public: 00191 00192 constellation_sector(std::vector<gr_complex> constell, 00193 std::vector<int> pre_diff_code, 00194 unsigned int rotational_symmetry, 00195 unsigned int dimensionality, 00196 unsigned int n_sectors); 00197 00198 ~constellation_sector(); 00199 00200 unsigned int decision_maker(const gr_complex *sample); 00201 00202 protected: 00203 virtual unsigned int get_sector(const gr_complex *sample) = 0; 00204 virtual unsigned int calc_sector_value(unsigned int sector) = 0; 00205 void find_sector_values(); 00206 00207 unsigned int n_sectors; 00208 00209 private: 00210 std::vector<int> sector_values; 00211 }; 00212 00213 /************************************************************/ 00214 /* 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 00229 * too large. 00230 */ 00231 00232 00233 class DIGITAL_API constellation_rect 00234 : public constellation_sector 00235 { 00236 public: 00237 typedef boost::shared_ptr<constellation_rect> sptr; 00238 00239 // public constructor 00240 static constellation_rect::sptr make(std::vector<gr_complex> constell, 00241 std::vector<int> pre_diff_code, 00242 unsigned int rotational_symmetry, 00243 unsigned int real_sectors, 00244 unsigned int imag_sectors, 00245 float width_real_sectors, 00246 float width_imag_sectors); 00247 ~constellation_rect(); 00248 00249 protected: 00250 00251 constellation_rect(std::vector<gr_complex> constell, 00252 std::vector<int> pre_diff_code, 00253 unsigned int rotational_symmetry, 00254 unsigned int real_sectors, 00255 unsigned int imag_sectors, 00256 float width_real_sectors, 00257 float width_imag_sectors); 00258 00259 unsigned int get_sector(const gr_complex *sample); 00260 00261 unsigned int calc_sector_value(unsigned int sector); 00262 00263 private: 00264 unsigned int n_real_sectors; 00265 unsigned int n_imag_sectors; 00266 float d_width_real_sectors; 00267 float d_width_imag_sectors; 00268 }; 00269 00270 00271 /************************************************************/ 00272 /* constellation_expl_rect */ 00273 /************************************************************/ 00274 00275 /*! 00276 * \brief Rectangular digital constellation 00277 * \ingroup digital 00278 * 00279 * Only implemented for 1-(complex)dimensional constellation. 00280 * 00281 * Constellation space is divided into rectangular sectors. Each 00282 * sector is associated with the nearest constellation point. 00283 * 00284 * This class is different from constellation_rect in that the 00285 * mapping from sector to constellation point is explicitly passed 00286 * into the constructor as sector_values. Usually we do not need 00287 * this, since we want each sector to be automatically mapped to 00288 * the closest constellation point, however sometimes it's nice to 00289 * have the flexibility. 00290 */ 00291 class DIGITAL_API constellation_expl_rect 00292 : public constellation_rect 00293 { 00294 public: 00295 typedef boost::shared_ptr<constellation_expl_rect> sptr; 00296 00297 static sptr make(std::vector<gr_complex> constellation, 00298 std::vector<int> pre_diff_code, 00299 unsigned int rotational_symmetry, 00300 unsigned int real_sectors, 00301 unsigned int imag_sectors, 00302 float width_real_sectors, 00303 float width_imag_sectors, 00304 std::vector<unsigned int> sector_values); 00305 ~constellation_expl_rect(); 00306 00307 protected: 00308 constellation_expl_rect(std::vector<gr_complex> constellation, 00309 std::vector<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 unsigned int calc_sector_value (unsigned int sector) { 00318 return d_sector_values[sector]; 00319 } 00320 00321 private: 00322 std::vector<unsigned int> d_sector_values; 00323 }; 00324 00325 /************************************************************/ 00326 /* constellation_psk */ 00327 /************************************************************/ 00328 00329 /*! 00330 * \brief constellation_psk 00331 * \ingroup digital 00332 * 00333 * Constellation space is divided into pie slices sectors. 00334 * 00335 * Each slice is associated with the nearest constellation point. 00336 * 00337 * Works well for PSK but nothing else. 00338 * 00339 * Assumes that there is a constellation point at 1.x 00340 */ 00341 class DIGITAL_API constellation_psk : public constellation_sector 00342 { 00343 public: 00344 typedef boost::shared_ptr<constellation_psk> sptr; 00345 00346 // public constructor 00347 static sptr make(std::vector<gr_complex> constell, 00348 std::vector<int> pre_diff_code, 00349 unsigned int n_sectors); 00350 00351 ~constellation_psk(); 00352 00353 protected: 00354 unsigned int get_sector(const gr_complex *sample); 00355 00356 unsigned int calc_sector_value(unsigned int sector); 00357 00358 constellation_psk(std::vector<gr_complex> constell, 00359 std::vector<int> pre_diff_code, 00360 unsigned int n_sectors); 00361 }; 00362 00363 00364 /************************************************************/ 00365 /* constellation_bpsk */ 00366 /* */ 00367 /* Only works for BPSK. */ 00368 /* */ 00369 /************************************************************/ 00370 00371 /*! 00372 * \brief Digital constellation for BPSK 00373 * \ingroup digital 00374 */ 00375 class DIGITAL_API constellation_bpsk : public constellation 00376 { 00377 public: 00378 typedef boost::shared_ptr<constellation_bpsk> sptr; 00379 00380 // public constructor 00381 static sptr make(); 00382 00383 ~constellation_bpsk(); 00384 00385 unsigned int decision_maker(const gr_complex *sample); 00386 00387 protected: 00388 constellation_bpsk(); 00389 }; 00390 00391 00392 /************************************************************/ 00393 /* constellation_qpsk */ 00394 /* */ 00395 /* Only works for QPSK. */ 00396 /* */ 00397 /************************************************************/ 00398 00399 /*! 00400 * \brief Digital constellation for QPSK 00401 * \ingroup digital 00402 */ 00403 class DIGITAL_API constellation_qpsk : public constellation 00404 { 00405 public: 00406 typedef boost::shared_ptr<constellation_qpsk> sptr; 00407 00408 // public constructor 00409 static sptr make(); 00410 00411 ~constellation_qpsk(); 00412 00413 unsigned int decision_maker(const gr_complex *sample); 00414 00415 protected: 00416 constellation_qpsk(); 00417 }; 00418 00419 00420 /************************************************************/ 00421 /* constellation_dqpsk */ 00422 /* */ 00423 /* Works with differential encoding; slower decisions. */ 00424 /* */ 00425 /************************************************************/ 00426 00427 /*! 00428 * \brief Digital constellation for DQPSK 00429 * \ingroup digital 00430 */ 00431 class DIGITAL_API constellation_dqpsk : public constellation 00432 { 00433 public: 00434 typedef boost::shared_ptr<constellation_dqpsk> sptr; 00435 00436 // public constructor 00437 static sptr make(); 00438 00439 ~constellation_dqpsk(); 00440 00441 unsigned int decision_maker(const gr_complex *sample); 00442 00443 protected: 00444 constellation_dqpsk(); 00445 }; 00446 00447 00448 /************************************************************/ 00449 /* constellation_8psk */ 00450 /* */ 00451 /* Only works for 8PSK. */ 00452 /* */ 00453 /************************************************************/ 00454 00455 /*! 00456 * \brief Digital constellation for 8PSK 00457 * \ingroup digital 00458 */ 00459 class DIGITAL_API constellation_8psk : public constellation 00460 { 00461 public: 00462 typedef boost::shared_ptr<constellation_8psk> sptr; 00463 00464 // public constructor 00465 static sptr make(); 00466 00467 ~constellation_8psk(); 00468 00469 unsigned int decision_maker(const gr_complex *sample); 00470 00471 protected: 00472 constellation_8psk(); 00473 }; 00474 00475 } /* namespace digital */ 00476 } /* namespace gr */ 00477 00478 #endif /* INCLUDED_DIGITAL_CONSTELLATION_H */