Merge commit 'v3.3.0' into upstream
[debian/gnuradio] / gr-atsc / src / lib / atsc_field_sync_mux.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 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 <atsc_field_sync_mux.h>
28 #include <gr_io_signature.h>
29 #include <atsc_consts.h>
30 #include <atsci_pnXXX.h>
31
32
33 atsc_field_sync_mux_sptr
34 atsc_make_field_sync_mux()
35 {
36   return atsc_field_sync_mux_sptr(new atsc_field_sync_mux());
37 }
38
39 atsc_field_sync_mux::atsc_field_sync_mux()
40   : gr_sync_block("atsc_field_sync_mux",
41                   gr_make_io_signature(1, 1, sizeof(atsc_data_segment)),
42                   gr_make_io_signature(1, 1, sizeof(atsc_data_segment)))
43 {
44   reset();
45 }
46
47 static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one)
48
49 static const int N_SAVED_SYMBOLS = atsc_field_sync_mux::N_SAVED_SYMBOLS;
50
51 static void
52 init_field_sync_common (unsigned char *p, int mask,
53                         const unsigned char saved_symbols[N_SAVED_SYMBOLS])
54 {
55   static const unsigned char bin_map[2] = { 1, 6 };  // map binary values to 1 of 8 levels
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
112   for (int j = 0; j < N_SAVED_SYMBOLS; j++)
113     p[i++] = saved_symbols[j];
114
115   assert (i == ATSC_DATA_SEGMENT_LENGTH);
116 }
117 inline static void
118 init_field_sync_1 (atsc_data_segment *s,
119                    const unsigned char saved_symbols[N_SAVED_SYMBOLS])
120 {
121   init_field_sync_common (&s->data[0], 0, saved_symbols);
122 }
123
124 inline static void
125 init_field_sync_2 (atsc_data_segment *s,
126                    const unsigned char saved_symbols[N_SAVED_SYMBOLS])
127
128 {
129   init_field_sync_common (&s->data[0], 1, saved_symbols);
130 }
131
132 static void
133 save_last_symbols (unsigned char saved_symbols[N_SAVED_SYMBOLS],
134                    const atsc_data_segment &seg)
135 {
136   for (int i = 0; i < N_SAVED_SYMBOLS; i++)
137     saved_symbols[i] = seg.data[i + ATSC_DATA_SEGMENT_LENGTH - N_SAVED_SYMBOLS];}
138
139
140 inline static bool
141 last_regular_seg_p (const plinfo &pli)
142 {
143   return pli.regular_seg_p () && (pli.segno () == ATSC_DSEGS_PER_FIELD - 1);
144 }
145
146 void
147 atsc_field_sync_mux::forecast (int noutput_items, gr_vector_int &ninput_items_required)
148 {
149   unsigned ninputs = ninput_items_required.size();
150   for (unsigned i = 0; i < ninputs; i++) 
151     ninput_items_required[i] = fixed_rate_noutput_to_ninput (noutput_items);
152   
153 }
154
155
156 int
157 atsc_field_sync_mux::work (int noutput_items,
158                        gr_vector_const_void_star &input_items,
159                        gr_vector_void_star &output_items)
160 {
161   const atsc_data_segment *in = (const atsc_data_segment *) input_items[0];
162   atsc_data_segment *out = (atsc_data_segment *) output_items[0];
163
164   unsigned int index = 0;
165   for (int outdex = 0; outdex < noutput_items; outdex++){
166
167     assert (in[index].pli.regular_seg_p ());
168
169     if (!in[index].pli.first_regular_seg_p ()){
170       out[outdex] = in[index];                  // just copy in to out
171
172       if (last_regular_seg_p (in[index].pli))
173         save_last_symbols (d_saved_symbols, in[index]);
174
175       index++;
176     }
177     else {                                      // first_regular_seg_p
178       if (!d_already_output_field_sync){
179         // write out field sync...
180         atsc_data_segment       field_sync;
181
182         if (in[index].pli.in_field1_p ())
183           init_field_sync_1 (&field_sync, d_saved_symbols);
184         else
185           init_field_sync_2 (&field_sync, d_saved_symbols);
186
187         // note that index doesn't advance in this branch
188         out[outdex] = field_sync;
189         d_already_output_field_sync = true;
190       }
191       else {
192         // already output field sync, now output first regular segment
193         out[outdex] = in[index];
194         index++;
195         d_already_output_field_sync = false;
196       }
197     }
198   }
199
200   d_current_index += index;
201
202   return noutput_items;
203 }