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