3 * Copyright 2002 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
24 * --- ATSC Segment and Symbol Sync Recovery ---
30 #include <atsc_consts.h>
31 #include <gri_mmse_fir_interpolator.h>
32 #include <gr_single_pole_iir.h>
36 * --- support classes for atsci_sssr ---
41 typedef float sample_t;
43 // ----------------------------------------------------------------
44 //! digital correlator for 1001 and 0110 patterns
46 class digital_correlator {
47 int d_sr; // 4 bit shift register
52 digital_correlator () { reset (); }
56 //! called on channel change
57 void reset () { d_sr = 0; }
59 //! clock bit in and return true if we've seen 1001
61 bool update (int bit) {
62 d_sr = ((bit & 1) << 3) | (d_sr >> 1);
64 return (d_sr == 0x9); // 1001
70 // ----------------------------------------------------------------
71 //! segment sync integrator
73 class seg_sync_integrator {
74 signed char d_integrator[ATSC_DATA_SEGMENT_LENGTH];
79 seg_sync_integrator () { reset (); }
83 //! called on channel change
86 //! update current tap with weight and return integrated correlation value
87 int update (int weight, int index);
89 //! return index of maximum correlation value
90 int find_max (int *value);
94 // ----------------------------------------------------------------
95 //! quad filter (used to compute timing error)
102 quad_filter () { reset (); }
106 //! called on channel change
107 void reset () { d_delay[0] = d_delay[1] = d_delay[2] = d_delay[3] = 0; }
109 double update (sample_t sample){
110 d_delay[3] = d_delay[2];
111 d_delay[2] = d_delay[1];
112 d_delay[1] = d_delay[0];
115 // the coefficients are -1,-1,+1,+1
116 return d_delay[3] + d_delay[2] - d_delay[1] - d_delay[0];
121 // ----------------------------------------------------------------
124 * \brief ATSC Segment and Symbol Sync Recovery
126 * This class implements data segment sync tracking and symbol timing
127 * using the method described in "ATSC/VSB Tutorial - Receiver Technology"
128 * by Wayne E. Bretl of Zenith, pgs 41-45.
132 sssr::digital_correlator d_correlator;
133 sssr::seg_sync_integrator d_integrator;
134 sssr::quad_filter d_quad_filter;
135 double d_quad_output[ATSC_DATA_SEGMENT_LENGTH];
136 double d_timing_adjust;
137 int d_counter; // free running mod 832 counter
143 bool incr_counter () {
145 if (d_counter >= ATSC_DATA_SEGMENT_LENGTH){
152 void incr_symbol_index () {
154 if (d_symbol_index >= ATSC_DATA_SEGMENT_LENGTH)
166 //! call on channel change
171 * \brief process a single sample at the ATSC symbol rate (~10.76 MSPS)
173 * This block computes an indication of our timing error and keeps
174 * track of where the segment sync's occur. \p timing_adjust is
175 * returned to indicate how the interpolator timing needs to be
176 * adjusted to track the transmitter's symbol timing. If \p seg_locked
177 * is true, then \p symbol_index is the index of this sample in
178 * the current segment. The symbols are numbered from 0 to 831, where
179 * symbols 0, 1, 2 and 3 correspond to the data segment sync pattern,
180 * nominally +5, -5, -5, +5.
183 void update (sssr::sample_t sample_in, // input
184 bool *seg_locked, // are we seeing segment syncs?
185 int *symbol_index, // 0..831
186 double *timing_adjust); // how much to adjust timing
190 // ----------------------------------------------------------------
193 * \brief interpolator control for segment and symbol sync recovery
196 class atsci_interpolator {
197 gri_mmse_fir_interpolator d_interp;
198 gr_single_pole_iir<float,float,float> d_loop; // ``VCO'' loop filter
199 double d_nominal_ratio_of_rx_clock_to_symbol_freq; // FREQ
200 double d_w; // ratio of PERIOD of Tx to Rx clocks
201 double d_mu; // fractional delay [0,1]
202 int d_incr; // diagnostic only
203 FILE *d_debug_fp; // diagnostic only
206 //! \p nominal_ratio_of_rx_clock_to_symbol_freq must be >= 1.8
207 atsci_interpolator (double nominal_ratio_of_rx_clock_to_symbol_freq);
208 ~atsci_interpolator ();
212 //! call on channel change
216 * \brief produce next sample referenced to Tx clock
218 * If there aren't enough input_samples left to produce
219 * an output, return false, else true.
222 bool update (const sssr::sample_t input_samples[], // I: vector of samples
223 int nsamples, // I: total number of samples
224 int *index, // I/O: current input index
225 double timing_adjustment, // I: how much to bump timing
226 sssr::sample_t *output_sample); // O: the output sample
230 // how much history we require on our input
231 unsigned ntaps () const { return d_interp.ntaps (); }
233 // diagnostic accessors
234 double mu () const { return d_mu; }
235 double w () const { return d_w; }
236 int incr () const { return d_incr; }
240 #endif /* _ATSC_SSSR_H_ */