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 #include <GrAtscBitTimingLoop.h>
25 #include "fpll_btloop_coupling.h"
27 #include <atsc_consts.h>
33 static const int DEC = 2; // nominal decimation factor
36 * I strongly suggest that you not mess with these...
38 static const double DEFAULT_TIMING_RATE = 2.19e-4 / FPLL_BTLOOP_COUPLING_CONST;
39 static const double DEFAULT_LOOP_TAP = 0.05;
42 GrAtscBitTimingLoop::GrAtscBitTimingLoop ()
43 : VrDecimatingSigProc<float,float> (1, DEC),
44 next_input(0), w (1.0), mu (0.5), last_right(0),
45 debug_no_update (false)
47 d_timing_rate = DEFAULT_TIMING_RATE;
48 loop.set_taps (DEFAULT_LOOP_TAP);
50 history = 1500; // spare input samples in case we need them.
52 #ifdef _BT_DIAG_OUTPUT_
53 fp_loop = fopen ("loop.out", "w");
59 fp_ps = fopen ("ps.out", "w");
68 // We are nominally a 2x decimator, but our actual rate varies slightly
69 // depending on the difference between the transmitter and receiver
70 // sampling clocks. Hence, we need to compute our input ranges
74 GrAtscBitTimingLoop::forecast(VrSampleRange output,
75 VrSampleRange inputs[]) {
76 /* dec:1 ratio with history */
77 for(unsigned int i=0;i<numberInputs;i++) {
78 inputs[i].index=next_input;
79 inputs[i].size=output.size*decimation + history-1;
85 GrAtscBitTimingLoop::filter_error (double e)
87 static const double limit = 50 * FPLL_BTLOOP_COUPLING_CONST;
96 return loop.filter (e);
100 GrAtscBitTimingLoop::work (VrSampleRange output, void *ao[],
101 VrSampleRange inputs[], void *ai[])
103 iType *in = ((iType **)ai)[0];
104 oType *out = ((oType **)ao)[0];
106 // Force in-order computation of output stream.
107 // This is required because of our slightly variable decimation factor
111 // We are tasked with producing output.size output samples.
112 // We will consume approximately 2 * output.size input samples.
115 unsigned int ii = 0; // input index
116 unsigned int k; // output index
118 // We look at a window of 3 samples that we call left (oldest),
119 // middle, right (newest). Each time through the loop, the previous
120 // right becomes the new left, and the new samples are middle and
123 // The basic game plan is to drive the average difference between
124 // right and left to zero. Given that all transitions are
125 // equiprobable (the data is white) and that the composite matched
126 // filter is symmetric (raised cosine) it turns out that in the
127 // average, if we drive that difference to zero, (implying that the
128 // average slope at the middle point is zero), we'll be sampling
129 // middle at the maximum or minimum point in the pulse.
133 iType right = last_right;
135 for (k = 0; k < output.size; k++){
138 middle = produce_sample (in, ii);
139 right = produce_sample (in, ii);
141 // assert (ii < inputs[0].size);
142 if (!(ii < inputs[0].size)){
143 fprintf (stderr, "ii < inputs[0].size\n");
144 fprintf (stderr, "ii = %d, inputs[0].size = %lu, k = %d, output.size = %lu\n",
145 ii, inputs[0].size, k, output.size);
150 out[k] = middle; // produce our output
152 double timing_error = -middle * ((double) right - left);
154 // update_timing_control_word
156 double filtered_timing_error = filter_error (timing_error);
158 if (!debug_no_update){
159 mu += filtered_timing_error * d_timing_rate;
162 #ifdef _BT_DIAG_OUTPUT_
167 iodata[3] = timing_error;
168 iodata[4] = filtered_timing_error;
172 if (fwrite (iodata, sizeof (iodata), 1, fp_loop) != 1){
173 perror ("fwrite: loop");
181 next_input += ii; // update next_input so forecast can get us what we need
186 * Produce samples equally spaced in time that are referenced
187 * to the transmitter's sample clock, not ours.
189 * See pp 523-527 of "Digital Communication Receivers", Meyr,
190 * Moeneclaey and Fechtel, Wiley, 1998.
193 GrAtscBitTimingLoop::iType
194 GrAtscBitTimingLoop::produce_sample (const iType *in, unsigned int &index)
196 // update mu and index as function of control word, w
199 double f = floor (sum);
200 int incr = (int) f; // mostly 1, rarely 0 or 2
203 assert (0 <= incr && incr <= 2);
204 assert (0.0 <= mu && mu <= 1.0);
208 iType n = intr.interpolate (&in[index], mu);
210 #if defined(_BT_DIAG_OUTPUT_) && 0
216 if (fwrite (iodata, sizeof (iodata), 1, fp_ps) != 1){
217 perror ("fwrite: ps");