070c901ad01f7bde2a7e614a02be4e791a7da27b
[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., 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 <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_block("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))),
52                   d_locked(false), d_in_field2(true), d_segment_number(0),
53                   d_next_input(0), d_lost_index(0), d_inputs0_size(0),
54                   d_inputs0_index(0), d_consume(0)
55 {
56   reset();
57 }
58
59 inline static bool
60 tag_is_seg_sync_or_field_sync (atsc::syminfo tag)
61 {
62   return tag.symbol_num == 0 && tag.valid;
63 }
64
65 void
66 atsc_field_sync_demux::forecast (int noutput_items, gr_vector_int &ninput_items_required)
67 {
68   unsigned ninputs = ninput_items_required.size();
69   for (unsigned i = 0; i < ninputs; i++) {
70     ninput_items_required[i] = noutput_items * DEC + 2 * DEC ;
71
72   d_inputs0_index = d_next_input;
73   d_inputs0_size = noutput_items * DEC + 2 * DEC ;
74   }
75 }
76
77 int
78 atsc_field_sync_demux::general_work (int noutput_items,
79                                  gr_vector_int &ninput_items,
80                                  gr_vector_const_void_star &input_items,
81                                  gr_vector_void_star &output_items)
82 {
83   int   r = work (noutput_items, input_items, output_items);
84     consume_each (d_consume);
85     // printf("Consumed: %d, produced: %d\n",d_consume,r);
86     // we consume input even if no output is produced
87     // while looking for sync
88   return r;
89 }
90
91
92 int
93 atsc_field_sync_demux::work (int noutput_items,
94                        gr_vector_const_void_star &input_items,
95                        gr_vector_void_star &output_items)
96 {
97   float *in = (float *) input_items[0];
98   atsc::syminfo *input_tags    = (atsc::syminfo *) input_items[1];
99   atsc_soft_data_segment *out = (atsc_soft_data_segment *) output_items[0];
100
101   assert(sizeof(float) == sizeof(atsc::syminfo));
102
103   int  ii = 0;         // input index
104
105   // Are we in sync?
106   if (!tag_is_seg_sync_or_field_sync (input_tags[0])){      // No ...
107
108     if (d_locked){
109       d_locked = false;
110       d_lost_index = d_inputs0_index + ii;
111       cerr << "atsc_field_sync_demux: lost sync at  "
112            << d_lost_index << endl;
113     }
114
115     // ... search for beginning of a field sync
116
117     // cerr << "atsc_field_sync_demux: searching for sync at "
118     //      << d_inputs0_index + ii << endl;
119
120     for (ii = 1; ii < d_inputs0_size; ii++){
121       if (atsc::tag_is_start_field_sync (input_tags[ii])){
122         // found one
123         d_locked = true;
124
125         const char *str;
126         if (atsc::tag_is_start_field_sync_1 (input_tags[ii]))
127           str = "FIELD-1";
128         else if (atsc::tag_is_start_field_sync_2 (input_tags[ii]))
129           str = "FIELD-2";
130         else
131           str = "SEGMENT";
132
133         cerr << "atsc_field_sync_demux: synced (" << str << ") at "
134              << d_inputs0_index + ii
135              << " [delta = " << d_inputs0_index + ii - d_lost_index
136              << "]\n";
137
138         d_next_input += ii;     // update for forecast
139         d_consume = ii;
140         return 0;               // no work completed so far
141       }
142     }
143     // no non-NORMAL tag found
144     d_next_input += ii;         // update for forecast
145     d_consume = ii;
146     // printf("ii: %d, d_next_input: %d\n",ii,d_next_input);
147     return 0;                   // no work completed so far
148   }
149
150   // We are in sync.  Produce output...
151
152   int  k = 0;          // output index
153
154   while (k < noutput_items){
155
156     if (d_inputs0_size - ii <  ATSC_DATA_SEGMENT_LENGTH){
157       // We're out of input data.
158       cerr << "atsc_field_sync_demux: ran out of input data\n";
159       d_next_input += ii;       // update for forecast
160       return k;                 // return amount of work completed so far
161     }
162
163     if (!tag_is_seg_sync_or_field_sync (input_tags[ii])){
164       // lost sync...
165       cerr << "atsc_field_sync_demux: lost sync at "
166            << d_inputs0_index + ii << endl;
167
168       d_next_input += ii;       // update for forecast
169       return k;                 // return amount of work completed so far
170     }
171
172     if (atsc::tag_is_start_field_sync_1 (input_tags[ii])){
173       d_in_field2 = false;
174       d_segment_number = 0;
175       ii += ATSC_DATA_SEGMENT_LENGTH;   // skip over field sync
176       continue;
177     }
178
179     if (atsc::tag_is_start_field_sync_2 (input_tags[ii])){
180       d_in_field2 = true;
181       d_segment_number = 0;
182       ii += ATSC_DATA_SEGMENT_LENGTH;   // skip over field sync
183       continue;
184     }
185
186     if (d_segment_number >= ATSC_DSEGS_PER_FIELD){
187       // something's wrong...
188       cerr << "atsc_field_sync_demux: segment number overflow\n";
189       d_segment_number = 0;
190     }
191
192     out[k].pli.set_regular_seg (d_in_field2, d_segment_number++);
193     for (int jj = 0; jj < ATSC_DATA_SEGMENT_LENGTH; jj++)
194       out[k].data[jj] = in[ii + jj];
195     ii += ATSC_DATA_SEGMENT_LENGTH;
196     k++;
197   }
198
199   d_next_input += ii;           // update for forecast
200   d_consume = ii;
201   return k;                     // return amount of work completed
202
203 }
204
205
206
207