Updated license from GPL version 2 or later to GPL version 3 or later.
[debian/gnuradio] / gr-atsc / src / lib / GrAtscBitTimingLoop2.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2002 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
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)
10  * any later version.
11  * 
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.
16  * 
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.
21  */
22
23 #include <GrAtscBitTimingLoop2.h>
24 #include <algorithm>
25 #include <atsc_consts.h>
26 #include <stdio.h>
27 #include <assert.h>
28
29
30 static const int        DEC = 2;        // nominal decimation factor
31
32 static const unsigned   AVG_WINDOW_LEN = 256;
33 static const float      TIMING_RATE_CONST = 1e-5;    // FIXME document interaction with AGC
34
35
36 GrAtscBitTimingLoop2::GrAtscBitTimingLoop2 ()
37   : VrDecimatingSigProc<float,float> (1, DEC),
38     next_input(0), dc (0.0002), mu (0.0), last_right(0), use_right_p (true)
39 {
40   history = 100;        // spare input samples in case we need them.
41
42 #ifdef _BT_DIAG_OUTPUT_
43   fp_loop = fopen ("loop.out", "w");
44   if (fp_loop == 0){
45     perror ("loop.out");
46     exit (1);
47   }
48     
49   fp_ps = fopen ("ps.out", "w");
50   if (fp_ps == 0){
51     perror ("ps.out");
52     exit (1);
53   }
54 #endif
55
56 }
57
58 //
59 // We are nominally a 2x decimator, but our actual rate varies slightly
60 // depending on the difference between the transmitter and receiver
61 // sampling clocks.  Hence, we need to compute our input ranges
62 // explictly.
63
64 int
65 GrAtscBitTimingLoop2::forecast(VrSampleRange output,
66                               VrSampleRange inputs[]) {
67   /* dec:1 ratio with history */
68   for(unsigned int i=0;i<numberInputs;i++) {
69     inputs[i].index=next_input;
70     inputs[i].size=output.size*decimation + history-1;
71   }
72   return 0;
73 }  
74
75 inline float
76 GrAtscBitTimingLoop2::filter_error (float e)
77 {
78   return e;     // identity function
79 }
80
81 int 
82 GrAtscBitTimingLoop2::work (VrSampleRange output, void *ao[],
83                            VrSampleRange inputs[], void *ai[])
84 {
85   iType  *in = ((iType **)ai)[0];
86   oType  *out = ((oType **)ao)[0];
87
88   // Force in-order computation of output stream.
89   // This is required because of our slightly variable decimation factor
90   sync (output.index);
91
92   
93   // We are tasked with producing output.size output samples.  
94   // We will consume approximately 2 * output.size input samples.
95
96
97   unsigned int  ii = 0;         // input index
98   unsigned int  k;              // output index
99
100   // We look at a window of 3 samples that we call left (oldest),
101   // middle, right (newest).  Each time through the loop, the previous
102   // right becomes the new left, and the new samples are middle and
103   // right.
104   //
105   // The basic game plan is to drive the average difference between
106   // right and left to zero.  Given that all transitions are
107   // equiprobable (the data is white) and that the composite matched
108   // filter is symmetric (raised cosine) it turns out that in the
109   // average, if we drive that difference to zero, (implying that the
110   // average slope at the middle point is zero), we'll be sampling
111   // middle at the maximum or minimum point in the pulse.
112
113   iType left;
114   iType middle;
115   iType right = last_right;
116
117   for (k = 0; k < output.size; k++){
118
119     left = right;
120     
121     iType middle_raw = produce_sample (in, ii);
122     iType middle_dc = dc.filter (middle_raw);
123     middle = middle_raw - middle_dc;
124
125     iType right_raw = produce_sample (in, ii);
126     iType right_dc = dc.filter (right_raw);
127     right = right_raw - right_dc;
128
129     if (use_right_p)    // produce our output
130       out[k] = right;   
131     else
132       out[k] = middle;
133   }
134
135 #ifdef _BT_DIAG_OUTPUT_
136   float iodata[8];
137   iodata[0] = 0;
138   iodata[1] = out[k];
139   iodata[2] = 0;
140   iodata[3] = 0;
141   iodata[4] = 0;
142   iodata[5] = mu;
143   iodata[6] = 0;
144   iodata[7] = 0;        // spare
145   if (fwrite (iodata, sizeof (iodata), 1, fp_loop) != 1){
146     perror ("fwrite: loop");
147     exit (1);
148   }
149 #endif
150
151
152   last_right = right;
153   next_input += ii;     // update next_input so forecast can get us what we need
154   return output.size;
155 }
156
157 /*!
158  * Produce samples equally spaced in time that are referenced
159  * to the transmitter's sample clock, not ours.
160  *
161  * See pp 523-527 of "Digital Communication Receivers", Meyr,
162  * Moeneclaey and Fechtel, Wiley, 1998.
163  */
164
165 GrAtscBitTimingLoop2::iType
166 GrAtscBitTimingLoop2::produce_sample (const iType *in, unsigned int &index)
167 {
168   iType n = intr.interpolate (&in[index], mu);
169
170   index++;
171   return n;
172 }
173