GNU Radio 3.7.0 C++ API
sssr_impl.h
Go to the documentation of this file.
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 <gnuradio/atsc/api.h>
00031 #include <gnuradio/atsc/consts.h>
00032 #include <gnuradio/filter/mmse_fir_interpolator_ff.h>
00033 #include <gnuradio/filter/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   gr::filter::mmse_fir_interpolator_ff d_interp;
00199   gr::filter::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_ */