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 2, 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_deframer.h>
27 #include <pageri_flex_modes.h>
28 #include <gr_io_signature.h>
29 #include <gr_count_bits.h>
31 pager_flex_deframer_sptr pager_make_flex_deframer(int rate)
33 return pager_flex_deframer_sptr(new pager_flex_deframer(rate));
36 // FLEX deframer block takes input from symbol stream with alphabet [0, 1, 2, 3]
37 // at specified channel rate and and outputs deinterleaved 32-bit FLEX code words
38 // at 50, 100, or 200 code words per second (based on detected mode in sync
41 pager_flex_deframer::pager_flex_deframer(int rate) :
42 gr_block ("flex_deframer",
43 gr_make_io_signature (1, 1, sizeof(unsigned char)),
44 gr_make_io_signature (1, 1, sizeof(gr_int32))),
45 d_sync(rate/1600) // Maximum samples per baud
48 set_output_multiple(1);
52 void pager_flex_deframer::forecast(int noutput_items, gr_vector_int &inputs_required)
54 // samples per bit X 32 bits * number of outputs needed
55 int items = noutput_items*sizeof(gr_int32)*8*d_spb;
56 for (unsigned int i = 0; i < inputs_required.size(); i++)
57 inputs_required[i] = items;
60 int pager_flex_deframer::index_avg(int start, int end)
64 return (end + start)/2;
66 return ((end + start)/2 + d_spb/2) % d_spb;
69 bool pager_flex_deframer::test_sync(unsigned char sym)
71 // 64-bit FLEX sync code:
74 // Where BBBBBBBB is always 0xA6C6AAAA
75 // and AAAA^CCCC is 0xFFFF
77 // Specific values of AAAA determine what bps and encoding the
78 // packet is beyond the frame information word
80 // First we match on the marker field with a hamming distance < 4
81 // Then we match on the outer code with a hamming distance < 4
83 d_sync[d_index] = (d_sync[d_index] << 1) | (sym < 2);
84 gr_int64 val = d_sync[d_index];
85 gr_int32 marker = ((val & 0x0000FFFFFFFF0000ULL)) >> 16;
87 if (gr_count_bits32(marker^FLEX_SYNC_MARKER) < 4) {
88 gr_int32 code = ((val & 0xFFFF000000000000ULL) >> 32) |
89 (val & 0x000000000000FFFFULL);
91 for (int i = 0; i < num_flex_modes; i++) {
92 if (gr_count_bits32(code^flex_modes[i].sync) < 4) {
98 // Marker received but doesn't match known codes
99 // All codes have high word inverted to low word
100 unsigned short high = (code & 0xFFFF0000) >> 16;
101 unsigned short low = code & 0x0000FFFF;
102 unsigned short syn = high^low;
104 fprintf(stderr, "Unknown sync code detected: %08X\n", code);
110 void pager_flex_deframer::enter_idle()
121 d_spb = d_rate/d_baudrate;
128 void pager_flex_deframer::enter_syncing()
131 d_state = ST_SYNCING;
134 void pager_flex_deframer::enter_sync1()
138 d_center = index_avg(d_start, d_end);
140 fprintf(stderr, "SYNC1=%08X\n", flex_modes[d_mode].sync);
143 void pager_flex_deframer::enter_sync2()
147 d_baudrate = flex_modes[d_mode].baud;
148 d_levels = flex_modes[d_mode].levels;
149 d_spb = d_rate/d_baudrate;
151 if (d_baudrate == 3200) {
152 // Oversampling buffer just got halved
153 d_center = d_center/2;
154 d_index = d_index/2-d_spb/2; // We're here at the center of a 1600 baud bit
155 d_count = -1; // So this hack gets us in the right place for 3200
159 void pager_flex_deframer::enter_data()
165 void pager_flex_deframer::enter_output()
168 d_count = flex_modes[d_mode].phases*88; // Now d_count will count codewords, not bits
169 d_output_phase = 0; // Always phase A
173 void pager_flex_deframer::accumulate_frames(unsigned char sym)
175 // Bits are encoded with 2-bit gray code
184 // Codewords are interleaved in blocks of 8
191 // etc., for all 32 bits. So each successive incoming bit is multiplexed
192 // into a different d_frames[][], indexed by d_cdw
194 d_cdw = d_blk*8+d_cdi;
197 if (d_baudrate == 1600) {
198 d_frames[0][d_cdw] <<= 1;
199 d_frames[0][d_cdw] |= (sym < 2);
202 d_frames[1][d_cdw] <<= 1;
203 d_frames[1][d_cdw] |= (sym == 0 || sym == 3);
208 d_frames[0][d_cdw] <<= 1;
209 d_frames[0][d_cdw] |= (sym < 2);
212 d_frames[1][d_cdw] <<= 1;
213 d_frames[1][d_cdw] |= (sym == 0 || sym == 3);
218 d_frames[2][d_cdw] <<= 1;
219 d_frames[2][d_cdw] |= (sym < 2);
222 d_frames[3][d_cdw] <<= 1;
223 d_frames[3][d_cdw] |= (sym == 0 || sym == 3);
230 if (++d_count % (d_baudrate*4/25) == 0)
234 int pager_flex_deframer::general_work(int noutput_items,
235 gr_vector_int &ninput_items,
236 gr_vector_const_void_star &input_items,
237 gr_vector_void_star &output_items)
239 const unsigned char *in = (const unsigned char *)input_items[0];
240 gr_int32 *out = (gr_int32 *)output_items[0];
243 int ninputs = ninput_items[0];
245 while (i < ninputs && j < noutput_items) {
246 unsigned char sym = 0;
247 if (d_state != ST_OUTPUT) {
249 d_index = ++d_index % d_spb;
259 if (!test_sync(sym)) {
262 *out++ = flex_modes[d_mode].sync; j++;
267 if (d_index == d_center) {
268 d_sync[d_index] = (d_sync[d_index] << 1) | (sym < 2);
269 if (++d_count == 48) { // Skip 16 bits of dotting
270 // Output frame information word
271 *out++ = (gr_int32)(d_sync[d_index] & 0x00000000FFFFFFFFULL); j++;
278 if (d_index == d_center) {
279 // Skip 25 ms = 40 bits @ 1600 bps, 80 @ 3200 bps
280 if (++d_count == d_baudrate/40)
286 if (d_index == d_center) {
287 accumulate_frames(sym);
288 if (d_count == d_baudrate*1760/1000)
294 output_codeword(out++); j++;
300 assert(0); // memory corruption of d_state if ever gets here
310 void pager_flex_deframer::output_codeword(gr_int32 *out)
312 *out = d_frames[d_output_phase][d_output_index++];
314 if (d_output_index == 88) {
317 if (d_output_phase == 1 && !flex_modes[d_mode].phase_b)
319 if (d_output_phase == 2 && !flex_modes[d_mode].phase_c)
321 if (d_output_phase == 3 && !flex_modes[d_mode].phase_d)