GNU Radio 3.7.0-50 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  // public constructor
158  static sptr make(std::vector<gr_complex> constell,
159  std::vector<int> pre_diff_code,
160  unsigned int rotational_symmetry,
161  unsigned int dimensionality);
162 
163  unsigned int decision_maker(const gr_complex *sample);
164  // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
165  // void calc_euclidean_metric(gr_complex *sample, float *metric);
166  // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
167 
168  protected:
169  constellation_calcdist(std::vector<gr_complex> constell,
170  std::vector<int> pre_diff_code,
171  unsigned int rotational_symmetry,
172  unsigned int dimensionality);
173  };
174 
175 
176  /************************************************************/
177  /*! constellation_sector */
178  /************************************************************/
179 
180  /*!
181  * \brief Sectorized digital constellation
182  * \ingroup digital
183  *
184  * Constellation space is divided into sectors. Each sector is
185  * associated with the nearest constellation point.
186  *
187  */
189  {
190  public:
191 
192  constellation_sector(std::vector<gr_complex> constell,
193  std::vector<int> pre_diff_code,
194  unsigned int rotational_symmetry,
195  unsigned int dimensionality,
196  unsigned int n_sectors);
197 
199 
200  unsigned int decision_maker(const gr_complex *sample);
201 
202  protected:
203  virtual unsigned int get_sector(const gr_complex *sample) = 0;
204  virtual unsigned int calc_sector_value(unsigned int sector) = 0;
205  void find_sector_values();
206 
207  unsigned int n_sectors;
208 
209  private:
210  std::vector<int> sector_values;
211  };
212 
213  /************************************************************/
214  /* constellation_rect */
215  /************************************************************/
216 
217  /*!
218  * \brief Rectangular digital constellation
219  * \ingroup digital
220  *
221  * Only implemented for 1-(complex)dimensional constellation.
222  *
223  * Constellation space is divided into rectangular sectors. Each
224  * sector is associated with the nearest constellation point.
225  *
226  * Works well for square QAM.
227  *
228  * Works for any generic constellation provided sectors are not
229  * too large.
230  */
231 
232 
234  : public constellation_sector
235  {
236  public:
238 
239  // public constructor
240  static constellation_rect::sptr make(std::vector<gr_complex> constell,
241  std::vector<int> pre_diff_code,
242  unsigned int rotational_symmetry,
243  unsigned int real_sectors,
244  unsigned int imag_sectors,
245  float width_real_sectors,
246  float width_imag_sectors);
248 
249  protected:
250 
251  constellation_rect(std::vector<gr_complex> constell,
252  std::vector<int> pre_diff_code,
253  unsigned int rotational_symmetry,
254  unsigned int real_sectors,
255  unsigned int imag_sectors,
256  float width_real_sectors,
257  float width_imag_sectors);
258 
259  unsigned int get_sector(const gr_complex *sample);
260 
261  unsigned int calc_sector_value(unsigned int sector);
262 
263  private:
264  unsigned int n_real_sectors;
265  unsigned int n_imag_sectors;
266  float d_width_real_sectors;
267  float d_width_imag_sectors;
268  };
269 
270 
271  /************************************************************/
272  /* constellation_expl_rect */
273  /************************************************************/
274 
275  /*!
276  * \brief Rectangular digital constellation
277  * \ingroup digital
278  *
279  * Only implemented for 1-(complex)dimensional constellation.
280  *
281  * Constellation space is divided into rectangular sectors. Each
282  * sector is associated with the nearest constellation point.
283  *
284  * This class is different from constellation_rect in that the
285  * mapping from sector to constellation point is explicitly passed
286  * into the constructor as sector_values. Usually we do not need
287  * this, since we want each sector to be automatically mapped to
288  * the closest constellation point, however sometimes it's nice to
289  * have the flexibility.
290  */
292  : public constellation_rect
293  {
294  public:
296 
297  static sptr make(std::vector<gr_complex> constellation,
298  std::vector<int> pre_diff_code,
299  unsigned int rotational_symmetry,
300  unsigned int real_sectors,
301  unsigned int imag_sectors,
302  float width_real_sectors,
303  float width_imag_sectors,
304  std::vector<unsigned int> sector_values);
306 
307  protected:
308  constellation_expl_rect(std::vector<gr_complex> constellation,
309  std::vector<int> pre_diff_code,
310  unsigned int rotational_symmetry,
311  unsigned int real_sectors,
312  unsigned int imag_sectors,
313  float width_real_sectors,
314  float width_imag_sectors,
315  std::vector<unsigned int> sector_values);
316 
317  unsigned int calc_sector_value (unsigned int sector) {
318  return d_sector_values[sector];
319  }
320 
321  private:
322  std::vector<unsigned int> d_sector_values;
323  };
324 
325  /************************************************************/
326  /* constellation_psk */
327  /************************************************************/
328 
329  /*!
330  * \brief constellation_psk
331  * \ingroup digital
332  *
333  * Constellation space is divided into pie slices sectors.
334  *
335  * Each slice is associated with the nearest constellation point.
336  *
337  * Works well for PSK but nothing else.
338  *
339  * Assumes that there is a constellation point at 1.x
340  */
342  {
343  public:
345 
346  // public constructor
347  static sptr make(std::vector<gr_complex> constell,
348  std::vector<int> pre_diff_code,
349  unsigned int n_sectors);
350 
352 
353  protected:
354  unsigned int get_sector(const gr_complex *sample);
355 
356  unsigned int calc_sector_value(unsigned int sector);
357 
358  constellation_psk(std::vector<gr_complex> constell,
359  std::vector<int> pre_diff_code,
360  unsigned int n_sectors);
361  };
362 
363 
364  /************************************************************/
365  /* constellation_bpsk */
366  /* */
367  /* Only works for BPSK. */
368  /* */
369  /************************************************************/
370 
371  /*!
372  * \brief Digital constellation for BPSK
373  * \ingroup digital
374  */
376  {
377  public:
379 
380  // public constructor
381  static sptr make();
382 
384 
385  unsigned int decision_maker(const gr_complex *sample);
386 
387  protected:
389  };
390 
391 
392  /************************************************************/
393  /* constellation_qpsk */
394  /* */
395  /* Only works for QPSK. */
396  /* */
397  /************************************************************/
398 
399  /*!
400  * \brief Digital constellation for QPSK
401  * \ingroup digital
402  */
404  {
405  public:
407 
408  // public constructor
409  static sptr make();
410 
412 
413  unsigned int decision_maker(const gr_complex *sample);
414 
415  protected:
417  };
418 
419 
420  /************************************************************/
421  /* constellation_dqpsk */
422  /* */
423  /* Works with differential encoding; slower decisions. */
424  /* */
425  /************************************************************/
426 
427  /*!
428  * \brief Digital constellation for DQPSK
429  * \ingroup digital
430  */
432  {
433  public:
435 
436  // public constructor
437  static sptr make();
438 
440 
441  unsigned int decision_maker(const gr_complex *sample);
442 
443  protected:
445  };
446 
447 
448  /************************************************************/
449  /* constellation_8psk */
450  /* */
451  /* Only works for 8PSK. */
452  /* */
453  /************************************************************/
454 
455  /*!
456  * \brief Digital constellation for 8PSK
457  * \ingroup digital
458  */
460  {
461  public:
463 
464  // public constructor
465  static sptr make();
466 
468 
469  unsigned int decision_maker(const gr_complex *sample);
470 
471  protected:
473  };
474 
475  } /* namespace digital */
476 } /* namespace gr */
477 
478 #endif /* INCLUDED_DIGITAL_CONSTELLATION_H */