Statistics
| Branch: | Tag: | Revision:

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