Houston, we have a trunk.
[debian/gnuradio] / gr-atsc / src / lib / atsci_fs_correlator_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_correlator_naive.h>
24 #include <atsci_sync_tag.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_correlator_naive::s_511[LENGTH_511];
36 unsigned char atsci_fs_correlator_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_correlator_naive::atsci_fs_correlator_naive ()
60 {
61   init_s_511 (s_511);
62   init_s_63 (s_63);
63   reset ();
64 }
65
66 atsci_fs_correlator_naive::~atsci_fs_correlator_naive ()
67 {
68 }
69
70 void
71 atsci_fs_correlator_naive::reset ()
72 {
73   d_index = 0;
74   memset (d_sample_sr, 0, sizeof (d_sample_sr));
75   memset (d_bit_sr, 0, sizeof (d_bit_sr));
76 }
77
78 void
79 atsci_fs_correlator_naive::filter (float input_sample,
80                                   float *output_sample, float *output_tag)
81 {
82   // check for a hit on the PN 511 pattern
83   int   errors = 0;
84   int   start = wrap (d_index + OFFSET_511);
85
86   for (int i = 0; i < LENGTH_511 && errors < PN511_ERROR_LIMIT; i++)
87     errors += d_bit_sr[wrap (start + i)] ^ s_511[i];
88
89   if (errors >= PN511_ERROR_LIMIT)
90     *output_tag = atsc_sync_tag::NORMAL;
91
92   else {        // 511 pattern is good.  determine if this is field 1 or field 2
93     errors = 0;
94     start = wrap (d_index + OFFSET_2ND_63);
95     for (int i = 0; i < LENGTH_2ND_63; i++)
96       errors += d_bit_sr[wrap (start + i)] ^ s_63[i];
97
98     // we should have either field 1 (== PN63) or field 2 (== ~PN63)
99     if (errors <= PN63_ERROR_LIMIT)
100       *output_tag = atsc_sync_tag::START_FIELD_SYNC_1;
101
102     else if (errors >= (LENGTH_2ND_63 - PN63_ERROR_LIMIT))
103       *output_tag = atsc_sync_tag::START_FIELD_SYNC_2;
104
105     else {
106       // should be extremely rare.
107       cerr << "!!! atsci_fs_correlator_naive: PN63 error count = " << errors << endl;
108       *output_tag = atsc_sync_tag::NORMAL;
109     }
110   }
111
112   // return oldest sample
113   *output_sample = d_sample_sr[d_index];
114
115   // overwrite with newest sample;
116   d_sample_sr[d_index] = input_sample;
117   d_bit_sr[d_index] = input_sample < 0 ? 0 : 1;
118   d_index = incr (d_index);
119 }
120
121 int
122 atsci_fs_correlator_naive::delay () const
123 {
124   return SRSIZE;
125 }