GNU Radio 3.6.5.1 C++ API
digital_constellation.h
Go to the documentation of this file.
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 <digital_api.h>
27 #include <vector>
28 #include <math.h>
29 #include <gr_complex.h>
30 #include <boost/enable_shared_from_this.hpp>
31 #include <digital_metric_type.h>
32 
33 /************************************************************/
34 /* digital_constellation */
35 /* */
36 /* Base class defining interface. */
37 /************************************************************/
38 
41 
42 /*!
43  * \brief An abstracted constellation object
44  * \ingroup digital
45  *
46  * The constellation objects hold the necessary information to pass
47  * around constellation information for modulators and
48  * demodulators. These objects contain the mapping between the bits
49  * and the constellation points used to represent them as well as
50  * methods for slicing the symbol space. Various implementations are
51  * possible for efficiency and ease of use.
52  *
53  * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
54  * from this class and overloaded to perform optimized slicing and
55  * constellation mappings.
56  */
57 class DIGITAL_API digital_constellation : public boost::enable_shared_from_this<digital_constellation>
58 {
59 public:
60  digital_constellation (std::vector<gr_complex> constellation,
61  std::vector<unsigned int> pre_diff_code,
62  unsigned int rotational_symmetry,
63  unsigned int dimensionality);
65 
66  virtual ~digital_constellation();
67 
68  //! Returns the constellation points for a symbol value
69  void map_to_points(unsigned int value, gr_complex *points);
70  std::vector<gr_complex> map_to_points_v(unsigned int value);
71 
72  //! Returns the constellation point that matches best.
73  virtual unsigned int decision_maker (const gr_complex *sample) = 0;
74  //! Takes a vector rather than a pointer. Better for SWIG wrapping.
75  unsigned int decision_maker_v (std::vector<gr_complex> sample);
76  //! Also calculates the phase error.
77  unsigned int decision_maker_pe (const gr_complex *sample, float *phase_error);
78  //! Calculates distance.
79  unsigned int decision_maker_e (const gr_complex *sample, float *error);
80 
81  //! Calculates metrics for all points in the constellation.
82  //! For use with the viterbi algorithm.
83  virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type);
84  virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
85  virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
86 
87  //! Returns the set of points in this constellation.
88  std::vector<gr_complex> points() { return d_constellation;}
89  //! Returns the vector of points in this constellation.
90  //! Raise error if dimensionality is not one.
91  std::vector<gr_complex> s_points();
92  //! Returns a vector of vectors of points.
93  std::vector<std::vector<gr_complex> > v_points();
94  //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
95  bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
96  //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
97  void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
98  //! Returns the encoding to apply before differential encoding.
99  std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;}
100  //! Returns the order of rotational symmetry.
101  unsigned int rotational_symmetry() { return d_rotational_symmetry;}
102  //! Returns the number of complex numbers in a single symbol.
103  unsigned int dimensionality() {return d_dimensionality;}
104 
105  unsigned int bits_per_symbol () {
106  return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
107  }
108 
109  unsigned int arity () {
110  return d_arity;
111  }
112 
114  return shared_from_this();
115  }
116 
117  protected:
118 
119  std::vector<gr_complex> d_constellation;
120  std::vector<unsigned int> d_pre_diff_code;
122  unsigned int d_rotational_symmetry;
123  unsigned int d_dimensionality;
124  unsigned int d_arity;
125  // The orignal constellation points were multiplied by this factor to get a
126  // constellation with average magnitude 1.
128 
129  float get_distance(unsigned int index, const gr_complex *sample);
130  unsigned int get_closest_point(const gr_complex *sample);
131  void calc_arity ();
132 };
133 
134 /************************************************************/
135 /* digital_constellation_calcdist */
136 /* */
137 /************************************************************/
138 
141 
142 // public constructor
144 digital_make_constellation_calcdist (std::vector<gr_complex> constellation,
145  std::vector<unsigned int> pre_diff_code,
146  unsigned int rotational_symmetry,
147  unsigned int dimensionality);
148 
149 
150 /*! \brief Calculate Euclidian distance for any constellation
151  * \ingroup digital
152  *
153  * Constellation which calculates the distance to each point in the
154  * constellation for decision making. Inefficient for large
155  * constellations.
156  */
158 {
159  public:
160  digital_constellation_calcdist (std::vector<gr_complex> constellation,
161  std::vector<unsigned int> pre_diff_code,
162  unsigned int rotational_symmetry,
163  unsigned int dimensionality);
164  unsigned int decision_maker (const gr_complex *sample);
165  // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
166  // void calc_euclidean_metric(gr_complex *sample, float *metric);
167  // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
168 
169  private:
171  digital_make_constellation_calcdist (std::vector<gr_complex> constellation);
172 };
173 
174 
175 /************************************************************/
176 /*! digital_constellation_sector */
177 /************************************************************/
178 
179 /*!
180  * \brief Sectorized digital constellation
181  * \ingroup digital
182  *
183  * Constellation space is divided into sectors. Each sector is
184  * associated with the nearest constellation point.
185  *
186  */
188 {
189  public:
190 
191  digital_constellation_sector (std::vector<gr_complex> constellation,
192  std::vector<unsigned int> pre_diff_code,
193  unsigned int rotational_symmetry,
194  unsigned int dimensionality,
195  unsigned int n_sectors);
196 
197  unsigned int decision_maker (const gr_complex *sample);
198 
199  protected:
200 
201  virtual unsigned int get_sector (const gr_complex *sample) = 0;
202  virtual unsigned int calc_sector_value (unsigned int sector) = 0;
203  void find_sector_values ();
204 
205  unsigned int n_sectors;
206 
207  private:
208 
209  std::vector<unsigned int> sector_values;
210 
211 };
212 
213 /************************************************************/
214 /* digital_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 too
229  * large.
230  */
231 
234 
235 // public constructor
237 digital_make_constellation_rect (std::vector<gr_complex> constellation,
238  std::vector<unsigned int> pre_diff_code,
239  unsigned int rotational_symmetry,
240  unsigned int real_sectors,
241  unsigned int imag_sectors,
242  float width_real_sectors,
243  float width_imag_sectors);
244 
246 {
247  public:
248 
249  digital_constellation_rect (std::vector<gr_complex> constellation,
250  std::vector<unsigned int> pre_diff_code,
251  unsigned int rotational_symmetry,
252  unsigned int real_sectors,
253  unsigned int imag_sectors,
254  float width_real_sectors,
255  float width_imag_sectors);
256 
257  protected:
258 
259  unsigned int get_sector (const gr_complex *sample);
260 
261  unsigned int calc_sector_value (unsigned int sector);
262 
263  private:
264 
265  unsigned int n_real_sectors;
266  unsigned int n_imag_sectors;
267  float d_width_real_sectors;
268  float d_width_imag_sectors;
269 
271  digital_make_constellation_rect (std::vector<gr_complex> constellation,
272  std::vector<unsigned int> pre_diff_code,
273  unsigned int rotational_symmetry,
274  unsigned int real_sectors,
275  unsigned int imag_sectors,
276  float width_real_sectors,
277  float width_imag_sectors);
278 
279 };
280 
281 /************************************************************/
282 /* digital_constellation_expl_rect */
283 /************************************************************/
284 
285 /*!
286  * \brief Rectangular digital constellation
287  * \ingroup digital
288  *
289  * Only implemented for 1-(complex)dimensional constellation.
290  *
291  * Constellation space is divided into rectangular sectors. Each
292  * sector is associated with the nearest constellation point.
293  *
294  * This class is different from constellation_rect in that the mapping
295  * from sector to constellation point is explicitly passed into the
296  * constructor as sector_values. Usually we do not need this, since
297  * we want each sector to be automatically mapped to the closest
298  * constellation point, however sometimes it's nice to have the
299  * flexibility.
300  */
301 
304 
305 // public constructor
308  std::vector<gr_complex> constellation,
309  std::vector<unsigned 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 
319 {
320  public:
321 
323  std::vector<gr_complex> constellation,
324  std::vector<unsigned int> pre_diff_code,
325  unsigned int rotational_symmetry,
326  unsigned int real_sectors,
327  unsigned int imag_sectors,
328  float width_real_sectors,
329  float width_imag_sectors,
330  std::vector<unsigned int> sector_values
331  );
332 
333  protected:
334  unsigned int calc_sector_value (unsigned int sector) {
335  return d_sector_values[sector];
336  }
337 
338  private:
339  std::vector<unsigned int> d_sector_values;
340 
343  std::vector<gr_complex> constellation,
344  std::vector<unsigned int> pre_diff_code,
345  unsigned int rotational_symmetry,
346  unsigned int real_sectors,
347  unsigned int imag_sectors,
348  float width_real_sectors,
349  float width_imag_sectors,
350  std::vector<unsigned int> sector_values
351  );
352 
353 };
354 
355 
356 /************************************************************/
357 /* digital_constellation_psk */
358 /************************************************************/
359 
362 
363 // public constructor
365 digital_make_constellation_psk (std::vector<gr_complex> constellation,
366  std::vector<unsigned int> pre_diff_code,
367  unsigned int n_sectors);
368 
369 /*!
370  * \brief digital_constellation_psk
371  * \ingroup digital
372  *
373  * Constellation space is divided into pie slices sectors.
374  *
375  * Each slice is associated with the nearest constellation point.
376  *
377  * Works well for PSK but nothing else.
378  *
379  * Assumes that there is a constellation point at 1.x
380  */
382 {
383  public:
384 
385  digital_constellation_psk (std::vector<gr_complex> constellation,
386  std::vector<unsigned int> pre_diff_code,
387  unsigned int n_sectors);
388 
389  protected:
390 
391  unsigned int get_sector (const gr_complex *sample);
392 
393  unsigned int calc_sector_value (unsigned int sector);
394 
395  private:
396 
398  digital_make_constellation_psk (std::vector<gr_complex> constellation,
399  std::vector<unsigned int> pre_diff_code,
400  unsigned int n_sectors);
401 
402 };
403 
404 
405 /************************************************************/
406 /* digital_constellation_bpsk */
407 /* */
408 /* Only works for BPSK. */
409 /* */
410 /************************************************************/
411 
414 
415 // public constructor
418 
419 /*!
420  * \brief Digital constellation for BPSK
421  * \ingroup digital
422  */
424 {
425  public:
426 
428  unsigned int decision_maker (const gr_complex *sample);
429 
432 
433 };
434 
435 
436 /************************************************************/
437 /* digital_constellation_qpsk */
438 /* */
439 /* Only works for QPSK. */
440 /* */
441 /************************************************************/
442 
445 
446 // public constructor
449 
450 /*!
451  * \brief Digital constellation for QPSK
452  * \ingroup digital
453  */
455 {
456  public:
457 
459  unsigned int decision_maker (const gr_complex *sample);
460 
463 
464 };
465 
466 
467 /************************************************************/
468 /* digital_constellation_dqpsk */
469 /* */
470 /* Works with differential encoding; slower decisions. */
471 /* */
472 /************************************************************/
473 
476 
477 // public constructor
480 
481 /*!
482  * \brief Digital constellation for DQPSK
483  * \ingroup digital
484  */
486 {
487  public:
488 
490  unsigned int decision_maker (const gr_complex *sample);
491 
494 
495 };
496 
497 
498 /************************************************************/
499 /* digital_constellation_8psk */
500 /* */
501 /* Only works for 8PSK. */
502 /* */
503 /************************************************************/
504 
507 
508 // public constructor
511 
512 /*!
513  * \brief Digital constellation for 8PSK
514  * \ingroup digital
515  */
517 {
518  public:
519 
521  unsigned int decision_maker (const gr_complex *sample);
522 
525 
526 };
527 
528 #endif