Merge commit 'v3.3.0' into upstream
[debian/gnuradio] / gr-atsc / src / lib / qa_atsci_fs_correlator.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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <qa_atsci_fs_correlator.h>
28 #include <atsci_fs_correlator.h>
29 #include <create_atsci_fs_correlator.h>
30 #include <atsci_sync_tag.h>
31 #include <stdlib.h>
32 #include <algorithm>
33 #include <atsci_pnXXX.h>
34 #include <atsc_types.h>
35 #include <cppunit/TestAssert.h>
36 #include <assert.h>
37 #include <random.h>
38
39
40 static float
41 uniform ()
42 {
43   return 2.0 * ((float) random () / RANDOM_MAX - 0.5);  // uniformly (-1, 1)
44 }
45
46
47 static float
48 bin_map (int bit)
49 {
50   return bit ? +5 : -5;
51 }
52
53 static void
54 init_field_sync_common (float *p, int mask)
55                         
56 {
57   int  i = 0;
58
59   p[i++] = bin_map(1);                  // data segment sync pulse
60   p[i++] = bin_map(0);
61   p[i++] = bin_map(0);
62   p[i++] = bin_map(1);
63
64   for (int j = 0; j < 511; j++)         // PN511
65     p[i++] = bin_map(atsc_pn511[j]);
66
67   for (int j = 0; j < 63; j++)          // PN63
68     p[i++] = bin_map(atsc_pn63[j]);
69
70   for (int j = 0; j < 63; j++)          // PN63, toggled on field 2
71     p[i++] = bin_map(atsc_pn63[j] ^ mask);
72   
73   for (int j = 0; j < 63; j++)          // PN63
74     p[i++] = bin_map(atsc_pn63[j]);
75
76   p[i++] = bin_map(0);                  // 24 bits of VSB8 mode identifiera
77   p[i++] = bin_map(0);
78   p[i++] = bin_map(0);
79   p[i++] = bin_map(0);
80
81   p[i++] = bin_map(1);
82   p[i++] = bin_map(0);
83   p[i++] = bin_map(1);
84   p[i++] = bin_map(0);
85
86   p[i++] = bin_map(0);
87   p[i++] = bin_map(1);
88   p[i++] = bin_map(0);
89   p[i++] = bin_map(1);
90
91   p[i++] = bin_map(1);
92   p[i++] = bin_map(1);
93   p[i++] = bin_map(1);
94   p[i++] = bin_map(1);
95
96   p[i++] = bin_map(0);
97   p[i++] = bin_map(1);
98   p[i++] = bin_map(0);
99   p[i++] = bin_map(1);
100
101   p[i++] = bin_map(1);
102   p[i++] = bin_map(0);
103   p[i++] = bin_map(1);
104   p[i++] = bin_map(0);
105
106
107   for (int j = 0; j < 92; j++)          // 92 more bits
108     p[i++] = bin_map(atsc_pn63[j % 63]);
109
110   // now copy the last 12 symbols of the previous segment
111   // bogus pad for this test...
112
113   for (int j = 0; j < 12; j++)
114     p[i++] = bin_map(j & 1);
115
116   assert (i == ATSC_DATA_SEGMENT_LENGTH);
117 }
118
119 inline static void
120 init_field_sync_1 (float *s)
121 {
122   init_field_sync_common (s, 0);
123 }
124
125 inline static void
126 init_field_sync_2 (float *s)
127 {
128   init_field_sync_common (s, 1);
129 }
130
131 static void
132 cause_errors (float *p, int nerrs1, int nerrs2)
133 {
134   static const int offset1 =   4;       // offset to PN 511
135   static const int offset2 = 578;       // offset to 2nd PN 63
136
137   for (int i = 0; i < nerrs1; i++){     // flip nerrs1 bits in PN 511
138     p[i + offset1] = -p[i + offset1];
139   }
140
141   for (int i = 0; i < nerrs2; i++){     // flip nerrs2 bits in PN 63
142     p[i + offset2] = -p[i + offset2];
143   }
144 }
145
146
147 void
148 qa_atsci_fs_correlator::setUp ()
149 {
150   fsc = create_atsci_fs_correlator ();
151 }
152
153 void
154 qa_atsci_fs_correlator::tearDown ()
155 {
156   delete fsc;
157   fsc = 0;
158 }
159
160
161 // check sample fifo
162
163 void
164 qa_atsci_fs_correlator::t0 ()
165 {
166   int   delay = fsc->delay ();
167   int   i;
168   float output_sample, output_tag;
169
170   for (i = 0; i < delay; i++){
171     fsc->filter ((float) i, &output_sample, &output_tag);
172     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, output_sample, 1e-6);
173     CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::NORMAL, output_tag, 1e-6);
174   }
175
176   for (; i < delay + 5000; i++){
177     fsc->filter ((float) i, &output_sample, &output_tag);
178     CPPUNIT_ASSERT_DOUBLES_EQUAL ((float) (i - delay), output_sample, 1e-6);
179     CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::NORMAL, output_tag, 1e-6);
180   }
181 }
182
183 void
184 qa_atsci_fs_correlator::util (int which_field, int nerrs1, int nerrs2)
185 {
186   static const int PAD = 303;
187   static const int ISIZE = 4096;
188   int   delay = fsc->delay ();
189   float output_sample, output_tag;
190   int   i;
191   float input[ISIZE];
192
193   fsc->reset ();        // known starting conditions
194   
195   // build input
196   
197   for (i = 0; i < PAD; i++)
198     input[i] = uniform () * 7;
199
200   init_field_sync_common (&input[i], which_field);
201   cause_errors (&input[i], nerrs1, nerrs2);
202   i += ATSC_DATA_SEGMENT_LENGTH;
203
204   for (; i < ISIZE; i++)
205     input[i] = uniform () * 7;
206
207   // run the input and check
208   
209   for (i = 0; i < ISIZE; i++){
210     fsc->filter (input[i], &output_sample, &output_tag);
211     if (i == delay + PAD){      // should be field sync
212       if (which_field == 0)
213         CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::START_FIELD_SYNC_1, output_tag, 1e-6);
214       else
215         CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::START_FIELD_SYNC_2, output_tag, 1e-6);
216     }
217     else {
218       CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::NORMAL, output_tag, 1e-6);
219     }
220   }
221 }
222
223
224 void
225 qa_atsci_fs_correlator::t1 ()
226 {
227   util (0, 0, 0);
228 }
229
230 void
231 qa_atsci_fs_correlator::t2 ()
232 {
233   util (1, 0, 0);
234 }
235
236 void
237 qa_atsci_fs_correlator::t3 ()
238 {
239   for (int nerrs1 = 0; nerrs1 < 20; nerrs1++){
240     for (int nerrs2 = 0; nerrs2 < 5; nerrs2++){
241       util (0, nerrs1, nerrs2);
242     }
243   }
244 }
245
246 void
247 qa_atsci_fs_correlator::t4 ()
248 {
249   for (int nerrs1 = 0; nerrs1 < 5; nerrs1++){
250     for (int nerrs2 = 0; nerrs2 < 5; nerrs2++){
251       util (1, nerrs1, nerrs2);
252     }
253   }
254 }
255