Statistics
| Branch: | Tag: | Revision:

root / gnuradio-core / src / lib / general / gr_mpsk_receiver_cc.h @ 28e08614

History | View | Annotate | Download (11.5 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2004 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 2, 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_GR_MPSK_RECEIVER_CC_H
24
#define        INCLUDED_GR_MPSK_RECEIVER_CC_H
25
26
#include <gr_block.h>
27
#include <gr_complex.h>
28
#include <fstream>
29
30
class gri_mmse_fir_interpolator_cc;
31
32
class gr_mpsk_receiver_cc;
33
typedef boost::shared_ptr<gr_mpsk_receiver_cc> gr_mpsk_receiver_cc_sptr;
34
35
// public constructor
36
gr_mpsk_receiver_cc_sptr 
37
gr_make_mpsk_receiver_cc (unsigned int M, float theta, 
38
                          float alpha, float beta,
39
                          float fmin, float fmax,
40
                          float mu, float gain_mu, 
41
                          float omega, float gain_omega, float omega_rel);
42
43
/*!
44
 * \brief This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol
45
 * synchronization. 
46
 * \ingroup block
47
 *
48
 * This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol
49
 * synchronization. It performs carrier frequency and phase locking as well as symbol timing recovery. 
50
 * It works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It should also work for OQPSK and 
51
 * PI/4 DQPSK.
52
 *
53
 * The phase and frequency synchronization are based on a Costas loop that finds the error of the incoming
54
 * signal point compared to its nearest constellation point. The frequency and phase of the NCO are 
55
 * updated according to this error. There are optimized phase error detectors for BPSK and QPSK, but 8PSK
56
 * is done using a brute-force computation of the constellation points to find the minimum.
57
 *
58
 * The symbol synchronization is done using a modified Mueller and Muller circuit from the paper:
59
 * 
60
 *    G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller and Muller 
61
 *    algorithm,"  Electronics Letters, Vol. 31, no. 13,  22 June 1995, pp. 1032 - 1033.
62
 *
63
 * This circuit interpolates the downconverted sample (using the NCO developed by the Costas loop)
64
 * every mu samples, then it finds the sampling error based on this and the past symbols and the decision
65
 * made on the samples. Like the phase error detector, there are optimized decision algorithms for BPSK
66
 * and QPKS, but 8PSK uses another brute force computation against all possible symbols. The modifications
67
 * to the M&M used here reduce self-noise.
68
 *
69
 */
70
71
class gr_mpsk_receiver_cc : public gr_block
72
{
73
 public:
74
  ~gr_mpsk_receiver_cc ();
75
  void forecast(int noutput_items, gr_vector_int &ninput_items_required);
76
  int general_work (int noutput_items,
77
                    gr_vector_int &ninput_items,
78
                    gr_vector_const_void_star &input_items,
79
                    gr_vector_void_star &output_items);
80
81
82
  // Member functions related to the symbol tracking portion of the receiver
83
  //! (M&M) Returns current value of mu
84
  float mu() const { return d_mu;}
85
86
  //! (M&M) Returns current value of omega
87
  float omega() const { return d_omega;}
88
89
  //! (M&M) Returns mu gain factor
90
  float gain_mu() const { return d_gain_mu;}
91
92
  //! (M&M) Returns omega gain factor
93
  float gain_omega() const { return d_gain_omega;}
94
95
  //! (M&M) Sets value of mu
96
  void set_mu (float mu) { d_mu = mu; }
97
  
98
  //! (M&M) Sets value of omega and its min and max values 
99
  void set_omega (float omega) { 
100
    d_omega = omega;
101
    d_min_omega = omega*(1.0 - d_omega_rel);
102
    d_max_omega = omega*(1.0 + d_omega_rel);
103
  }
104
105
  //! (M&M) Sets value for mu gain factor
106
  void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
107
108
  //! (M&M) Sets value for omega gain factor
109
  void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
110
111
112
113
  // Member function related to the phase/frequency tracking portion of the receiver
114
  //! (CL) Returns the value for alpha (the phase gain term)
115
  float alpha() const { return d_alpha; }
116
  
117
  //! (CL) Returns the value of beta (the frequency gain term)
118
  float beta() const { return d_beta; }
119
120
  //! (CL) Returns the current value of the frequency of the NCO in the Costas loop
121
  float freq() const { return d_freq; }
122
123
  //! (CL) Returns the current value of the phase of the NCO in the Costal loop
124
  float phase() const { return d_phase; }
125
126
  //! (CL) Sets the value for alpha (the phase gain term)
127
  void set_alpha(float alpha) { d_alpha = alpha; }
128
  
129
  //! (CL) Setss the value of beta (the frequency gain term)
130
  void set_beta(float beta) { d_beta = beta; }
131
132
  //! (CL) Sets the current value of the frequency of the NCO in the Costas loop
133
  void set_freq(float freq) { d_freq = freq; }
134
135
  //! (CL) Setss the current value of the phase of the NCO in the Costal loop
136
  void set_phase(float phase) { d_phase = phase; }
137
138
139
protected:
140
141
 /*!
142
   * \brief Constructor to synchronize incoming M-PSK symbols
143
   *
144
   * \param M                modulation order of the M-PSK modulation
145
   * \param theta        any constant phase rotation from the real axis of the constellation
146
   * \param alpha        gain parameter to adjust the phase in the Costas loop (~0.01)
147
   * \param beta        gain parameter to adjust the frequency in the Costas loop (~alpha^2/4)        
148
   * \param fmin        minimum normalized frequency value the loop can achieve
149
   * \param fmax        maximum normalized frequency value the loop can achieve
150
   * \param mu          initial parameter for the interpolator [0,1]
151
   * \param gain_mu     gain parameter of the M&M error signal to adjust mu (~0.05)
152
   * \param omega       initial value for the number of symbols between samples (~number of samples/symbol)
153
   * \param gain_omega  gain parameter to adjust omega based on the error (~omega^2/4)
154
   * \param omega_rel   sets the maximum (omega*(1+omega_rel)) and minimum (omega*(1+omega_rel)) omega (~0.005)
155
   *
156
   * The constructor also chooses which phase detector and decision maker to use in the work loop based on the
157
   * value of M.
158
   */
159
  gr_mpsk_receiver_cc (unsigned int M, float theta, 
160
                       float alpha, float beta,
161
                       float fmin, float fmax,
162
                       float mu, float gain_mu, 
163
                       float omega, float gain_omega, float omega_rel);
164
165
  void make_constellation();
166
  void mm_sampler(const gr_complex symbol);
167
  void mm_error_tracking(gr_complex sample);
168
  void phase_error_tracking(gr_complex sample);
169
170
171
/*!
172
   * \brief Phase error detector for MPSK modulations.
173
   *
174
   * \param sample   the I&Q sample from which to determine the phase error
175
   *
176
   * This function determines the phase error for any MPSK signal by creating a set of PSK constellation points
177
   * and doing a brute-force search to see which point minimizes the Euclidean distance. This point is then used
178
   * to derotate the sample to the real-axis and a atan (using the fast approximation function) to determine the
179
   * phase difference between the incoming sample and the real constellation point
180
   *
181
   * This should be cleaned up and made more efficient.
182
   *
183
   * \returns the approximated phase error.
184
 */
185
  float phase_error_detector_generic(gr_complex sample) const; // generic for M but more costly
186
187
 /*!
188
   * \brief Phase error detector for BPSK modulation.
189
   *
190
   * \param sample   the I&Q sample from which to determine the phase error
191
   *
192
   * This function determines the phase error using a simple BPSK phase error detector by multiplying the real
193
   * and imaginary (the error signal) components together. As the imaginary part goes to 0, so does this error.
194
   *
195
   * \returns the approximated phase error.
196
 */
197
  float phase_error_detector_bpsk(gr_complex sample) const;    // optimized for BPSK
198
199
 /*!
200
   * \brief Phase error detector for QPSK modulation.
201
   *
202
   * \param sample   the I&Q sample from which to determine the phase error
203
   *
204
   * This function determines the phase error using the limiter approach in a standard 4th order Costas loop
205
   *
206
   * \returns the approximated phase error.
207
 */
208
  float phase_error_detector_qpsk(gr_complex sample) const;
209
210
211
212
 /*!
213
   * \brief Decision maker for a generic MPSK constellation.
214
   *
215
   * \param sample   the baseband I&Q sample from which to make the decision
216
   *
217
   * This decision maker is a generic implementation that does a brute-force search 
218
   * for the constellation point that minimizes the error between it and the incoming signal.
219
   *
220
   * \returns the index to d_constellation that minimizes the error/
221
 */
222
  unsigned int decision_generic(gr_complex sample) const;
223
224
225
 /*!
226
   * \brief Decision maker for BPSK constellation.
227
   *
228
   * \param sample   the baseband I&Q sample from which to make the decision
229
   *
230
   * This decision maker is a simple slicer function that makes a decision on the symbol based on its
231
   * placement on the real axis of greater than 0 or less than 0; the quadrature component is always 0.
232
   *
233
   * \returns the index to d_constellation that minimizes the error/
234
 */
235
  unsigned int decision_bpsk(gr_complex sample) const;
236
  
237
238
 /*!
239
   * \brief Decision maker for QPSK constellation.
240
   *
241
   * \param sample   the baseband I&Q sample from which to make the decision
242
   *
243
   * This decision maker is a simple slicer function that makes a decision on the symbol based on its
244
   * placement versus both axes and returns which quadrant the symbol is in.
245
   *
246
   * \returns the index to d_constellation that minimizes the error/
247
 */
248
  unsigned int decision_qpsk(gr_complex sample) const;
249
250
  private:
251
  unsigned int d_M;
252
  float        d_theta;
253
254
  // Members related to carrier and phase tracking
255
  float d_alpha;
256
  float d_beta;
257
  float d_freq, d_max_freq, d_min_freq;
258
  float d_phase;
259
260
/*!
261
   * \brief Decision maker function pointer 
262
   *
263
   * \param sample   the baseband I&Q sample from which to make the decision
264
   *
265
   * This is a function pointer that is set in the constructor to point to the proper decision function
266
   * for the specified constellation order.
267
   *
268
   * \return index into d_constellation point that is the closest to the recieved sample
269
 */
270
  unsigned int (gr_mpsk_receiver_cc::*d_decision)(gr_complex sample) const; // pointer to decision function
271
272
273
  std::vector<gr_complex> d_constellation;
274
  unsigned int d_current_const_point;
275
276
  // Members related to symbol timing
277
  float d_mu, d_gain_mu;
278
  float d_omega, d_gain_omega, d_omega_rel, d_max_omega, d_min_omega;
279
  gr_complex d_p_2T, d_p_1T, d_p_0T;
280
  gr_complex d_c_2T, d_c_1T, d_c_0T;
281
282
 /*!
283
   * \brief Phase error detector function pointer 
284
   *
285
   * \param sample   the I&Q sample from which to determine the phase error
286
   *
287
   * This is a function pointer that is set in the constructor to point to the proper phase error detector
288
   * function for the specified constellation order.
289
 */
290
  float (gr_mpsk_receiver_cc::*d_phase_error_detector)(gr_complex sample) const;
291
292
293
  //! get interpolated value
294
  gri_mmse_fir_interpolator_cc         *d_interp;
295
  
296
  //! delay line length.
297
  static const unsigned int DLLEN = 8;
298
  
299
  //! delay line plus some length for overflow protection
300
  gr_complex d_dl[2*DLLEN];
301
  
302
  //! index to delay line
303
  unsigned int d_dl_idx;
304
305
  friend gr_mpsk_receiver_cc_sptr
306
  gr_make_mpsk_receiver_cc (unsigned int M, float theta,
307
                            float alpha, float beta,
308
                            float fmin, float fmax,
309
                            float mu, float gain_mu, 
310
                            float omega, float gain_omega, float omega_rel);
311
};
312
313
#endif