2 * Copyright 2004,2006 Free Software Foundation, Inc.
4 * This file is part of GNU Radio
6 * GNU Radio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
11 * GNU Radio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Radio; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street,
19 * Boston, MA 02110-1301, USA.
26 #include <pager_flex_sync.h>
27 #include <pageri_flex_modes.h>
28 #include <pageri_bch3221.h>
29 #include <pageri_util.h>
30 #include <gr_io_signature.h>
31 #include <gr_count_bits.h>
33 pager_flex_sync_sptr pager_make_flex_sync()
35 return pager_flex_sync_sptr(new pager_flex_sync());
38 // FLEX sync block takes input from sliced baseband stream [0-3] at specified
39 // channel rate. Symbol timing is established based on receiving one of the
40 // defined FLEX protocol synchronization words. The block outputs one FLEX frame
41 // worth of bits on each output phase for the data portion of the frame. Unused phases
42 // get all zeros, which are considered idle code words.
44 pager_flex_sync::pager_flex_sync() :
45 gr_block ("flex_sync",
46 gr_make_io_signature (1, 1, sizeof(unsigned char)),
47 gr_make_io_signature (4, 4, sizeof(unsigned char))),
48 d_sync(10) // Fixed at 10 samples per baud (@ 1600 baud)
53 void pager_flex_sync::forecast(int noutput_items, gr_vector_int &inputs_required)
55 // samples per bit X number of outputs needed
56 int items = noutput_items*d_spb;
57 for (unsigned int i = 0; i < inputs_required.size(); i++)
58 inputs_required[i] = items;
61 int pager_flex_sync::index_avg(int start, int end)
65 return (end + start)/2;
67 return ((end + start)/2 + d_spb/2) % d_spb;
70 bool pager_flex_sync::test_sync(unsigned char sym)
72 // 64-bit FLEX sync code:
75 // Where BBBBBBBB is always 0xA6C6AAAA
76 // and AAAA^CCCC is 0xFFFF
78 // Specific values of AAAA determine what bps and encoding the
79 // packet is beyond the frame information word
81 // First we match on the marker field with a hamming distance < 4
82 // Then we match on the outer code with a hamming distance < 4
84 d_sync[d_index] = (d_sync[d_index] << 1) | (sym < 2);
85 gr_int64 val = d_sync[d_index];
86 gr_int32 marker = ((val & 0x0000FFFFFFFF0000ULL)) >> 16;
88 if (gr_count_bits32(marker^FLEX_SYNC_MARKER) < 4) {
89 gr_int32 code = ((val & 0xFFFF000000000000ULL) >> 32) |
90 (val & 0x000000000000FFFFULL);
92 for (int i = 0; i < num_flex_modes; i++) {
93 if (gr_count_bits32(code^flex_modes[i].sync) < 4) {
99 // Marker received but doesn't match known codes
100 // All codes have high word inverted to low word
101 unsigned short high = (code & 0xFFFF0000) >> 16;
102 unsigned short low = code & 0x0000FFFF;
103 unsigned short syn = high^low;
105 fprintf(stderr, "Unknown sync code detected: %08X\n", code);
111 void pager_flex_sync::enter_idle()
122 d_spb = 16000/d_baudrate;
131 void pager_flex_sync::enter_syncing()
134 d_state = ST_SYNCING;
137 void pager_flex_sync::enter_sync1()
141 d_center = index_avg(d_start, d_end); // Center of goodness
145 void pager_flex_sync::enter_sync2()
149 d_baudrate = flex_modes[d_mode].baud;
150 d_levels = flex_modes[d_mode].levels;
151 d_spb = 16000/d_baudrate;
153 if (d_baudrate == 3200) {
154 // Oversampling buffer just got halved
155 d_center = d_center/2;
157 // We're here at the center of a 1600 baud bit
158 // So this hack puts the index and bit counter
159 // in the right place for 3200 bps.
160 d_index = d_index/2-d_spb/2;
165 void pager_flex_sync::enter_data()
171 void pager_flex_sync::parse_fiw()
173 // Nothing is done with these now, but these will end up getting
174 // passed as metadata when mblocks are available
176 // Bits 31-28 are frame number related, but unknown function
177 // This might be a checksum
178 d_unknown2 = pageri_reverse_bits8((d_fiw >> 24) & 0xF0);
180 // Cycle is bits 27-24, reversed
181 d_cycle = pageri_reverse_bits8((d_fiw >> 20) & 0xF0);
183 // Frame is bits 23-17, reversed
184 d_frame = pageri_reverse_bits8((d_fiw >> 16) & 0xFE);
186 // Bits 16-11 are some sort of marker, usually identical across
187 // many frames but sometimes changes between frames or modes
188 d_unknown1 = (d_fiw >> 11) & 0x3F;
190 //printf("CYC:%02i FRM:%03i\n", d_cycle, d_frame);
193 int pager_flex_sync::output_symbol(unsigned char sym)
195 // Here is where we output a 1 or 0 on each phase according
196 // to current FLEX mode and symbol value. Unassigned phases
197 // are zero from the enter_idle() initialization.
199 // FLEX can transmit the data portion of the frame at either
200 // 1600 bps or 3200 bps, and can use either two- or four-level
203 // At 1600 bps, 2-level, a single "phase" is transmitted with bit
204 // value '0' using level '3' and bit value '1' using level '0'.
206 // At 1600 bps, 4-level, a second "phase" is transmitted, and the
207 // di-bits are encoded with a gray code:
209 // Symbol Phase 1 Phase 2
210 // ------ ------- -------
216 // At 1600 bps, 4-level, these are called PHASE A and PHASE B.
218 // At 3200 bps, the same 1 or 2 bit encoding occurs, except that
219 // additionally two streams are interleaved on alternating symbols.
220 // Thus, PHASE A (and PHASE B if 4-level) are decoded on one symbol,
221 // then PHASE C (and PHASE D if 4-level) are decoded on the next.
225 if (d_baudrate == 1600) {
228 d_bit_b = (sym == 0) || (sym == 3);
230 *d_phase_a++ = d_bit_a;
231 *d_phase_b++ = d_bit_b;
232 *d_phase_c++ = d_bit_c;
233 *d_phase_d++ = d_bit_d;
240 d_bit_b = (sym == 0) || (sym == 3);
246 d_bit_d = (sym == 0) || (sym == 3);
249 *d_phase_a++ = d_bit_a;
250 *d_phase_b++ = d_bit_b;
251 *d_phase_c++ = d_bit_c;
252 *d_phase_d++ = d_bit_d;
260 int pager_flex_sync::general_work(int noutput_items,
261 gr_vector_int &ninput_items,
262 gr_vector_const_void_star &input_items,
263 gr_vector_void_star &output_items)
265 const unsigned char *in = (const unsigned char *)input_items[0];
266 d_phase_a = (unsigned char *)output_items[0];
267 d_phase_b = (unsigned char *)output_items[1];
268 d_phase_c = (unsigned char *)output_items[2];
269 d_phase_d = (unsigned char *)output_items[3];
272 int ninputs = ninput_items[0];
274 while (i < ninputs && j < noutput_items) {
275 unsigned char sym = *in++; i++;
276 d_index = ++d_index % d_spb;
280 // Continually compare the received symbol stream
281 // against the known FLEX sync words.
287 // Wait until we stop seeing sync, then calculate
288 // the center of the bit period (d_center)
294 // Skip 16 bits of dotting, then accumulate 32 bits
295 // of Frame Information Word.
296 if (d_index == d_center) {
297 d_fiw = (d_fiw << 1) | (sym > 1);
298 if (++d_count == 48) {
299 // FIW is accumulated, call BCH to error correct it
300 pageri_bch3221(d_fiw);
308 // This part and the remainder of the frame are transmitted
309 // at either 1600 bps or 3200 bps based on the received
310 // FLEX sync word. The second SYNC header is 25ms of idle bits
312 if (d_index == d_center) {
313 // Skip 25 ms = 40 bits @ 1600 bps, 80 @ 3200 bps
314 if (++d_count == d_baudrate/40)
320 // The data portion of the frame is 1760 ms long at either
321 // baudrate. This is 2816 bits @ 1600 bps and 5632 bits @ 3200 bps.
322 // The output_symbol() routine decodes and doles out the bits
323 // to each of the four transmitted phases of FLEX interleaved codes.
324 if (d_index == d_center) {
325 j += output_symbol(sym);
326 if (++d_count == d_baudrate*1760/1000)
332 assert(0); // memory corruption of d_state if ever gets here