1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
|
/* -*- c++ -*- */
/*
* Copyright (C) 2017 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this file; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_DIGITAL_TIMING_ERROR_DETECTOR_H
#define INCLUDED_DIGITAL_TIMING_ERROR_DETECTOR_H
#include <gnuradio/gr_complex.h>
#include <gnuradio/digital/timing_error_detector_type.h>
#include <gnuradio/digital/constellation.h>
#include <deque>
namespace gr {
namespace digital {
/*!
* \brief Base class for the composite symbol clock timing error
* detector object used by the symbol_synchronizer_xx blocks.
* \ingroup internal
*
* \details
* This is the base class for the symbol clock timing error detector
* object used by the symbol_synchronizer_xx blocks to provide a
* user selectable timing error detector type.
*
* This base class provides the enumeration type for the available
* types of timing error detectors.
*
* This base class also provides most of the methods update, manage, and
* store the data points required to compute the symbol clock timing error,
* and the timing error result itself.
*
* The derived classes only have to provide the simple functions
* to actually compute the timing error.
*/
class timing_error_detector
{
public:
/*!
* \brief Create a timing error detector object of the specified
* type
* \param type The type/algorithm to use for the timing error detector
* \param constellation A constellation to be used as a decision slicer
* for decision directed timing error detector
* algorithms
*/
static timing_error_detector *make(enum ted_type type,
constellation_sptr constellation =
constellation_sptr());
virtual ~timing_error_detector() {};
/*!
* \brief Return the number of input samples per symbol this timing
* error detector algorithm requires.
*/
virtual int inputs_per_symbol() { return d_inputs_per_symbol; }
/*!
* \brief Provide a complex input sample to the TED algorithm
* \param x the input sample
* \param dx the derivative at the input sample, if required by the
* timinig error detector algorithm
*/
virtual void input(const gr_complex &x,
const gr_complex &dx = gr_complex(0.0f, 0.0f));
/*!
* \brief Provide a float input sample to the TED algorithm
* \param x the input sample
* \param dx the derivative at the input sample, if required by the
* timinig error detector algorithm
*/
virtual void input(float x,
float dx = 0.0f);
/*!
* \brief Return if this timing error detector algorithm requires a
* look-ahead input sample to be input to produce a new error estimate
* for the symbol sampling instant.
*/
virtual bool needs_lookahead() { return d_needs_lookahead; }
/*!
* \brief Provide a complex input lookahead sample to the TED algorithm
* \param x the input lookahead sample
* \param dx the derivative at the input lookahead sample, if required
* by the timinig error detector algorithm
*/
virtual void input_lookahead(const gr_complex &x,
const gr_complex &dx =
gr_complex(0.0f, 0.0f));
/*!
* \brief Provide a float input lookahead sample to the TED algorithm
* \param x the input lookahead sample
* \param dx the derivative at the input lookahead sample, if required
* by the timinig error detector algorithm
*/
virtual void input_lookahead(float x,
float dx = 0.0f);
/*!
* \brief Return if this timing error detector algorithm requires
* derivative input samples in addition to normal input samples.
*/
virtual bool needs_derivative() { return d_needs_derivative; }
/*!
* \brief Return the current symbol timing error estimate
*/
virtual float error() { return d_error; }
/*!
* \brief Revert the timing error detector processing state back one
* step.
* \param preserve_error If true, don't revert the error estimate.
*/
virtual void revert(bool preserve_error = false);
/*!
* \brief Reset the timing error detector
*/
virtual void sync_reset();
private:
enum ted_type d_type;
protected:
/*!
* \brief Create a timing error detector abstract base class object
* object
* \param type The type/algorithm to use for the timing error detector
* \param inputs_per_symbol The input samples per symbol this TED
* algorithm requires
* \param error_computation_depth The number of input samples this TED
* algorithm needs to compute the error
* \param needs_lookahead True if this TED algorithm needs a lookahead
* input sample to compute the error for the
* symbol sampling instant
* \param needs_derivative True if this TED algorithm needs a derivative
* input sample in addition to the normal input
* sample
* \param constellation A constellation to be used as a decision slicer
* for decision directed timing error detector
* algorithms
*/
timing_error_detector(enum ted_type type,
int inputs_per_symbol,
int error_computation_depth,
bool needs_lookahead = false,
bool needs_derivative = false,
constellation_sptr constellation =
constellation_sptr());
/*!
* \brief Advance the TED input clock, so the input() methods will
* compute the TED error term at the proper symbol sampling instant.
*/
void advance_input_clock() {
d_input_clock = (d_input_clock + 1) % d_inputs_per_symbol;
}
/*!
* \brief Revert the TED input clock one step
*/
void revert_input_clock()
{
if (d_input_clock == 0)
d_input_clock = d_inputs_per_symbol - 1;
else
d_input_clock--;
}
/*!
* \brief Reset the TED input clock, so the next input clock advance
* corresponds to a symbol sampling instant.
*/
void sync_reset_input_clock() {
d_input_clock = d_inputs_per_symbol - 1;
}
/*!
* \brief Convert the soft symbol sample into a hard symbol decision.
* \param x the soft input symbol sample
*/
gr_complex slice(const gr_complex &x);
/*!
* \brief Compute the TED error term for complex input samples
*/
virtual float compute_error_cf() = 0;
/*!
* \brief Compute the TED error term for float input samples
*/
virtual float compute_error_ff() = 0;
constellation_sptr d_constellation;
float d_error;
float d_prev_error;
int d_inputs_per_symbol;
int d_input_clock;
int d_error_depth;
std::deque<gr_complex> d_input;
std::deque<gr_complex> d_decision;
std::deque<gr_complex> d_input_derivative;
bool d_needs_lookahead;
bool d_needs_derivative;
};
/*!
* \brief Mueller and Müller (M&M) timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Mueller and Müller (M&M) timing error detector algorithm
* class. It is a decision directed timing error detector, and requires
* an input slicer constellation to make decisions.
*
* See equation (49) of:
* Mueller, Kurt H., Müller, Markus, "Timing Recovery in Digital
* Synchronous Data Receivers", _IEEE_Transactions_on_Communications_,
* Vol. COM-24, No. 5, May 1976, pp. 516-531
*/
class ted_mueller_and_muller : public timing_error_detector
{
public:
/*!
* \brief Create a Mueller and Müller (M&M) timing error detector
* \param constellation A constellation to be used as a decision slicer
*/
ted_mueller_and_muller(constellation_sptr constellation)
: timing_error_detector(TED_MUELLER_AND_MULLER,
1, 2, false, false, constellation)
{}
~ted_mueller_and_muller() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Modified Mueller and Müller (M&M) timing error detector algorithm
* class
* \ingroup internal
*
* \details
* This is the modified Mueller and Müller (M&M) timing error detector
* algorithm class. It is a decision directed timing error detector, and
* requires an input slicer constellation to make decisions.
*
* The modification of the standard M&M TED is done to remove
* self-noise that is present in the standard M&M TED.
*
* See:
* G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller
* and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22
* June 1995, pp. 1032 - 1033.
*/
class ted_mod_mueller_and_muller : public timing_error_detector
{
public:
/*!
* \brief Create a modified Mueller and Müller (M&M) timing error
* detector
* \param constellation A constellation to be used as a decision slicer
*/
ted_mod_mueller_and_muller(constellation_sptr constellation)
: timing_error_detector(TED_MOD_MUELLER_AND_MULLER,
1, 3, false, false, constellation)
{}
~ted_mod_mueller_and_muller() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Zero Crossing timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Zero Crossing timing error detector algorithm class.
* It is a decision directed timing error detector, and
* requires an input slicer constellation to make decisions.
*/
class ted_zero_crossing : public timing_error_detector
{
public:
/*!
* \brief Create a Zero Crossing timing error detector
* \param constellation A constellation to be used as a decision slicer
*/
ted_zero_crossing(constellation_sptr constellation)
: timing_error_detector(TED_ZERO_CROSSING,
2, 3, false, false, constellation)
{}
~ted_zero_crossing() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Gardner timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Gardner timing error detector algorithm class.
*
* See:
* F.M. Gardner, “A BPSK/QPSK Timing Error Detector for Sampled Receivers”,
* IEEE Trans., COM-34, (5), 1988, pp. 423 – 429.
*/
class ted_gardner : public timing_error_detector
{
public:
/*!
* \brief Create a Gardner timing error detector
*/
ted_gardner()
: timing_error_detector(TED_GARDNER,
2, 3, false, false,
constellation_sptr())
{}
~ted_gardner() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Early-Late timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Early-Late timing error detector algorithm class.
* It requires a lookahead sample to compute the symbol timing error
* at the symbol sampling instant.
*/
class ted_early_late : public timing_error_detector
{
public:
/*!
* \brief Create a Early-Late timing error detector
*/
ted_early_late()
: timing_error_detector(TED_EARLY_LATE,
2, 2, true, false,
constellation_sptr())
{}
~ted_early_late() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Generalized MSK timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Generalized MSK timing error detector algorithm class.
* It operates on the CPM MSK signal directly and not the FM pulses.
*
* See:
* A.N. D'Andrea, U. Mengali, R. Reggiannini, "A digital approach to clock
* recovery in generalized minimum shift keying", IEEE Transactions on
* Vehicular Technology, Vol. 39, Issue 3, August 1990, pp. 227-234
*/
class ted_generalized_msk : public timing_error_detector
{
public:
/*!
* \brief Create a Generalized MSK timing error detector
*/
ted_generalized_msk()
: timing_error_detector(TED_DANDREA_AND_MENGALI_GEN_MSK,
2, 4, false, false, constellation_sptr())
{}
~ted_generalized_msk() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Gaussian MSK timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Gaussian MSK timing error detector algorithm class.
* It operates on the CPM MSK signal directly and not the FM pulses.
*
* See:
* U. Mengali, A.N. D'Andrea, _Synchronization_Techniques_for_Digital_
* Receviers_, New York, Plenum Press 1997
*/
class ted_gaussian_msk : public timing_error_detector
{
public:
/*!
* \brief Create a Generalized MSK timing error detector
*/
ted_gaussian_msk()
: timing_error_detector(TED_MENGALI_AND_DANDREA_GMSK,
2, 4, false, false, constellation_sptr())
{}
~ted_gaussian_msk() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Signal times Slope Maximum Likelyhood solution approximation
* timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Signal times Slope Maximum Likelyhood solution approximation
* timing error detector algorithm class. This approximation is good for
* small signals (< 1.0) and/or situations with low SNR.
*
* See equation (5) and the 2 following paragraphs of:
* Fredric J. Harris, Michael Rice, "Multirate Digital Filters for
* Symbol Timing Synchronization in Software Defined Radios",
* _IEEE_Journal_on_Selected_Areas_in_Communications_, Vol. 19, No. 12,
* December 2001, pp. 2346 - 2357
*/
class ted_signal_times_slope_ml : public timing_error_detector
{
public:
/*!
* \brief Create a Signal times Slope Maximum Likelyhood solution
* approximation timing error detector
*/
ted_signal_times_slope_ml()
: timing_error_detector(TED_SIGNAL_TIMES_SLOPE_ML,
1, 1, false, true, constellation_sptr())
{}
~ted_signal_times_slope_ml() {};
private:
float compute_error_cf();
float compute_error_ff();
};
/*!
* \brief Signum times Slope Maximum Likelyhood solution approximation
* timing error detector algorithm class
* \ingroup internal
*
* \details
* This is the Signum times Slope Maximum Likelyhood solution approximation
* timing error detector algorithm class. This approximation is good for
* large signals (> 1.0) and/or situations with high SNR.
*
* See equation (5) and the 2 following paragraphs of:
* Fredric J. Harris, Michael Rice, "Multirate Digital Filters for
* Symbol Timing Synchronization in Software Defined Radios",
* _IEEE_Journal_on_Selected_Areas_in_Communications_, Vol. 19, No. 12,
* December 2001, pp. 2346 - 2357
*/
class ted_signum_times_slope_ml : public timing_error_detector
{
public:
/*!
* \brief Create a Signum times Slope Maximum Likelyhood solution
* approximation timing error detector
*/
ted_signum_times_slope_ml()
: timing_error_detector(TED_SIGNUM_TIMES_SLOPE_ML,
1, 1, false, true, constellation_sptr())
{}
~ted_signum_times_slope_ml() {};
private:
float compute_error_cf();
float compute_error_ff();
};
} /* namespace digital */
} /* namespace gr */
#endif /* INCLUDED_DIGITAL_TIMING_ERROR_DETECTOR_H */
|