GNU Radio v3.7.0-113-g523a53ac C++ API
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 <gnuradio/gr_complex.h>
30 #include <vector>
31 
32 namespace gr {
33  namespace digital {
34 
35  /************************************************************/
36  /* constellation */
37  /* */
38  /* Base class defining interface. */
39  /************************************************************/
40 
41  class constellation;
42  typedef boost::shared_ptr<constellation> constellation_sptr;
43 
44  /*!
45  * \brief An abstracted constellation object
46  * \ingroup symbol_coding_blk
47  *
48  * \details
49  * The constellation objects hold the necessary information to pass
50  * around constellation information for modulators and
51  * demodulators. These objects contain the mapping between the bits
52  * and the constellation points used to represent them as well as
53  * methods for slicing the symbol space. Various implementations are
54  * possible for efficiency and ease of use.
55  *
56  * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
57  * from this class and overloaded to perform optimized slicing and
58  * constellation mappings.
59  */
61  : public boost::enable_shared_from_this<constellation>
62  {
63  public:
64  constellation(std::vector<gr_complex> constell,
65  std::vector<int> pre_diff_code,
66  unsigned int rotational_symmetry,
67  unsigned int dimensionality);
68  constellation();
69  virtual ~constellation();
70 
71  //! Returns the constellation points for a symbol value
72  void map_to_points(unsigned int value, gr_complex *points);
73  std::vector<gr_complex> map_to_points_v(unsigned int value);
74 
75  //! Returns the constellation point that matches best.
76  virtual unsigned int decision_maker(const gr_complex *sample) = 0;
77  //! Takes a vector rather than a pointer. Better for SWIG wrapping.
78  unsigned int decision_maker_v(std::vector<gr_complex> sample);
79  //! Also calculates the phase error.
80  unsigned int decision_maker_pe(const gr_complex *sample, float *phase_error);
81  //! Calculates distance.
82  //unsigned int decision_maker_e(const gr_complex *sample, float *error);
83 
84  //! Calculates metrics for all points in the constellation.
85  //! For use with the viterbi algorithm.
86  virtual void calc_metric(const gr_complex *sample, float *metric, gr::digital::trellis_metric_type_t type);
87  virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
88  virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
89 
90  //! Returns the set of points in this constellation.
91  std::vector<gr_complex> points() { return d_constellation;}
92  //! Returns the vector of points in this constellation.
93  //! Raise error if dimensionality is not one.
94  std::vector<gr_complex> s_points();
95  //! Returns a vector of vectors of points.
96  std::vector<std::vector<gr_complex> > v_points();
97  //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
98  bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
99  //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
100  void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
101  //! Returns the encoding to apply before differential encoding.
102  std::vector<int> pre_diff_code() { return d_pre_diff_code;}
103  //! Returns the order of rotational symmetry.
104  unsigned int rotational_symmetry() { return d_rotational_symmetry;}
105  //! Returns the number of complex numbers in a single symbol.
106  unsigned int dimensionality() {return d_dimensionality;}
107 
108  unsigned int bits_per_symbol()
109  {
110  return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
111  }
112 
113  unsigned int arity()
114  {
115  return d_arity;
116  }
117 
119  {
120  return shared_from_this();
121  }
122 
123  protected:
124  std::vector<gr_complex> d_constellation;
125  std::vector<int> d_pre_diff_code;
127  unsigned int d_rotational_symmetry;
128  unsigned int d_dimensionality;
129  unsigned int d_arity;
130  //! The factor by which the user given constellation points were
131  //! scaled by to achieve an average amplitude of 1.
133 
134  float get_distance(unsigned int index, const gr_complex *sample);
135  unsigned int get_closest_point(const gr_complex *sample);
136  void calc_arity();
137  };
138 
139  /************************************************************/
140  /* constellation_calcdist */
141  /* */
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  */
152  : public constellation
153  {
154  public:
156 
157  /*!
158  * Make a general constellation object that calculates the Euclidean distance for hard decisions.
159  *
160  * \param constell List of constellation points (order of list matches pre_diff_code)
161  * \param pre_diff_code List of alphabet symbols (before applying any differential
162  * coding) (order of list matches constell)
163  * \param rotational_symmetry Number of rotations around unit circle that have the same representation.
164  * \param dimensionality Number of dimensions to the constellation.
165  */
166  static sptr make(std::vector<gr_complex> constell,
167  std::vector<int> pre_diff_code,
168  unsigned int rotational_symmetry,
169  unsigned int dimensionality);
170 
171  unsigned int decision_maker(const gr_complex *sample);
172  // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
173  // void calc_euclidean_metric(gr_complex *sample, float *metric);
174  // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
175 
176  protected:
177  constellation_calcdist(std::vector<gr_complex> constell,
178  std::vector<int> pre_diff_code,
179  unsigned int rotational_symmetry,
180  unsigned int dimensionality);
181  };
182 
183 
184  /************************************************************/
185  /*! constellation_sector */
186  /************************************************************/
187 
188  /*!
189  * \brief Sectorized digital constellation
190  * \ingroup digital
191  *
192  * Constellation space is divided into sectors. Each sector is
193  * associated with the nearest constellation point.
194  *
195  */
197  {
198  public:
199 
200  constellation_sector(std::vector<gr_complex> constell,
201  std::vector<int> pre_diff_code,
202  unsigned int rotational_symmetry,
203  unsigned int dimensionality,
204  unsigned int n_sectors);
205 
207 
208  unsigned int decision_maker(const gr_complex *sample);
209 
210  protected:
211  virtual unsigned int get_sector(const gr_complex *sample) = 0;
212  virtual unsigned int calc_sector_value(unsigned int sector) = 0;
213  void find_sector_values();
214 
215  unsigned int n_sectors;
216 
217  private:
218  std::vector<int> sector_values;
219  };
220 
221  /************************************************************/
222  /* constellation_rect */
223  /************************************************************/
224 
225  /*!
226  * \brief Rectangular digital constellation
227  * \ingroup digital
228  *
229  * Only implemented for 1-(complex)dimensional constellation.
230  *
231  * Constellation space is divided into rectangular sectors. Each
232  * sector is associated with the nearest constellation point.
233  *
234  * Works well for square QAM.
235  *
236  * Works for any generic constellation provided sectors are not
237  * too large.
238  */
239 
240 
242  : public constellation_sector
243  {
244  public:
246 
247  /*!
248  * Make a rectangular constellation object.
249  *
250  * \param constell List of constellation points (order of list matches pre_diff_code)
251  * \param pre_diff_code List of alphabet symbols (before applying any differential
252  * coding) (order of list matches constell)
253  * \param rotational_symmetry Number of rotations around unit circle that have the same representation.
254  * \param real_sectors Number of sectors the real axis is split in to.
255  * \param imag_sectors Number of sectors the imag axis is split in to.
256  * \param width_real_sectors width of each real sector to calculate decision boundaries.
257  * \param width_imag_sectors width of each imag sector to calculate decision boundaries.
258  */
259  static constellation_rect::sptr make(std::vector<gr_complex> constell,
260  std::vector<int> pre_diff_code,
261  unsigned int rotational_symmetry,
262  unsigned int real_sectors,
263  unsigned int imag_sectors,
264  float width_real_sectors,
265  float width_imag_sectors);
267 
268  protected:
269 
270  constellation_rect(std::vector<gr_complex> constell,
271  std::vector<int> pre_diff_code,
272  unsigned int rotational_symmetry,
273  unsigned int real_sectors,
274  unsigned int imag_sectors,
275  float width_real_sectors,
276  float width_imag_sectors);
277 
278  unsigned int get_sector(const gr_complex *sample);
279 
280  unsigned int calc_sector_value(unsigned int sector);
281 
282  private:
283  unsigned int n_real_sectors;
284  unsigned int n_imag_sectors;
285  float d_width_real_sectors;
286  float d_width_imag_sectors;
287  };
288 
289 
290  /************************************************************/
291  /* constellation_expl_rect */
292  /************************************************************/
293 
294  /*!
295  * \brief Rectangular digital constellation
296  * \ingroup digital
297  *
298  * Only implemented for 1-(complex)dimensional constellation.
299  *
300  * Constellation space is divided into rectangular sectors. Each
301  * sector is associated with the nearest constellation point.
302  *
303  * This class is different from constellation_rect in that the
304  * mapping from sector to constellation point is explicitly passed
305  * into the constructor as sector_values. Usually we do not need
306  * this, since we want each sector to be automatically mapped to
307  * the closest constellation point, however sometimes it's nice to
308  * have the flexibility.
309  */
311  : public constellation_rect
312  {
313  public:
315 
316  static sptr make(std::vector<gr_complex> constellation,
317  std::vector<int> pre_diff_code,
318  unsigned int rotational_symmetry,
319  unsigned int real_sectors,
320  unsigned int imag_sectors,
321  float width_real_sectors,
322  float width_imag_sectors,
323  std::vector<unsigned int> sector_values);
325 
326  protected:
327  constellation_expl_rect(std::vector<gr_complex> constellation,
328  std::vector<int> pre_diff_code,
329  unsigned int rotational_symmetry,
330  unsigned int real_sectors,
331  unsigned int imag_sectors,
332  float width_real_sectors,
333  float width_imag_sectors,
334  std::vector<unsigned int> sector_values);
335 
336  unsigned int calc_sector_value (unsigned int sector) {
337  return d_sector_values[sector];
338  }
339 
340  private:
341  std::vector<unsigned int> d_sector_values;
342  };
343 
344  /************************************************************/
345  /* constellation_psk */
346  /************************************************************/
347 
348  /*!
349  * \brief constellation_psk
350  * \ingroup digital
351  *
352  * Constellation space is divided into pie slices sectors.
353  *
354  * Each slice is associated with the nearest constellation point.
355  *
356  * Works well for PSK but nothing else.
357  *
358  * Assumes that there is a constellation point at 1.x
359  */
361  {
362  public:
364 
365  // public constructor
366  static sptr make(std::vector<gr_complex> constell,
367  std::vector<int> pre_diff_code,
368  unsigned int n_sectors);
369 
371 
372  protected:
373  unsigned int get_sector(const gr_complex *sample);
374 
375  unsigned int calc_sector_value(unsigned int sector);
376 
377  constellation_psk(std::vector<gr_complex> constell,
378  std::vector<int> pre_diff_code,
379  unsigned int n_sectors);
380  };
381 
382 
383  /************************************************************/
384  /* constellation_bpsk */
385  /* */
386  /* Only works for BPSK. */
387  /* */
388  /************************************************************/
389 
390  /*!
391  * \brief Digital constellation for BPSK
392  * \ingroup digital
393  */
395  {
396  public:
398 
399  // public constructor
400  static sptr make();
401 
403 
404  unsigned int decision_maker(const gr_complex *sample);
405 
406  protected:
408  };
409 
410 
411  /************************************************************/
412  /* constellation_qpsk */
413  /* */
414  /* Only works for QPSK. */
415  /* */
416  /************************************************************/
417 
418  /*!
419  * \brief Digital constellation for QPSK
420  * \ingroup digital
421  */
423  {
424  public:
426 
427  // public constructor
428  static sptr make();
429 
431 
432  unsigned int decision_maker(const gr_complex *sample);
433 
434  protected:
436  };
437 
438 
439  /************************************************************/
440  /* constellation_dqpsk */
441  /* */
442  /* Works with differential encoding; slower decisions. */
443  /* */
444  /************************************************************/
445 
446  /*!
447  * \brief Digital constellation for DQPSK
448  * \ingroup digital
449  */
451  {
452  public:
454 
455  // public constructor
456  static sptr make();
457 
459 
460  unsigned int decision_maker(const gr_complex *sample);
461 
462  protected:
464  };
465 
466 
467  /************************************************************/
468  /* constellation_8psk */
469  /* */
470  /* Only works for 8PSK. */
471  /* */
472  /************************************************************/
473 
474  /*!
475  * \brief Digital constellation for 8PSK
476  * \ingroup digital
477  */
479  {
480  public:
482 
483  // public constructor
484  static sptr make();
485 
487 
488  unsigned int decision_maker(const gr_complex *sample);
489 
490  protected:
492  };
493 
494  } /* namespace digital */
495 } /* namespace gr */
496 
497 #endif /* INCLUDED_DIGITAL_CONSTELLATION_H */