root / gr-digital / include / digital_constellation.h @ aea83c80
History | View | Annotate | Download (14.4 kB)
| 1 | /* -*- c++ -*- */
|
|---|---|
| 2 | /*
|
| 3 | * Copyright 2010, 2011 Free Software Foundation, Inc. |
| 4 | * |
| 5 | * This file is part of GNU Radio |
| 6 | * |
| 7 | * GNU Radio is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 3, or (at your option) |
| 10 | * any later version. |
| 11 | * |
| 12 | * GNU Radio is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License |
| 18 | * along with GNU Radio; see the file COPYING. If not, write to |
| 19 | * the Free Software Foundation, Inc., 51 Franklin Street, |
| 20 | * Boston, MA 02110-1301, USA. |
| 21 | */ |
| 22 | |
| 23 | #ifndef INCLUDED_DIGITAL_CONSTELLATION_H
|
| 24 | #define INCLUDED_DIGITAL_CONSTELLATION_H
|
| 25 | |
| 26 | #include <vector> |
| 27 | #include <math.h> |
| 28 | #include <gr_complex.h> |
| 29 | #include <boost/enable_shared_from_this.hpp> |
| 30 | #include <digital_metric_type.h> |
| 31 | |
| 32 | /************************************************************/
|
| 33 | /* digital_constellation */
|
| 34 | /* */
|
| 35 | /* Base class defining interface. */
|
| 36 | /************************************************************/
|
| 37 | |
| 38 | class digital_constellation; |
| 39 | typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr;
|
| 40 | |
| 41 | /*!
|
| 42 | * \brief An abstracted constellation object |
| 43 | * \ingroup digital |
| 44 | * |
| 45 | * The constellation objects hold the necessary information to pass |
| 46 | * around constellation information for modulators and |
| 47 | * demodulators. These objects contain the mapping between the bits |
| 48 | * and the constellation points used to represent them as well as |
| 49 | * methods for slicing the symbol space. Various implementations are |
| 50 | * possible for efficiency and ease of use. |
| 51 | * |
| 52 | * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited |
| 53 | * from this class and overloaded to perform optimized slicing and |
| 54 | * constellation mappings. |
| 55 | */ |
| 56 | class digital_constellation : public boost::enable_shared_from_this<digital_constellation> |
| 57 | {
|
| 58 | public:
|
| 59 | digital_constellation (std::vector<gr_complex> constellation, |
| 60 | std::vector<unsigned int> pre_diff_code, |
| 61 | unsigned int rotational_symmetry, |
| 62 | unsigned int dimensionality); |
| 63 | digital_constellation (); |
| 64 | |
| 65 | //! Returns the constellation points for a symbol value
|
| 66 | void map_to_points(unsigned int value, gr_complex *points); |
| 67 | std::vector<gr_complex> map_to_points_v(unsigned int value); |
| 68 | |
| 69 | //! Returns the constellation point that matches best.
|
| 70 | virtual unsigned int decision_maker (const gr_complex *sample) = 0; |
| 71 | //! Takes a vector rather than a pointer. Better for SWIG wrapping.
|
| 72 | unsigned int decision_maker_v (std::vector<gr_complex> sample); |
| 73 | //! Also calculates the phase error.
|
| 74 | unsigned int decision_maker_pe (const gr_complex *sample, float *phase_error); |
| 75 | //! Calculates distance.
|
| 76 | unsigned int decision_maker_e (const gr_complex *sample, float *error); |
| 77 | |
| 78 | //! Calculates metrics for all points in the constellation.
|
| 79 | //! For use with the viterbi algorithm.
|
| 80 | virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type); |
| 81 | virtual void calc_euclidean_metric(const gr_complex *sample, float *metric); |
| 82 | virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric); |
| 83 | |
| 84 | //! Returns the set of points in this constellation.
|
| 85 | std::vector<gr_complex> points() { return d_constellation;}
|
| 86 | //! Returns the vector of points in this constellation.
|
| 87 | //! Raise error if dimensionality is not one.
|
| 88 | std::vector<gr_complex> s_points(); |
| 89 | //! Returns a vector of vectors of points.
|
| 90 | std::vector<std::vector<gr_complex> > v_points(); |
| 91 | //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
|
| 92 | bool apply_pre_diff_code() { return d_apply_pre_diff_code;} |
| 93 | //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
|
| 94 | void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;} |
| 95 | //! Returns the encoding to apply before differential encoding.
|
| 96 | std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;} |
| 97 | //! Returns the order of rotational symmetry.
|
| 98 | unsigned int rotational_symmetry() { return d_rotational_symmetry;} |
| 99 | //! Returns the number of complex numbers in a single symbol.
|
| 100 | unsigned int dimensionality() {return d_dimensionality;} |
| 101 | |
| 102 | unsigned int bits_per_symbol () { |
| 103 | return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0)); |
| 104 | } |
| 105 | |
| 106 | unsigned int arity () { |
| 107 | return d_arity;
|
| 108 | } |
| 109 | |
| 110 | digital_constellation_sptr base() {
|
| 111 | return shared_from_this();
|
| 112 | } |
| 113 | |
| 114 | protected:
|
| 115 | |
| 116 | std::vector<gr_complex> d_constellation; |
| 117 | std::vector<unsigned int> d_pre_diff_code; |
| 118 | bool d_apply_pre_diff_code;
|
| 119 | unsigned int d_rotational_symmetry; |
| 120 | unsigned int d_dimensionality; |
| 121 | unsigned int d_arity; |
| 122 | |
| 123 | float get_distance(unsigned int index, const gr_complex *sample); |
| 124 | unsigned int get_closest_point(const gr_complex *sample); |
| 125 | void calc_arity ();
|
| 126 | }; |
| 127 | |
| 128 | /************************************************************/
|
| 129 | /* digital_constellation_calcdist */
|
| 130 | /* */
|
| 131 | /************************************************************/
|
| 132 | |
| 133 | class digital_constellation_calcdist; |
| 134 | typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_calcdist_sptr;
|
| 135 | |
| 136 | // public constructor
|
| 137 | digital_constellation_calcdist_sptr |
| 138 | digital_make_constellation_calcdist (std::vector<gr_complex> constellation, |
| 139 | std::vector<unsigned int> pre_diff_code, |
| 140 | unsigned int rotational_symmetry, |
| 141 | unsigned int dimensionality); |
| 142 | |
| 143 | |
| 144 | /*! \brief Calculate Euclidian distance for any constellation
|
| 145 | * \ingroup digital |
| 146 | * |
| 147 | * Constellation which calculates the distance to each point in the |
| 148 | * constellation for decision making. Inefficient for large |
| 149 | * constellations. |
| 150 | */ |
| 151 | class digital_constellation_calcdist : public digital_constellation |
| 152 | {
|
| 153 | public:
|
| 154 | digital_constellation_calcdist (std::vector<gr_complex> constellation, |
| 155 | std::vector<unsigned int> pre_diff_code, |
| 156 | unsigned int rotational_symmetry, |
| 157 | unsigned int dimensionality); |
| 158 | unsigned int decision_maker (const gr_complex *sample); |
| 159 | // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
|
| 160 | // void calc_euclidean_metric(gr_complex *sample, float *metric);
|
| 161 | // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
|
| 162 | |
| 163 | private:
|
| 164 | friend digital_constellation_calcdist_sptr |
| 165 | digital_make_constellation_calcdist (std::vector<gr_complex> constellation); |
| 166 | }; |
| 167 | |
| 168 | |
| 169 | /************************************************************/
|
| 170 | /*! digital_constellation_sector */
|
| 171 | /************************************************************/
|
| 172 | |
| 173 | /*!
|
| 174 | * \brief Sectorized digital constellation |
| 175 | * \ingroup digital |
| 176 | * |
| 177 | * Constellation space is divided into sectors. Each sector is |
| 178 | * associated with the nearest constellation point. |
| 179 | * |
| 180 | */ |
| 181 | class digital_constellation_sector : public digital_constellation |
| 182 | {
|
| 183 | public:
|
| 184 | |
| 185 | digital_constellation_sector (std::vector<gr_complex> constellation, |
| 186 | std::vector<unsigned int> pre_diff_code, |
| 187 | unsigned int rotational_symmetry, |
| 188 | unsigned int dimensionality, |
| 189 | unsigned int n_sectors); |
| 190 | |
| 191 | unsigned int decision_maker (const gr_complex *sample); |
| 192 | |
| 193 | protected:
|
| 194 | |
| 195 | virtual unsigned int get_sector (const gr_complex *sample) = 0; |
| 196 | virtual unsigned int calc_sector_value (unsigned int sector) = 0; |
| 197 | void find_sector_values ();
|
| 198 | |
| 199 | unsigned int n_sectors; |
| 200 | |
| 201 | private:
|
| 202 | |
| 203 | std::vector<unsigned int> sector_values; |
| 204 | |
| 205 | }; |
| 206 | |
| 207 | /************************************************************/
|
| 208 | /* digital_constellation_rect */
|
| 209 | /************************************************************/
|
| 210 | |
| 211 | /*!
|
| 212 | * \brief Rectangular digital constellation |
| 213 | * \ingroup digital |
| 214 | * |
| 215 | * Only implemented for 1-(complex)dimensional constellation. |
| 216 | * |
| 217 | * Constellation space is divided into rectangular sectors. Each |
| 218 | * sector is associated with the nearest constellation point. |
| 219 | * |
| 220 | * Works well for square QAM. |
| 221 | * |
| 222 | * Works for any generic constellation provided sectors are not too |
| 223 | * large. |
| 224 | */ |
| 225 | |
| 226 | class digital_constellation_rect; |
| 227 | typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect_sptr;
|
| 228 | |
| 229 | // public constructor
|
| 230 | digital_constellation_rect_sptr |
| 231 | digital_make_constellation_rect (std::vector<gr_complex> constellation, |
| 232 | std::vector<unsigned int> pre_diff_code, |
| 233 | unsigned int rotational_symmetry, |
| 234 | unsigned int real_sectors, |
| 235 | unsigned int imag_sectors, |
| 236 | float width_real_sectors,
|
| 237 | float width_imag_sectors);
|
| 238 | |
| 239 | class digital_constellation_rect : public digital_constellation_sector |
| 240 | {
|
| 241 | public:
|
| 242 | |
| 243 | digital_constellation_rect (std::vector<gr_complex> constellation, |
| 244 | std::vector<unsigned int> pre_diff_code, |
| 245 | unsigned int rotational_symmetry, |
| 246 | unsigned int real_sectors, |
| 247 | unsigned int imag_sectors, |
| 248 | float width_real_sectors,
|
| 249 | float width_imag_sectors);
|
| 250 | |
| 251 | protected:
|
| 252 | |
| 253 | unsigned int get_sector (const gr_complex *sample); |
| 254 | |
| 255 | unsigned int calc_sector_value (unsigned int sector); |
| 256 | |
| 257 | private:
|
| 258 | |
| 259 | unsigned int n_real_sectors; |
| 260 | unsigned int n_imag_sectors; |
| 261 | float d_width_real_sectors;
|
| 262 | float d_width_imag_sectors;
|
| 263 | |
| 264 | friend digital_constellation_rect_sptr |
| 265 | digital_make_constellation_rect (std::vector<gr_complex> constellation, |
| 266 | std::vector<unsigned int> pre_diff_code, |
| 267 | unsigned int rotational_symmetry, |
| 268 | unsigned int real_sectors, |
| 269 | unsigned int imag_sectors, |
| 270 | float width_real_sectors,
|
| 271 | float width_imag_sectors);
|
| 272 | |
| 273 | }; |
| 274 | |
| 275 | |
| 276 | /************************************************************/
|
| 277 | /* digital_constellation_psk */
|
| 278 | /************************************************************/
|
| 279 | |
| 280 | class digital_constellation_psk; |
| 281 | typedef boost::shared_ptr<digital_constellation_psk> digital_constellation_psk_sptr;
|
| 282 | |
| 283 | // public constructor
|
| 284 | digital_constellation_psk_sptr |
| 285 | digital_make_constellation_psk (std::vector<gr_complex> constellation, |
| 286 | std::vector<unsigned int> pre_diff_code, |
| 287 | unsigned int n_sectors); |
| 288 | |
| 289 | /*!
|
| 290 | * \brief digital_constellation_psk |
| 291 | * \ingroup digital |
| 292 | * |
| 293 | * Constellation space is divided into pie slices sectors. |
| 294 | * |
| 295 | * Each slice is associated with the nearest constellation point. |
| 296 | * |
| 297 | * Works well for PSK but nothing else. |
| 298 | * |
| 299 | * Assumes that there is a constellation point at 1.x |
| 300 | */ |
| 301 | class digital_constellation_psk : public digital_constellation_sector |
| 302 | {
|
| 303 | public:
|
| 304 | |
| 305 | digital_constellation_psk (std::vector<gr_complex> constellation, |
| 306 | std::vector<unsigned int> pre_diff_code, |
| 307 | unsigned int n_sectors); |
| 308 | |
| 309 | protected:
|
| 310 | |
| 311 | unsigned int get_sector (const gr_complex *sample); |
| 312 | |
| 313 | unsigned int calc_sector_value (unsigned int sector); |
| 314 | |
| 315 | private:
|
| 316 | |
| 317 | friend digital_constellation_psk_sptr |
| 318 | digital_make_constellation_psk (std::vector<gr_complex> constellation, |
| 319 | std::vector<unsigned int> pre_diff_code, |
| 320 | unsigned int n_sectors); |
| 321 | |
| 322 | }; |
| 323 | |
| 324 | |
| 325 | /************************************************************/
|
| 326 | /* digital_constellation_bpsk */
|
| 327 | /* */
|
| 328 | /* Only works for BPSK. */
|
| 329 | /* */
|
| 330 | /************************************************************/
|
| 331 | |
| 332 | class digital_constellation_bpsk; |
| 333 | typedef boost::shared_ptr<digital_constellation_bpsk> digital_constellation_bpsk_sptr;
|
| 334 | |
| 335 | // public constructor
|
| 336 | digital_constellation_bpsk_sptr |
| 337 | digital_make_constellation_bpsk (); |
| 338 | |
| 339 | /*!
|
| 340 | * \brief Digital constellation for BPSK |
| 341 | * \ingroup digital |
| 342 | */ |
| 343 | class digital_constellation_bpsk : public digital_constellation |
| 344 | {
|
| 345 | public:
|
| 346 | |
| 347 | digital_constellation_bpsk (); |
| 348 | unsigned int decision_maker (const gr_complex *sample); |
| 349 | |
| 350 | friend digital_constellation_bpsk_sptr |
| 351 | digital_make_constellation_bpsk (); |
| 352 | |
| 353 | }; |
| 354 | |
| 355 | |
| 356 | /************************************************************/
|
| 357 | /* digital_constellation_qpsk */
|
| 358 | /* */
|
| 359 | /* Only works for QPSK. */
|
| 360 | /* */
|
| 361 | /************************************************************/
|
| 362 | |
| 363 | class digital_constellation_qpsk; |
| 364 | typedef boost::shared_ptr<digital_constellation_qpsk> digital_constellation_qpsk_sptr;
|
| 365 | |
| 366 | // public constructor
|
| 367 | digital_constellation_qpsk_sptr |
| 368 | digital_make_constellation_qpsk (); |
| 369 | |
| 370 | /*!
|
| 371 | * \brief Digital constellation for QPSK |
| 372 | * \ingroup digital |
| 373 | */ |
| 374 | class digital_constellation_qpsk : public digital_constellation |
| 375 | {
|
| 376 | public:
|
| 377 | |
| 378 | digital_constellation_qpsk (); |
| 379 | unsigned int decision_maker (const gr_complex *sample); |
| 380 | |
| 381 | friend digital_constellation_qpsk_sptr |
| 382 | digital_make_constellation_qpsk (); |
| 383 | |
| 384 | }; |
| 385 | |
| 386 | |
| 387 | /************************************************************/
|
| 388 | /* digital_constellation_dqpsk */
|
| 389 | /* */
|
| 390 | /* Works with differential encoding; slower decisions. */
|
| 391 | /* */
|
| 392 | /************************************************************/
|
| 393 | |
| 394 | class digital_constellation_dqpsk; |
| 395 | typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
|
| 396 | |
| 397 | // public constructor
|
| 398 | digital_constellation_dqpsk_sptr |
| 399 | digital_make_constellation_dqpsk (); |
| 400 | |
| 401 | /*!
|
| 402 | * \brief Digital constellation for DQPSK |
| 403 | * \ingroup digital |
| 404 | */ |
| 405 | class digital_constellation_dqpsk : public digital_constellation |
| 406 | {
|
| 407 | public:
|
| 408 | |
| 409 | digital_constellation_dqpsk (); |
| 410 | unsigned int decision_maker (const gr_complex *sample); |
| 411 | |
| 412 | friend digital_constellation_dqpsk_sptr |
| 413 | digital_make_constellation_dqpsk (); |
| 414 | |
| 415 | }; |
| 416 | |
| 417 | |
| 418 | /************************************************************/
|
| 419 | /* digital_constellation_8psk */
|
| 420 | /* */
|
| 421 | /* Only works for 8PSK. */
|
| 422 | /* */
|
| 423 | /************************************************************/
|
| 424 | |
| 425 | class digital_constellation_8psk; |
| 426 | typedef boost::shared_ptr<digital_constellation_8psk> digital_constellation_8psk_sptr;
|
| 427 | |
| 428 | // public constructor
|
| 429 | digital_constellation_8psk_sptr |
| 430 | digital_make_constellation_8psk (); |
| 431 | |
| 432 | /*!
|
| 433 | * \brief Digital constellation for 8PSK |
| 434 | * \ingroup digital |
| 435 | */ |
| 436 | class digital_constellation_8psk : public digital_constellation |
| 437 | {
|
| 438 | public:
|
| 439 | |
| 440 | digital_constellation_8psk (); |
| 441 | unsigned int decision_maker (const gr_complex *sample); |
| 442 | |
| 443 | friend digital_constellation_8psk_sptr |
| 444 | digital_make_constellation_8psk (); |
| 445 | |
| 446 | }; |
| 447 | |
| 448 | #endif
|