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