GNU Radio Manual and C++ API Reference  3.7.9.2
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
constellation.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2010-2012 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 <gnuradio/digital/api.h>
28 #include <boost/enable_shared_from_this.hpp>
29 #include <boost/any.hpp>
30 #include <gnuradio/gr_complex.h>
31 #include <pmt/pmt.h>
32 #include <vector>
33 
34 namespace gr {
35  namespace digital {
36 
37  /************************************************************/
38  /* constellation */
39  /* */
40  /* Base class defining interface. */
41  /************************************************************/
42 
43  class constellation;
44  typedef boost::shared_ptr<constellation> constellation_sptr;
45 
46  /*!
47  * \brief An abstracted constellation object
48  * \ingroup symbol_coding_blk
49  *
50  * \details
51  * The constellation objects hold the necessary information to pass
52  * around constellation information for modulators and
53  * demodulators. These objects contain the mapping between the bits
54  * and the constellation points used to represent them as well as
55  * methods for slicing the symbol space. Various implementations are
56  * possible for efficiency and ease of use.
57  *
58  * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
59  * from this class and overloaded to perform optimized slicing and
60  * constellation mappings.
61  */
63  : public boost::enable_shared_from_this<constellation>
64  {
65  public:
66  constellation(std::vector<gr_complex> constell,
67  std::vector<int> pre_diff_code,
68  unsigned int rotational_symmetry,
69  unsigned int dimensionality);
70  constellation();
71  virtual ~constellation();
72 
73  //! Returns the constellation points for a symbol value
74  void map_to_points(unsigned int value, gr_complex *points);
75  std::vector<gr_complex> map_to_points_v(unsigned int value);
76 
77  //! Returns the constellation point that matches best.
78  virtual unsigned int decision_maker(const gr_complex *sample) = 0;
79  //! Takes a vector rather than a pointer. Better for SWIG wrapping.
80  unsigned int decision_maker_v(std::vector<gr_complex> sample);
81  //! Also calculates the phase error.
82  unsigned int decision_maker_pe(const gr_complex *sample, float *phase_error);
83  //! Calculates distance.
84  //unsigned int decision_maker_e(const gr_complex *sample, float *error);
85 
86  //! Calculates metrics for all points in the constellation.
87  //! For use with the viterbi algorithm.
88  virtual void calc_metric(const gr_complex *sample, float *metric, gr::digital::trellis_metric_type_t type);
89  virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
90  virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
91 
92  //! Returns the set of points in this constellation.
93  std::vector<gr_complex> points() { return d_constellation;}
94  //! Returns the vector of points in this constellation.
95  //! Raise error if dimensionality is not one.
96  std::vector<gr_complex> s_points();
97  //! Returns a vector of vectors of points.
98  std::vector<std::vector<gr_complex> > v_points();
99  //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
100  bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
101  //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
102  void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
103  //! Returns the encoding to apply before differential encoding.
104  std::vector<int> pre_diff_code() { return d_pre_diff_code;}
105  //! Returns the order of rotational symmetry.
106  unsigned int rotational_symmetry() { return d_rotational_symmetry;}
107  //! Returns the number of complex numbers in a single symbol.
108  unsigned int dimensionality() {return d_dimensionality;}
109 
110  unsigned int bits_per_symbol()
111  {
112  return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
113  }
114 
115  unsigned int arity()
116  {
117  return d_arity;
118  }
119 
120  constellation_sptr base()
121  {
122  return shared_from_this();
123  }
124 
126  {
127  return pmt::make_any(boost::any(base()));
128  }
129 
130  /*! \brief Generates the soft decision LUT based on
131  * constellation and symbol map.
132  *
133  * \details Generates the soft decision LUT based on
134  * constellation and symbol map. It can be given a estimate of
135  * the noise power in the channel as \p npwr.
136  *
137  * \param precision Number of bits of precision on each axis.
138  * \param npwr Estimate of the noise power (if known).
139  *
140  * This is expensive to compute.
141  */
142  void gen_soft_dec_lut(int precision, float npwr=1.0);
143 
144  /*! \brief Calculate soft decisions for the given \p sample.
145  *
146  * \details Calculate the soft decisions from the given \p sample
147  * at the given noise power \p npwr.
148  *
149  * This is a very costly algorithm (especially for higher order
150  * modulations) and should be used sparingly. It uses the
151  * #gen_soft_dec_lut function to generate the LUT, which
152  * should be done once or if a large change in the noise floor
153  * is detected.
154  *
155  * Instead of using this function, generate the LUT using the
156  * #gen_soft_dec_lut after creating the constellation object
157  * and then use the #soft_decision_maker function to return the
158  * answer from the LUT.
159  *
160  * \param sample The complex sample to get the soft decisions.
161  * \param npwr Estimate of the noise power (if known).
162  */
163  virtual std::vector<float> calc_soft_dec(gr_complex sample, float npwr=1.0);
164 
165  /*! \brief Define a soft decision look-up table.
166  *
167  * \details Define a soft decision look-up table (LUT). Because
168  * soft decisions can be calculated in various ways with various
169  * levels of accuracy and complexity, this function allows
170  * users to create a LUT in their own way.
171  *
172  * Setting the LUT here means that #has_soft_dec_lut will return
173  * true. Decision vectors returned by #soft_decision_maker will
174  * be calculated using this LUT.
175  *
176  * \param soft_dec_lut The soft decision LUT as a vector of
177  * tuples (vectors in C++) of soft decisions. Each
178  * element of the LUT is a vector of k-bit floats (where
179  * there are k bits/sample in the constellation).
180  * \param precision The number of bits of precision used when
181  * generating the LUT.
182  */
183  void set_soft_dec_lut(const std::vector< std::vector<float> > &soft_dec_lut,
184  int precision);
185 
186  //! Returns True if the soft decision LUT has been defined, False otherwise.
187  bool has_soft_dec_lut();
188 
189 
190  std::vector< std::vector<float> > soft_dec_lut();
191 
192 
193 
194  /*! \brief Returns the soft decisions for the given \p sample.
195  *
196  * \details Returns the soft decisions for the given \p
197  * sample. If a LUT is defined for the object, the decisions
198  * will be calculated from there. Otherwise, this function will
199  * call calc_soft_dec directly to calculate the soft decisions.
200  *
201  * \param sample The complex sample to get the soft decisions.
202  */
203  std::vector<float> soft_decision_maker(gr_complex sample);
204 
205 
206  protected:
207  std::vector<gr_complex> d_constellation;
208  std::vector<int> d_pre_diff_code;
210  unsigned int d_rotational_symmetry;
211  unsigned int d_dimensionality;
212  unsigned int d_arity;
213  //! The factor by which the user given constellation points were
214  //! scaled by to achieve an average amplitude of 1.
216  float d_re_min, d_re_max, d_im_min, d_im_max;
217 
218  std::vector< std::vector<float> > d_soft_dec_lut;
220  float d_lut_scale;
221 
222  float get_distance(unsigned int index, const gr_complex *sample);
223  unsigned int get_closest_point(const gr_complex *sample);
224  void calc_arity();
225 
226  void max_min_axes();
227  };
228 
229  /************************************************************/
230  /* constellation_calcdist */
231  /* */
232  /************************************************************/
233 
234  /*! \brief Calculate Euclidian distance for any constellation
235  * \ingroup digital
236  *
237  * \details
238  * Constellation which calculates the distance to each point in the
239  * constellation for decision making. Inefficient for large
240  * constellations.
241  */
243  : public constellation
244  {
245  public:
246  typedef boost::shared_ptr<constellation_calcdist> sptr;
247 
248  /*!
249  * Make a general constellation object that calculates the Euclidean distance for hard decisions.
250  *
251  * \param constell List of constellation points (order of list matches pre_diff_code)
252  * \param pre_diff_code List of alphabet symbols (before applying any differential
253  * coding) (order of list matches constell)
254  * \param rotational_symmetry Number of rotations around unit circle that have the same representation.
255  * \param dimensionality Number of dimensions to the constellation.
256  */
257  static sptr make(std::vector<gr_complex> constell,
258  std::vector<int> pre_diff_code,
259  unsigned int rotational_symmetry,
260  unsigned int dimensionality);
261 
262  unsigned int decision_maker(const gr_complex *sample);
263  // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
264  // void calc_euclidean_metric(gr_complex *sample, float *metric);
265  // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
266 
267  protected:
268  constellation_calcdist(std::vector<gr_complex> constell,
269  std::vector<int> pre_diff_code,
270  unsigned int rotational_symmetry,
271  unsigned int dimensionality);
272  };
273 
274 
275  /************************************************************/
276  /*! constellation_sector */
277  /************************************************************/
278 
279  /*!
280  * \brief Sectorized digital constellation
281  * \ingroup digital
282  *
283  * \details
284  * Constellation space is divided into sectors. Each sector is
285  * associated with the nearest constellation point.
286  */
288  {
289  public:
290 
291  /*!
292  * Make a sectorized constellation object.
293  *
294  * \param constell List of constellation points (order of list matches pre_diff_code)
295  * \param pre_diff_code List of alphabet symbols (before applying any differential
296  * coding) (order of list matches constell)
297  * \param rotational_symmetry Number of rotations around unit circle that have the same representation.
298  * \param dimensionality Number of z-axis dimensions to the constellation
299  * \param n_sectors Number of sectors in the constellation.
300  */
301  constellation_sector(std::vector<gr_complex> constell,
302  std::vector<int> pre_diff_code,
303  unsigned int rotational_symmetry,
304  unsigned int dimensionality,
305  unsigned int n_sectors);
306 
308 
309  unsigned int decision_maker(const gr_complex *sample);
310 
311  protected:
312  virtual unsigned int get_sector(const gr_complex *sample) = 0;
313  virtual unsigned int calc_sector_value(unsigned int sector) = 0;
314  void find_sector_values();
315 
316  unsigned int n_sectors;
317 
318  private:
319  std::vector<int> sector_values;
320  };
321 
322  /************************************************************/
323  /* constellation_rect */
324  /************************************************************/
325 
326  /*!
327  * \brief Rectangular digital constellation
328  * \ingroup digital
329  *
330  * Only implemented for 1-(complex)dimensional constellation.
331  *
332  * Constellation space is divided into rectangular sectors. Each
333  * sector is associated with the nearest constellation point.
334  *
335  * Works well for square QAM.
336  *
337  * Works for any generic constellation provided sectors are not
338  * too large.
339  */
341  : public constellation_sector
342  {
343  public:
344  typedef boost::shared_ptr<constellation_rect> sptr;
345 
346  /*!
347  * Make a rectangular constellation object.
348  *
349  * \param constell List of constellation points (order of list matches pre_diff_code)
350  * \param pre_diff_code List of alphabet symbols (before applying any differential
351  * coding) (order of list matches constell)
352  * \param rotational_symmetry Number of rotations around unit circle that have the same representation.
353  * \param real_sectors Number of sectors the real axis is split in to.
354  * \param imag_sectors Number of sectors the imag axis is split in to.
355  * \param width_real_sectors width of each real sector to calculate decision boundaries.
356  * \param width_imag_sectors width of each imag sector to calculate decision boundaries.
357  */
358  static constellation_rect::sptr make(std::vector<gr_complex> constell,
359  std::vector<int> pre_diff_code,
360  unsigned int rotational_symmetry,
361  unsigned int real_sectors,
362  unsigned int imag_sectors,
363  float width_real_sectors,
364  float width_imag_sectors);
366 
367  protected:
368 
369  constellation_rect(std::vector<gr_complex> constell,
370  std::vector<int> pre_diff_code,
371  unsigned int rotational_symmetry,
372  unsigned int real_sectors,
373  unsigned int imag_sectors,
374  float width_real_sectors,
375  float width_imag_sectors);
376 
377  unsigned int get_sector(const gr_complex *sample);
378  gr_complex calc_sector_center(unsigned int sector);
379  unsigned int calc_sector_value(unsigned int sector);
380 
381  private:
382  unsigned int n_real_sectors;
383  unsigned int n_imag_sectors;
384  float d_width_real_sectors;
385  float d_width_imag_sectors;
386  };
387 
388 
389  /************************************************************/
390  /* constellation_expl_rect */
391  /************************************************************/
392 
393  /*!
394  * \brief Rectangular digital constellation.
395  * \ingroup digital
396  *
397  * \details
398  * Only implemented for 1-(complex)dimensional constellation.
399  *
400  * Constellation space is divided into rectangular sectors. Each
401  * sector is associated with the nearest constellation point.
402  *
403  * This class is different from constellation_rect in that the
404  * mapping from sector to constellation point is explicitly passed
405  * into the constructor as sector_values. Usually we do not need
406  * this, since we want each sector to be automatically mapped to
407  * the closest constellation point, however sometimes it's nice to
408  * have the flexibility.
409  */
411  : public constellation_rect
412  {
413  public:
414  typedef boost::shared_ptr<constellation_expl_rect> sptr;
415 
416  static sptr make(std::vector<gr_complex> constellation,
417  std::vector<int> pre_diff_code,
418  unsigned int rotational_symmetry,
419  unsigned int real_sectors,
420  unsigned int imag_sectors,
421  float width_real_sectors,
422  float width_imag_sectors,
423  std::vector<unsigned int> sector_values);
425 
426  protected:
427  constellation_expl_rect(std::vector<gr_complex> constellation,
428  std::vector<int> pre_diff_code,
429  unsigned int rotational_symmetry,
430  unsigned int real_sectors,
431  unsigned int imag_sectors,
432  float width_real_sectors,
433  float width_imag_sectors,
434  std::vector<unsigned int> sector_values);
435 
436  unsigned int calc_sector_value (unsigned int sector) {
437  return d_sector_values[sector];
438  }
439 
440  private:
441  std::vector<unsigned int> d_sector_values;
442  };
443 
444  /************************************************************/
445  /* constellation_psk */
446  /************************************************************/
447 
448  /*!
449  * \brief constellation_psk
450  * \ingroup digital
451  *
452  * Constellation space is divided into pie slices sectors.
453  *
454  * Each slice is associated with the nearest constellation point.
455  *
456  * Works well for PSK but nothing else.
457  *
458  * Assumes that there is a constellation point at 1.x
459  */
461  {
462  public:
463  typedef boost::shared_ptr<constellation_psk> sptr;
464 
465  // public constructor
466  static sptr make(std::vector<gr_complex> constell,
467  std::vector<int> pre_diff_code,
468  unsigned int n_sectors);
469 
471 
472  protected:
473  unsigned int get_sector(const gr_complex *sample);
474 
475  unsigned int calc_sector_value(unsigned int sector);
476 
477  constellation_psk(std::vector<gr_complex> constell,
478  std::vector<int> pre_diff_code,
479  unsigned int n_sectors);
480  };
481 
482 
483  /************************************************************/
484  /* constellation_bpsk */
485  /* */
486  /* Only works for BPSK. */
487  /* */
488  /************************************************************/
489 
490  /*!
491  * \brief Digital constellation for BPSK .
492  * \ingroup digital
493  *
494  * \details
495  * \verbatim
496  0 | 1
497  \endverbatim
498  */
500  {
501  public:
502  typedef boost::shared_ptr<constellation_bpsk> sptr;
503 
504  // public constructor
505  static sptr make();
506 
508 
509  unsigned int decision_maker(const gr_complex *sample);
510 
511  protected:
513  };
514 
515 
516  /************************************************************/
517  /* constellation_qpsk */
518  /* */
519  /* Only works for QPSK. */
520  /* */
521  /************************************************************/
522 
523  /*!
524  * \brief Digital constellation for QPSK
525  * \ingroup digital
526  *
527  * \details
528  * \verbatim
529  01 | 11
530  -------
531  00 | 10
532  \endverbatim
533  */
535  {
536  public:
537  typedef boost::shared_ptr<constellation_qpsk> sptr;
538 
539  // public constructor
540  static sptr make();
541 
543 
544  unsigned int decision_maker(const gr_complex *sample);
545 
546  protected:
548  };
549 
550 
551  /************************************************************/
552  /* constellation_dqpsk */
553  /* */
554  /* Works with differential encoding; slower decisions. */
555  /* */
556  /************************************************************/
557 
558  /*!
559  * \brief Digital constellation for DQPSK.
560  * \ingroup digital
561  *
562  * \details
563  * \verbatim
564  01 | 00
565  -------
566  11 | 10
567  \endverbatim
568  */
570  {
571  public:
572  typedef boost::shared_ptr<constellation_dqpsk> sptr;
573 
574  // public constructor
575  static sptr make();
576 
578 
579  unsigned int decision_maker(const gr_complex *sample);
580 
581  protected:
583  };
584 
585 
586  /************************************************************/
587  /* constellation_8psk */
588  /* */
589  /* Only works for 8PSK. */
590  /* */
591  /************************************************************/
592 
593  /*!
594  * \brief Digital constellation for 8PSK.
595  * \ingroup digital
596  *
597  * \details
598  * \verbatim
599  101 | 100
600  001 | 000
601  -----------------
602  011 | 010
603  111 | 110
604  \endverbatim
605  */
607  {
608  public:
609  typedef boost::shared_ptr<constellation_8psk> sptr;
610 
611  // public constructor
612  static sptr make();
613 
615 
616  unsigned int decision_maker(const gr_complex *sample);
617 
618  protected:
620  };
621 
622  /************************************************************/
623  /* constellation_8psk_natural */
624  /* */
625  /* Only works for natural 8psk */
626  /* */
627  /************************************************************/
628 
629  /*!
630  * \brief Digital constellation for natually mapped 8PSK.
631  * \ingroup digital
632  *
633  * \details
634  * \verbatim
635  011 | 010
636  100 | 001
637  -----------------
638  101 | 000
639  110 | 111
640  \endverbatim
641  */
643  {
644  public:
645  typedef boost::shared_ptr<constellation_8psk_natural> sptr;
646 
647  // public constructor
648  static sptr make();
649 
651 
652  unsigned int decision_maker(const gr_complex *sample);
653 
654  protected:
656  };
657 
658  /************************************************************/
659  /* constellation_16qam */
660  /* */
661  /* the 16qam mapping used in set partition of tcm */
662  /* */
663  /************************************************************/
664 
665  /*!
666  * \brief Digital constellation for 16qam.
667  * \ingroup digital
668  *
669  * \details
670  * \verbatim
671  1000 1101 | 1100 1001
672  |
673  1111 1010 | 1011 1110
674  -----------------
675  0100 0001 | 0000 0101
676  |
677  0011 0110 | 0111 0010
678  \endverbatim
679  */
681  {
682  public:
683  typedef boost::shared_ptr<constellation_16qam> sptr;
684 
685  // public constructor
686  static sptr make();
687 
689 
690  unsigned int decision_maker(const gr_complex *sample);
691 
692  protected:
694  };
695 
696  } /* namespace digital */
697 } /* namespace gr */
698 
699 #endif /* INCLUDED_DIGITAL_CONSTELLATION_H */
int d_lut_precision
Definition: constellation.h:219
boost::shared_ptr< constellation_psk > sptr
Definition: constellation.h:463
boost::shared_ptr< constellation_dqpsk > sptr
Definition: constellation.h:572
Digital constellation for 16qam.
Definition: constellation.h:680
float d_scalefactor
The factor by which the user given constellation points were scaled by to achieve an average amplitud...
Definition: constellation.h:215
unsigned int bits_per_symbol()
Definition: constellation.h:110
constellation_pskConstellation space is divided into pie slices sectors.
Definition: constellation.h:460
Digital constellation for DQPSK.
Definition: constellation.h:569
constellation_sptr base()
Definition: constellation.h:120
trellis_metric_type_t
Definition: metric_type.h:29
An abstracted constellation object.
Definition: constellation.h:62
#define DIGITAL_API
Definition: gr-digital/include/gnuradio/digital/api.h:30
std::vector< gr_complex > points()
Returns the set of points in this constellation.
Definition: constellation.h:93
boost::shared_ptr< constellation_bpsk > sptr
Definition: constellation.h:502
Rectangular digital constellation.
Definition: constellation.h:410
Digital constellation for BPSK .
Definition: constellation.h:499
std::vector< std::vector< float > > d_soft_dec_lut
Definition: constellation.h:218
Digital constellation for natually mapped 8PSK.
Definition: constellation.h:642
unsigned int dimensionality()
Returns the number of complex numbers in a single symbol.
Definition: constellation.h:108
boost::shared_ptr< constellation_16qam > sptr
Definition: constellation.h:683
std::complex< float > gr_complex
Definition: gr_complex.h:27
std::vector< gr_complex > d_constellation
Definition: constellation.h:207
void calc_metric(int O, int D, const std::vector< T > &TABLE, const T *input, float *metric, digital::trellis_metric_type_t type)
Sectorized digital constellation.
Definition: constellation.h:287
Include this header to use the message passing features.
Definition: logger.h:131
std::vector< int > d_pre_diff_code
Definition: constellation.h:208
void set_pre_diff_code(bool a)
Whether to apply an encoding before doing differential encoding. (e.g. gray coding) ...
Definition: constellation.h:102
float d_lut_scale
Definition: constellation.h:220
Digital constellation for QPSK.
Definition: constellation.h:534
boost::shared_ptr< constellation_expl_rect > sptr
Definition: constellation.h:414
unsigned int d_arity
Definition: constellation.h:212
boost::shared_ptr< constellation_8psk > sptr
Definition: constellation.h:609
unsigned int calc_sector_value(unsigned int sector)
Definition: constellation.h:436
float d_re_min
Definition: constellation.h:216
boost::shared_ptr< constellation_8psk_natural > sptr
Definition: constellation.h:645
unsigned int arity()
Definition: constellation.h:115
Calculate Euclidian distance for any constellation.
Definition: constellation.h:242
std::vector< int > pre_diff_code()
Returns the encoding to apply before differential encoding.
Definition: constellation.h:104
pmt::pmt_t as_pmt()
Definition: constellation.h:125
PMT_API pmt_t make_any(const boost::any &any)
make an any
bool apply_pre_diff_code()
Whether to apply an encoding before doing differential encoding. (e.g. gray coding) ...
Definition: constellation.h:100
boost::shared_ptr< constellation_rect > sptr
Definition: constellation.h:344
unsigned int n_sectors
Definition: constellation.h:316
boost::intrusive_ptr< pmt_base > pmt_t
typedef for shared pointer (transparent reference counting). See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
Definition: pmt.h:56
boost::shared_ptr< constellation_calcdist > sptr
Definition: constellation.h:246
Rectangular digital constellationOnly implemented for 1-(complex)dimensional constellation.
Definition: constellation.h:340
bool d_apply_pre_diff_code
Definition: constellation.h:209
Digital constellation for 8PSK.
Definition: constellation.h:606
unsigned int d_dimensionality
Definition: constellation.h:211
unsigned int d_rotational_symmetry
Definition: constellation.h:210
unsigned int rotational_symmetry()
Returns the order of rotational symmetry.
Definition: constellation.h:106
boost::shared_ptr< constellation_qpsk > sptr
Definition: constellation.h:537