GNU Radio 3.3.0 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2002 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 /* 00024 * --- ATSC Segment and Symbol Sync Recovery --- 00025 */ 00026 00027 #ifndef _ATSC_SSSR_H_ 00028 #define _ATSC_SSSR_H_ 00029 00030 #include <atsc_consts.h> 00031 #include <gri_mmse_fir_interpolator.h> 00032 #include <gr_single_pole_iir.h> 00033 #include <cstdio> 00034 00035 /* 00036 * --- support classes for atsci_sssr --- 00037 */ 00038 00039 namespace sssr { 00040 00041 typedef float sample_t; 00042 00043 // ---------------------------------------------------------------- 00044 //! digital correlator for 1001 and 0110 patterns 00045 00046 class digital_correlator { 00047 int d_sr; // 4 bit shift register 00048 00049 public: 00050 00051 // Constructor 00052 digital_correlator () { reset (); } 00053 00054 // Manipulators 00055 00056 //! called on channel change 00057 void reset () { d_sr = 0; } 00058 00059 //! clock bit in and return true if we've seen 1001 00060 00061 bool update (int bit) { 00062 d_sr = ((bit & 1) << 3) | (d_sr >> 1); 00063 00064 return (d_sr == 0x9); // 1001 00065 } 00066 00067 }; 00068 00069 00070 // ---------------------------------------------------------------- 00071 //! segment sync integrator 00072 00073 class seg_sync_integrator { 00074 signed char d_integrator[ATSC_DATA_SEGMENT_LENGTH]; 00075 00076 public: 00077 00078 // Constructor 00079 seg_sync_integrator () { reset (); } 00080 00081 // Manipulators 00082 00083 //! called on channel change 00084 void reset (); 00085 00086 //! update current tap with weight and return integrated correlation value 00087 int update (int weight, int index); 00088 00089 //! return index of maximum correlation value 00090 int find_max (int *value); 00091 00092 }; 00093 00094 // ---------------------------------------------------------------- 00095 //! quad filter (used to compute timing error) 00096 00097 class quad_filter { 00098 sample_t d_delay[4]; 00099 00100 public: 00101 // Constructor 00102 quad_filter () { reset (); } 00103 00104 // Manipulators 00105 00106 //! called on channel change 00107 void reset () { d_delay[0] = d_delay[1] = d_delay[2] = d_delay[3] = 0; } 00108 00109 double update (sample_t sample){ 00110 d_delay[3] = d_delay[2]; 00111 d_delay[2] = d_delay[1]; 00112 d_delay[1] = d_delay[0]; 00113 d_delay[0] = sample; 00114 00115 // the coefficients are -1,-1,+1,+1 00116 return d_delay[3] + d_delay[2] - d_delay[1] - d_delay[0]; 00117 } 00118 }; 00119 } 00120 00121 // ---------------------------------------------------------------- 00122 00123 /*! 00124 * \brief ATSC Segment and Symbol Sync Recovery 00125 * 00126 * This class implements data segment sync tracking and symbol timing 00127 * using the method described in "ATSC/VSB Tutorial - Receiver Technology" 00128 * by Wayne E. Bretl of Zenith, pgs 41-45. 00129 */ 00130 00131 class atsci_sssr { 00132 sssr::digital_correlator d_correlator; 00133 sssr::seg_sync_integrator d_integrator; 00134 sssr::quad_filter d_quad_filter; 00135 double d_quad_output[ATSC_DATA_SEGMENT_LENGTH]; 00136 double d_timing_adjust; 00137 int d_counter; // free running mod 832 counter 00138 int d_symbol_index; 00139 bool d_seg_locked; 00140 FILE *d_debug_fp; 00141 00142 00143 bool incr_counter () { 00144 d_counter++; 00145 if (d_counter >= ATSC_DATA_SEGMENT_LENGTH){ 00146 d_counter = 0; 00147 return true; 00148 } 00149 return false; 00150 } 00151 00152 void incr_symbol_index () { 00153 d_symbol_index++; 00154 if (d_symbol_index >= ATSC_DATA_SEGMENT_LENGTH) 00155 d_symbol_index = 0; 00156 } 00157 00158 public: 00159 00160 // Constructor 00161 atsci_sssr (); 00162 ~atsci_sssr (); 00163 00164 // Manipulators 00165 00166 //! call on channel change 00167 void reset (); 00168 00169 00170 /*! 00171 * \brief process a single sample at the ATSC symbol rate (~10.76 MSPS) 00172 * 00173 * This block computes an indication of our timing error and keeps 00174 * track of where the segment sync's occur. \p timing_adjust is 00175 * returned to indicate how the interpolator timing needs to be 00176 * adjusted to track the transmitter's symbol timing. If \p seg_locked 00177 * is true, then \p symbol_index is the index of this sample in 00178 * the current segment. The symbols are numbered from 0 to 831, where 00179 * symbols 0, 1, 2 and 3 correspond to the data segment sync pattern, 00180 * nominally +5, -5, -5, +5. 00181 */ 00182 00183 void update (sssr::sample_t sample_in, // input 00184 bool *seg_locked, // are we seeing segment syncs? 00185 int *symbol_index, // 0..831 00186 double *timing_adjust); // how much to adjust timing 00187 00188 }; 00189 00190 // ---------------------------------------------------------------- 00191 00192 /*! 00193 * \brief interpolator control for segment and symbol sync recovery 00194 */ 00195 00196 class atsci_interpolator { 00197 gri_mmse_fir_interpolator d_interp; 00198 gr_single_pole_iir<float,float,float> d_loop; // ``VCO'' loop filter 00199 double d_nominal_ratio_of_rx_clock_to_symbol_freq; // FREQ 00200 double d_w; // ratio of PERIOD of Tx to Rx clocks 00201 double d_mu; // fractional delay [0,1] 00202 int d_incr; // diagnostic only 00203 FILE *d_debug_fp; // diagnostic only 00204 00205 public: 00206 //! \p nominal_ratio_of_rx_clock_to_symbol_freq must be >= 1.8 00207 atsci_interpolator (double nominal_ratio_of_rx_clock_to_symbol_freq); 00208 ~atsci_interpolator (); 00209 00210 // Manipulators 00211 00212 //! call on channel change 00213 void reset (); 00214 00215 /*! 00216 * \brief produce next sample referenced to Tx clock 00217 * 00218 * If there aren't enough input_samples left to produce 00219 * an output, return false, else true. 00220 */ 00221 00222 bool update (const sssr::sample_t input_samples[], // I: vector of samples 00223 int nsamples, // I: total number of samples 00224 int *index, // I/O: current input index 00225 double timing_adjustment, // I: how much to bump timing 00226 sssr::sample_t *output_sample); // O: the output sample 00227 00228 // Accessors 00229 00230 // how much history we require on our input 00231 unsigned ntaps () const { return d_interp.ntaps (); } 00232 00233 // diagnostic accessors 00234 double mu () const { return d_mu; } 00235 double w () const { return d_w; } 00236 int incr () const { return d_incr; } 00237 00238 }; 00239 00240 #endif /* _ATSC_SSSR_H_ */