GNU Radio Manual and C++ API Reference  3.7.14.0
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
sssr_impl.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2002 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 /*
24  * --- ATSC Segment and Symbol Sync Recovery ---
25  */
26 
27 #ifndef _ATSC_SSSR_H_
28 #define _ATSC_SSSR_H_
29 
30 #include <gnuradio/atsc/api.h>
31 #include <gnuradio/atsc/consts.h>
34 #include <cstdio>
35 
36 /*
37  * --- support classes for atsci_sssr ---
38  */
39 
40 namespace sssr {
41 
42 typedef float sample_t;
43 
44 // ----------------------------------------------------------------
45 //! digital correlator for 1001 and 0110 patterns
46 
48 {
49  int d_sr; // 4 bit shift register
50 
51 public:
52  // Constructor
53  digital_correlator() { reset(); }
54 
55  // Manipulators
56 
57  //! called on channel change
58  void reset() { d_sr = 0; }
59 
60  //! clock bit in and return true if we've seen 1001
61 
62  bool update(int bit)
63  {
64  d_sr = ((bit & 1) << 3) | (d_sr >> 1);
65 
66  return (d_sr == 0x9); // 1001
67  }
68 };
69 
70 
71 // ----------------------------------------------------------------
72 //! segment sync integrator
73 
75 {
76  signed char d_integrator[ATSC_DATA_SEGMENT_LENGTH];
77 
78 public:
79  // Constructor
80  seg_sync_integrator() { reset(); }
81 
82  // Manipulators
83 
84  //! called on channel change
85  void reset();
86 
87  //! update current tap with weight and return integrated correlation value
88  int update(int weight, int index);
89 
90  //! return index of maximum correlation value
91  int find_max(int* value);
92 };
93 
94 // ----------------------------------------------------------------
95 //! quad filter (used to compute timing error)
96 
98 {
99  sample_t d_delay[4];
100 
101 public:
102  // Constructor
103  quad_filter() { reset(); }
104 
105  // Manipulators
106 
107  //! called on channel change
108  void reset() { d_delay[0] = d_delay[1] = d_delay[2] = d_delay[3] = 0; }
109 
110  double update(sample_t sample)
111  {
112  d_delay[3] = d_delay[2];
113  d_delay[2] = d_delay[1];
114  d_delay[1] = d_delay[0];
115  d_delay[0] = sample;
116 
117  // the coefficients are -1,-1,+1,+1
118  return d_delay[3] + d_delay[2] - d_delay[1] - d_delay[0];
119  }
120 };
121 } // namespace sssr
122 
123 // ----------------------------------------------------------------
124 
125 /*!
126  * \brief ATSC Segment and Symbol Sync Recovery
127  *
128  * This class implements data segment sync tracking and symbol timing
129  * using the method described in "ATSC/VSB Tutorial - Receiver Technology"
130  * by Wayne E. Bretl of Zenith, pgs 41-45.
131  */
132 
134 {
135  sssr::digital_correlator d_correlator;
136  sssr::seg_sync_integrator d_integrator;
137  sssr::quad_filter d_quad_filter;
138  double d_quad_output[ATSC_DATA_SEGMENT_LENGTH];
139  double d_timing_adjust;
140  int d_counter; // free running mod 832 counter
141  int d_symbol_index;
142  bool d_seg_locked;
143  FILE* d_debug_fp;
144 
145 
146  bool incr_counter()
147  {
148  d_counter++;
149  if (d_counter >= ATSC_DATA_SEGMENT_LENGTH) {
150  d_counter = 0;
151  return true;
152  }
153  return false;
154  }
155 
156  void incr_symbol_index()
157  {
158  d_symbol_index++;
159  if (d_symbol_index >= ATSC_DATA_SEGMENT_LENGTH)
160  d_symbol_index = 0;
161  }
162 
163 public:
164  // Constructor
165  atsci_sssr();
166  ~atsci_sssr();
167 
168  // Manipulators
169 
170  //! call on channel change
171  void reset();
172 
173 
174  /*!
175  * \brief process a single sample at the ATSC symbol rate (~10.76 MSPS)
176  *
177  * This block computes an indication of our timing error and keeps
178  * track of where the segment sync's occur. \p timing_adjust is
179  * returned to indicate how the interpolator timing needs to be
180  * adjusted to track the transmitter's symbol timing. If \p seg_locked
181  * is true, then \p symbol_index is the index of this sample in
182  * the current segment. The symbols are numbered from 0 to 831, where
183  * symbols 0, 1, 2 and 3 correspond to the data segment sync pattern,
184  * nominally +5, -5, -5, +5.
185  */
186 
187  void update(sssr::sample_t sample_in, // input
188  bool* seg_locked, // are we seeing segment syncs?
189  int* symbol_index, // 0..831
190  double* timing_adjust); // how much to adjust timing
191 };
192 
193 // ----------------------------------------------------------------
194 
195 /*!
196  * \brief interpolator control for segment and symbol sync recovery
197  */
198 
200 {
202  gr::filter::single_pole_iir<float, float, float> d_loop; // ``VCO'' loop filter
203  double d_nominal_ratio_of_rx_clock_to_symbol_freq; // FREQ
204  double d_w; // ratio of PERIOD of Tx to Rx clocks
205  double d_mu; // fractional delay [0,1]
206  int d_incr; // diagnostic only
207  FILE* d_debug_fp; // diagnostic only
208 
209 public:
210  //! \p nominal_ratio_of_rx_clock_to_symbol_freq must be >= 1.8
211  atsci_interpolator(double nominal_ratio_of_rx_clock_to_symbol_freq);
213 
214  // Manipulators
215 
216  //! call on channel change
217  void reset();
218 
219  /*!
220  * \brief produce next sample referenced to Tx clock
221  *
222  * If there aren't enough input_samples left to produce
223  * an output, return false, else true.
224  */
225 
226  bool update(const sssr::sample_t input_samples[], // I: vector of samples
227  int nsamples, // I: total number of samples
228  int* index, // I/O: current input index
229  double timing_adjustment, // I: how much to bump timing
230  sssr::sample_t* output_sample); // O: the output sample
231 
232  // Accessors
233 
234  // how much history we require on our input
235  unsigned ntaps() const { return d_interp.ntaps(); }
236 
237  // diagnostic accessors
238  double mu() const { return d_mu; }
239  double w() const { return d_w; }
240  int incr() const { return d_incr; }
241 };
242 
243 #endif /* _ATSC_SSSR_H_ */
seg_sync_integrator()
Definition: sssr_impl.h:80
static const int ATSC_DATA_SEGMENT_LENGTH
Definition: consts.h:33
quad_filter()
Definition: sssr_impl.h:103
#define ATSC_API
Definition: gr-atsc/include/gnuradio/atsc/api.h:30
quad filter (used to compute timing error)
Definition: sssr_impl.h:97
double w() const
Definition: sssr_impl.h:239
float sample_t
Definition: sssr_impl.h:42
double update(sample_t sample)
Definition: sssr_impl.h:110
int incr() const
Definition: sssr_impl.h:240
ATSC Segment and Symbol Sync Recovery.
Definition: sssr_impl.h:133
void reset()
called on channel change
Definition: sssr_impl.h:108
interpolator control for segment and symbol sync recovery
Definition: sssr_impl.h:199
void reset()
called on channel change
Definition: sssr_impl.h:58
digital_correlator()
Definition: sssr_impl.h:53
segment sync integrator
Definition: sssr_impl.h:74
bool update(int bit)
clock bit in and return true if we've seen 1001
Definition: sssr_impl.h:62
Compute intermediate samples between signal samples x(k*Ts)
Definition: mmse_fir_interpolator_ff.h:50
double mu() const
Definition: sssr_impl.h:238
digital correlator for 1001 and 0110 patterns
Definition: sssr_impl.h:47
unsigned ntaps() const
Definition: sssr_impl.h:235