2 * Copyright 2004,2006,2007 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_parse.h>
27 #include <pageri_bch3221.h>
28 #include <gr_io_signature.h>
33 pager_flex_parse_sptr pager_make_flex_parse(gr_msg_queue_sptr queue, float freq)
35 return pager_flex_parse_sptr(new pager_flex_parse(queue, freq));
38 pager_flex_parse::pager_flex_parse(gr_msg_queue_sptr queue, float freq) :
39 gr_sync_block("flex_parse",
40 gr_make_io_signature(1, 1, sizeof(gr_int32)),
41 gr_make_io_signature(0, 0, 0)),
48 int pager_flex_parse::work(int noutput_items,
49 gr_vector_const_void_star &input_items,
50 gr_vector_void_star &output_items)
52 const gr_int32 *in = (const gr_int32 *)input_items[0];
55 while (i < noutput_items) {
56 // Accumulate one whole frame's worth of data words (88 of them)
57 d_datawords[d_count] = *in++; i++;
58 if (++d_count == 88) {
67 /* FLEX data frames (that is, 88 data words per phase recovered after sync,
68 symbol decoding, dephasing, deinterleaving, error correction, and conversion
69 from codewords to data words) start with a block information word containing
70 indices of the page address field and page vector fields.
73 void pager_flex_parse::parse_capcode(gr_int32 aw1, gr_int32 aw2)
75 d_laddr = (aw1 < 0x008001L) ||
80 d_capcode = aw1+((aw2^0x001FFFFF)<<15)+0x1F9000; // Don't ask
82 d_capcode = aw1-0x8000;
85 void pager_flex_parse::parse_data()
87 // Block information word is the first data word in frame
88 gr_int32 biw = d_datawords[0];
90 // Nothing to see here, please move along
91 if (biw == 0 || biw == 0x001FFFFF)
94 // Vector start index is bits 15-10
95 // Address start address is bits 9-8, plus one for offset
96 int voffset = (biw >> 10) & 0x3f;
97 int aoffset = ((biw >> 8) & 0x03) + 1;
99 //printf("BIW:%08X AW:%02i-%02i\n", biw, aoffset, voffset);
101 // Iterate through pages and dispatch to appropriate handler
102 for (int i = aoffset; i < voffset; i++) {
103 int j = voffset+i-aoffset; // Start of vector field for address @ i
105 if (d_datawords[i] == 0x00000000 ||
106 d_datawords[i] == 0x001FFFFF)
107 continue; // Idle codewords, invalid address
109 parse_capcode(d_datawords[i], d_datawords[i+1]);
113 if (d_capcode < 0) // Invalid address, skip
116 // Parse vector information word for address @ offset 'i'
117 gr_int32 viw = d_datawords[j];
118 d_type = (page_type_t)((viw >> 4) & 0x00000007);
119 int mw1 = (viw >> 7) & 0x00000007F;
120 int len = (viw >> 14) & 0x0000007F;
122 if (is_numeric_page(d_type))
126 if (mw1 == 0 && mw2 == 0)
127 continue; // Invalid VIW
129 if (is_tone_page(d_type))
132 if (mw1 > 87 || mw2 > 87)
133 continue; // Invalid offsets
136 d_payload.setf(std::ios::showpoint);
137 d_payload << std::setprecision(6) << std::setw(7)
138 << d_freq/1e6 << FIELD_DELIM
139 << std::setw(10) << d_capcode << FIELD_DELIM
140 << flex_page_desc[d_type] << FIELD_DELIM;
142 if (is_alphanumeric_page(d_type))
143 parse_alphanumeric(mw1, mw2-1, j);
144 else if (is_numeric_page(d_type))
145 parse_numeric(mw1, mw2, j);
146 else if (is_tone_page(d_type))
149 parse_unknown(mw1, mw2);
151 gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str()));
152 d_queue->handle(msg);
156 void pager_flex_parse::parse_alphanumeric(int mw1, int mw2, int j)
162 frag = (d_datawords[mw1] >> 11) & 0x03;
163 cont = (d_datawords[mw1] >> 10) & 0x01;
167 frag = (d_datawords[j+1] >> 11) & 0x03;
168 cont = (d_datawords[j+1] >> 10) & 0x01;
172 //d_payload << frag << FIELD_DELIM;
173 //d_payload << cont << FIELD_DELIM;
175 for (int i = mw1; i <= mw2; i++) {
176 gr_int32 dw = d_datawords[i];
179 if (i > mw1 || frag != 0x03) {
185 ch = (dw >> 7) & 0x7F;
186 if (ch != 0x03) // Fill
189 ch = (dw >> 14) & 0x7F;
190 if (ch != 0x03) // Fill
195 void pager_flex_parse::parse_numeric(int mw1, int mw2, int j)
197 // Get first dataword from message field or from second
198 // vector word if long address
201 dw = d_datawords[mw1];
206 dw = d_datawords[j+1];
209 unsigned char digit = 0;
211 if (d_type == FLEX_NUMBERED_NUMERIC)
212 count += 10; // Skip 10 header bits for numbered numeric pages
214 count += 2; // Otherwise skip 2
216 for (int i = mw1; i <= mw2; i++) {
217 for (int k = 0; k < 21; k++) {
218 // Shift LSB from data word into digit
219 digit = (digit >> 1) & 0x0F;
224 if (digit != 0x0C) // Fill
225 d_payload << flex_bcd[digit];
234 void pager_flex_parse::parse_tone_only()
238 void pager_flex_parse::parse_unknown(int mw1, int mw2)