GNU Radio v3.6.2-149-ga6d285d9 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 //! 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