Houston, we have a trunk.
[debian/gnuradio] / gr-atsc / src / lib / atsci_fs_checker_naive.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 2, 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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <atsci_fs_checker_naive.h>
24 #include <atsci_syminfo.h>
25 #include <atsci_pnXXX.h>
26 #include <iostream>
27 #include <cstring>
28
29 using std::cerr;
30 using std::endl;
31
32 static const int PN511_ERROR_LIMIT = 20;        // max number of bits wrong
33 static const int PN63_ERROR_LIMIT =   5;
34
35 unsigned char atsci_fs_checker_naive::s_511[LENGTH_511];
36 unsigned char atsci_fs_checker_naive::s_63[LENGTH_2ND_63];
37
38 static void
39 init_s_511 (unsigned char *p)
40 {
41   *p++ = 1;     // data segment sync pattern
42   *p++ = 0;
43   *p++ = 0;
44   *p++ = 1;
45
46   for (int i = 0; i < 511; i++){
47     p[i] = atsc_pn511[i];
48   }
49 }
50
51 static void
52 init_s_63 (unsigned char *p)
53 {
54   for (int i = 0; i < 63; i++){
55     p[i] = atsc_pn63[i];
56   }
57 }
58
59 atsci_fs_checker_naive::atsci_fs_checker_naive ()
60 {
61   init_s_511 (s_511);
62   init_s_63 (s_63);
63   reset ();
64 }
65
66 atsci_fs_checker_naive::~atsci_fs_checker_naive ()
67 {
68 }
69
70 void
71 atsci_fs_checker_naive::reset ()
72 {
73   d_index = 0;
74   memset (d_sample_sr, 0, sizeof (d_sample_sr));
75   memset (d_tag_sr, 0, sizeof (d_tag_sr));
76   memset (d_bit_sr, 0, sizeof (d_bit_sr));
77   d_field_num = 0;
78   d_segment_num = 0;
79 }
80
81 void
82 atsci_fs_checker_naive::filter (float input_sample, atsc::syminfo input_tag,
83                                float *output_sample, atsc::syminfo *output_tag)
84 {
85   atsc::syminfo proto_tag = d_tag_sr[d_index];  // oldest tag in the queue
86
87   if (proto_tag.symbol_num == 0){               // check for field sync pattern
88     
89     d_segment_num = (d_segment_num + 1) & atsc::SI_SEGMENT_NUM_MASK;  // increment
90
91     // check for a hit on the PN 511 pattern
92     int errors = 0;
93     int start = wrap (d_index + OFFSET_511);
94
95     for (int i = 0; i < LENGTH_511 && errors < PN511_ERROR_LIMIT; i++)
96       errors += d_bit_sr[wrap (start + i)] ^ s_511[i];
97
98     if (errors < PN511_ERROR_LIMIT){    // 511 pattern is good.
99                                         // determine if this is field 1 or field 2
100       errors = 0;
101       start = wrap (d_index + OFFSET_2ND_63);
102       for (int i = 0; i < LENGTH_2ND_63; i++)
103         errors += d_bit_sr[wrap (start + i)] ^ s_63[i];
104
105       // we should have either field 1 (== PN63) or field 2 (== ~PN63)
106
107       if (errors <= PN63_ERROR_LIMIT){
108         d_segment_num = atsc::SI_FIELD_SYNC_SEGMENT_NUM;        // this is FIELD_SYNC_1
109         d_field_num = 0;
110       }
111       else if (errors >= (LENGTH_2ND_63 - PN63_ERROR_LIMIT)){
112         d_segment_num = atsc::SI_FIELD_SYNC_SEGMENT_NUM;        // this is FIELD_SYNC_2
113         d_field_num = 1;
114       }
115       else {
116         // should be extremely rare.
117         cerr << "!!! atsci_fs_checker_naive: PN63 error count = " << errors << endl;
118       }
119     }
120   }
121
122   proto_tag.segment_num = d_segment_num;        // fill in segment number and field number      
123   proto_tag.field_num = d_field_num;
124
125   // return oldest sample
126   *output_sample = d_sample_sr[d_index];
127   *output_tag    = proto_tag;
128
129   // overwrite with newest sample;
130   d_sample_sr[d_index] = input_sample;
131   d_bit_sr[d_index] = input_sample < 0 ? 0 : 1;
132   d_tag_sr[d_index] = input_tag;
133   d_index = incr (d_index);
134 }
135
136 int
137 atsci_fs_checker_naive::delay () const
138 {
139   return SRSIZE;
140 }