summaryrefslogtreecommitdiff
path: root/gr-atsc/src/lib/atsci_sssr.h
blob: a6ec8109b07b96a79c77f8256e219e7146648d22 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/* -*- c++ -*- */
/*
 * Copyright 2002 Free Software Foundation, Inc.
 * 
 * This file is part of GNU Radio
 * 
 * GNU Radio is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 * 
 * GNU Radio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with GNU Radio; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

/*
 *   --- ATSC Segment and Symbol Sync Recovery ---
 */

#ifndef _ATSC_SSSR_H_
#define _ATSC_SSSR_H_

#include <atsc_consts.h>
#include <gri_mmse_fir_interpolator.h>
#include <gr_single_pole_iir.h>
#include <cstdio>

/*
 *   --- support classes for atsci_sssr ---
 */

namespace sssr {

  typedef float sample_t;

  // ----------------------------------------------------------------
  //! digital correlator for 1001 and 0110 patterns

  class digital_correlator {
    int		d_sr;	// 4 bit shift register

  public:
    
    // Constructor
    digital_correlator () { reset (); }

    // Manipulators

    //! called on channel change
    void reset () { d_sr = 0; }

    //! clock bit in and return true if we've seen 1001

    bool update (int bit) {
      d_sr = ((bit & 1) << 3) | (d_sr >> 1);

      return (d_sr == 0x9);	// 1001
    }

  };


  // ----------------------------------------------------------------
  //! segment sync integrator

  class seg_sync_integrator {
    signed char	d_integrator[ATSC_DATA_SEGMENT_LENGTH];
    
  public:

    // Constructor
    seg_sync_integrator () { reset (); }

    // Manipulators

    //! called on channel change
    void reset ();
    
    //! update current tap with weight and return integrated correlation value
    int update (int weight, int index);

    //! return index of maximum correlation value
    int find_max (int *value);

  };
  
  // ----------------------------------------------------------------
  //! quad filter (used to compute timing error)

  class quad_filter {
    sample_t	d_delay[4];

  public:
    // Constructor
    quad_filter () { reset (); }

    // Manipulators

    //! called on channel change
    void reset () { d_delay[0] = d_delay[1] = d_delay[2] = d_delay[3] = 0; }

    double update (sample_t sample){
      d_delay[3] = d_delay[2];
      d_delay[2] = d_delay[1];
      d_delay[1] = d_delay[0];
      d_delay[0] = sample;

      // the coefficients are -1,-1,+1,+1
      return d_delay[3] + d_delay[2] - d_delay[1] - d_delay[0];
    }
  };
}

// ----------------------------------------------------------------

/*!
 * \brief ATSC Segment and Symbol Sync Recovery
 *
 * This class implements data segment sync tracking and symbol timing
 * using the method described in "ATSC/VSB Tutorial - Receiver Technology"
 * by Wayne E. Bretl of Zenith, pgs 41-45.
 */

class atsci_sssr {
  sssr::digital_correlator	d_correlator;
  sssr::seg_sync_integrator	d_integrator;
  sssr::quad_filter		d_quad_filter;
  double			d_quad_output[ATSC_DATA_SEGMENT_LENGTH];
  double			d_timing_adjust;
  int				d_counter;	// free running mod 832 counter
  int				d_symbol_index;
  bool				d_seg_locked;
  FILE			       *d_debug_fp;

  
  bool incr_counter () {
    d_counter++;
    if (d_counter >= ATSC_DATA_SEGMENT_LENGTH){
      d_counter = 0;
      return true;
    }
    return false;
  }
    
  void incr_symbol_index () {
    d_symbol_index++;
    if (d_symbol_index >= ATSC_DATA_SEGMENT_LENGTH)
      d_symbol_index = 0;
  }

public:

  // Constructor
  atsci_sssr ();
  ~atsci_sssr ();

  // Manipulators

  //! call on channel change
  void reset ();


  /*!
   * \brief process a single sample at the ATSC symbol rate (~10.76 MSPS)
   *
   * This block computes an indication of our timing error and keeps
   * track of where the segment sync's occur.  \p timing_adjust is
   * returned to indicate how the interpolator timing needs to be
   * adjusted to track the transmitter's symbol timing.  If \p seg_locked
   * is true, then \p symbol_index is the index of this sample in 
   * the current segment.  The symbols are numbered from 0 to 831, where 
   * symbols 0, 1, 2 and 3 correspond to the data segment sync pattern, 
   * nominally +5, -5, -5, +5.
   */

  void update (sssr::sample_t  sample_in,	// input
	       bool	      *seg_locked,	// are we seeing segment syncs?
	       int	      *symbol_index,	// 0..831
	       double	      *timing_adjust);	// how much to adjust timing

};

// ----------------------------------------------------------------

/*!
 * \brief interpolator control for segment and symbol sync recovery
 */
 
class atsci_interpolator {
  gri_mmse_fir_interpolator	d_interp;
  gr_single_pole_iir<float,float,float> d_loop;	// ``VCO'' loop filter
  double			d_nominal_ratio_of_rx_clock_to_symbol_freq; // FREQ
  double			d_w;	// ratio of PERIOD of Tx to Rx clocks
  double			d_mu;	// fractional delay [0,1]
  int				d_incr;		// diagnostic only
  FILE			       *d_debug_fp;	// diagnostic only

public:
  //! \p nominal_ratio_of_rx_clock_to_symbol_freq must be >= 1.8
  atsci_interpolator (double nominal_ratio_of_rx_clock_to_symbol_freq);
  ~atsci_interpolator ();

  // Manipulators

  //! call on channel change
  void reset ();

  /*!
   * \brief produce next sample referenced to Tx clock
   *
   * If there aren't enough input_samples left to produce
   * an output, return false, else true.
   */

  bool update (const sssr::sample_t input_samples[],	// I: vector of samples
	       int	      	    nsamples,		// I: total number of samples
	       int	           *index,		// I/O: current input index
	       double		    timing_adjustment,	// I: how much to bump timing
	       sssr::sample_t	   *output_sample);	// O: the output sample

  // Accessors

  // how much history we require on our input
  unsigned ntaps () const { return d_interp.ntaps (); }

  // diagnostic accessors
  double mu ()   const { return d_mu; }
  double w ()    const { return d_w;  }
  int	 incr () const { return d_incr; }
  
};

#endif /* _ATSC_SSSR_H_ */