Houston, we have a trunk.
[debian/gnuradio] / gr-atsc / src / lib / atsc_field_sync_demux.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <cmath>
28 #include <atsc_field_sync_demux.h>
29 #include <gr_io_signature.h>
30 #include <atsc_types.h>
31 #include <atsc_consts.h>
32 #include <atsci_syminfo.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <iostream.h>
36
37 using std::abs;
38
39 static const int        DEC = ATSC_DATA_SEGMENT_LENGTH; // nominal decimation factor
40
41
42 atsc_field_sync_demux_sptr
43 atsc_make_field_sync_demux()
44 {
45   return atsc_field_sync_demux_sptr(new atsc_field_sync_demux());
46 }
47
48 atsc_field_sync_demux::atsc_field_sync_demux()
49   : gr_sync_decimator("atsc_field_sync_demux",
50                   gr_make_io_signature(2, 2, sizeof(float)),
51                   gr_make_io_signature(1, 1, sizeof(atsc_soft_data_segment)),DEC),
52                   d_locked(false), d_in_field2(true), d_segment_number(0),
53                   d_next_input(0), d_lost_index(0)
54 {
55   reset();
56 }
57
58 inline static bool
59 tag_is_seg_sync_or_field_sync (atsc::syminfo tag)
60 {
61   return tag.symbol_num == 0 && tag.valid;
62 }
63
64 void
65 atsc_field_sync_demux::forecast (int noutput_items, gr_vector_int &ninput_items_required)
66 {
67   unsigned ninputs = ninput_items_required.size();
68   for (unsigned i = 0; i < ninputs; i++) {
69     ninput_items_required[i] = noutput_items * DEC + 2 * DEC - 1;
70
71   inputs0_index = d_next_input;
72   inputs0_size = noutput_items * DEC + 2 * DEC - 1;
73   }
74 }
75
76
77 int
78 atsc_field_sync_demux::work (int noutput_items,
79                        gr_vector_const_void_star &input_items,
80                        gr_vector_void_star &output_items)
81 {
82   float *in = (float *) input_items[0];
83   atsc::syminfo *input_tags    = (atsc::syminfo *) input_items[1];
84   atsc_soft_data_segment *out = (atsc_soft_data_segment *) output_items[0];
85
86   assert(sizeof(float) == sizeof(atsc::syminfo));
87
88   int  ii = 0;         // input index
89
90   // Are we in sync?
91   if (!tag_is_seg_sync_or_field_sync (input_tags[0])){      // No ...
92
93     if (d_locked){
94       d_locked = false;
95       d_lost_index = inputs0_index + ii;
96       cerr << "atsc_field_sync_demux: lost sync at  "
97            << d_lost_index << endl;
98     }
99
100     // ... search for beginning of a field sync
101
102     // cerr << "atsc_field_sync_demux: searching for sync at "
103     //      << inputs0_index + ii << endl;
104
105     for (ii = 1; ii < inputs0_size; ii++){
106       if (atsc::tag_is_start_field_sync (input_tags[ii])){
107         // found one
108         d_locked = true;
109
110         const char *str;
111         if (atsc::tag_is_start_field_sync_1 (input_tags[ii]))
112           str = "FIELD-1";
113         else if (atsc::tag_is_start_field_sync_2 (input_tags[ii]))
114           str = "FIELD-2";
115         else
116           str = "SEGMENT";
117
118         cerr << "atsc_field_sync_demux: synced (" << str << ") at "
119              << inputs0_index + ii
120              << " [delta = " << inputs0_index + ii - d_lost_index
121              << "]\n";
122
123         d_next_input += ii;     // update for forecast
124         return 0;               // no work completed so far
125       }
126     }
127     // no non-NORMAL tag found
128     d_next_input += ii;         // update for forecast
129     return 0;                   // no work completed so far
130   }
131
132   // We are in sync.  Produce output...
133
134   int  k = 0;          // output index
135
136   while (k < noutput_items){
137
138     if (inputs0_size - ii <  ATSC_DATA_SEGMENT_LENGTH){
139       // We're out of input data.
140       cerr << "atsc_field_sync_demux: ran out of input data\n";
141       d_next_input += ii;       // update for forecast
142       return k;                 // return amount of work completed so far
143     }
144
145     if (!tag_is_seg_sync_or_field_sync (input_tags[ii])){
146       // lost sync...
147       cerr << "atsc_field_sync_demux: lost sync at "
148            << inputs0_index + ii << endl;
149
150       d_next_input += ii;       // update for forecast
151       return k;                 // return amount of work completed so far
152     }
153
154     if (atsc::tag_is_start_field_sync_1 (input_tags[ii])){
155       d_in_field2 = false;
156       d_segment_number = 0;
157       ii += ATSC_DATA_SEGMENT_LENGTH;   // skip over field sync
158       continue;
159     }
160
161     if (atsc::tag_is_start_field_sync_2 (input_tags[ii])){
162       d_in_field2 = true;
163       d_segment_number = 0;
164       ii += ATSC_DATA_SEGMENT_LENGTH;   // skip over field sync
165       continue;
166     }
167
168     if (d_segment_number >= ATSC_DSEGS_PER_FIELD){
169       // something's wrong...
170       cerr << "atsc_field_sync_demux: segment number overflow\n";
171       d_segment_number = 0;
172     }
173
174     out[k].pli.set_regular_seg (d_in_field2, d_segment_number++);
175     for (int jj = 0; jj < ATSC_DATA_SEGMENT_LENGTH; jj++)
176       out[k].data[jj] = in[ii + jj];
177     ii += ATSC_DATA_SEGMENT_LENGTH;
178     k++;
179   }
180
181   d_next_input += ii;           // update for forecast
182   return k;                     // return amount of work completed
183
184 }
185
186
187
188