diff options
Diffstat (limited to 'gr-pager/lib/flex_parse_impl.cc')
-rw-r--r-- | gr-pager/lib/flex_parse_impl.cc | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/gr-pager/lib/flex_parse_impl.cc b/gr-pager/lib/flex_parse_impl.cc new file mode 100644 index 0000000000..8cf0503de7 --- /dev/null +++ b/gr-pager/lib/flex_parse_impl.cc @@ -0,0 +1,258 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2007,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "flex_parse_impl.h" +#include "bch3221.h" +#include <gr_io_signature.h> +#include <ctype.h> +#include <iostream> +#include <iomanip> + +namespace gr { + namespace pager { + + flex_parse::sptr + flex_parse::make(gr_msg_queue_sptr queue, float freq) + { + return gnuradio::get_initial_sptr + (new flex_parse_impl(queue, freq)); + } + + flex_parse_impl::flex_parse_impl(gr_msg_queue_sptr queue, float freq) : + gr_sync_block("flex_parse", + gr_make_io_signature(1, 1, sizeof(gr_int32)), + gr_make_io_signature(0, 0, 0)), + d_queue(queue), + d_freq(freq) + { + d_count = 0; + } + + flex_parse_impl::~flex_parse_impl() + { + } + + int flex_parse_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_int32 *in = (const gr_int32 *)input_items[0]; + + int i = 0; + while(i < noutput_items) { + // Accumulate one whole frame's worth of data words (88 of them) + d_datawords[d_count] = *in++; i++; + if(++d_count == 88) { + parse_data(); + d_count = 0; + } + } + + return i; + } + + /* FLEX data frames (that is, 88 data words per phase recovered + after sync, symbol decoding, dephasing, deinterleaving, error + correction, and conversion from codewords to data words) start + with a block information word containing indices of the page + address field and page vector fields. */ + void + flex_parse_impl::parse_capcode(int aw1, int aw2) + { + d_laddr = (aw1 < 0x008001L) || + (aw1 > 0x1E0000L) || + (aw1 > 0x1E7FFEL); + + if(d_laddr) + d_capcode = aw1+((aw2^0x001FFFFF)<<15)+0x1F9000; // Don't ask + else + d_capcode = aw1-0x8000; + } + + void + flex_parse_impl::parse_data() + { + // Block information word is the first data word in frame + int biw = d_datawords[0]; + + // Nothing to see here, please move along + if(biw == 0 || biw == 0x001FFFFF) + return; + + // Vector start index is bits 15-10 + // Address start address is bits 9-8, plus one for offset + int voffset = (biw >> 10) & 0x3f; + int aoffset = ((biw >> 8) & 0x03) + 1; + + //printf("BIW:%08X AW:%02i-%02i\n", biw, aoffset, voffset); + + // Iterate through pages and dispatch to appropriate handler + for(int i = aoffset; i < voffset; i++) { + int j = voffset+i-aoffset; // Start of vector field for address @ i + + if(d_datawords[i] == 0x00000000 || + d_datawords[i] == 0x001FFFFF) + continue; // Idle codewords, invalid address + + parse_capcode(d_datawords[i], d_datawords[i+1]); + if(d_laddr) + i++; + + if(d_capcode < 0) // Invalid address, skip + continue; + + // Parse vector information word for address @ offset 'i' + int viw = d_datawords[j]; + d_type = (page_type_t)((viw >> 4) & 0x00000007); + int mw1 = (viw >> 7) & 0x00000007F; + int len = (viw >> 14) & 0x0000007F; + + if(is_numeric_page(d_type)) + len &= 0x07; + int mw2 = mw1+len; + + if(mw1 == 0 && mw2 == 0) + continue; // Invalid VIW + + if(is_tone_page(d_type)) + mw1 = mw2 = 0; + + if(mw1 > 87 || mw2 > 87) + continue; // Invalid offsets + + d_payload.str(""); + d_payload.setf(std::ios::showpoint); + d_payload << std::setprecision(6) << std::setw(7) + << d_freq/1e6 << FIELD_DELIM + << std::setw(10) << d_capcode << FIELD_DELIM + << flex_page_desc[d_type] << FIELD_DELIM; + + if(is_alphanumeric_page(d_type)) + parse_alphanumeric(mw1, mw2-1, j); + else if(is_numeric_page(d_type)) + parse_numeric(mw1, mw2, j); + else if(is_tone_page(d_type)) + parse_tone_only(); + else + parse_unknown(mw1, mw2); + + gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str())); + d_queue->handle(msg); + } + } + + void + flex_parse_impl::parse_alphanumeric(int mw1, int mw2, int j) + { + int frag; + //bool cont; + + if(!d_laddr) { + frag = (d_datawords[mw1] >> 11) & 0x03; + //cont = (d_datawords[mw1] >> 10) & 0x01; + mw1++; + } + else { + frag = (d_datawords[j+1] >> 11) & 0x03; + //cont = (d_datawords[j+1] >> 10) & 0x01; + mw2--; + } + + //d_payload << frag << FIELD_DELIM; + //d_payload << cont << FIELD_DELIM; + + for(int i = mw1; i <= mw2; i++) { + int dw = d_datawords[i]; + unsigned char ch; + + if(i > mw1 || frag != 0x03) { + ch = dw & 0x7F; + if(ch != 0x03) + d_payload << ch; + } + + ch = (dw >> 7) & 0x7F; + if(ch != 0x03) // Fill + d_payload << ch; + + ch = (dw >> 14) & 0x7F; + if(ch != 0x03) // Fill + d_payload << ch; + } + } + + void + flex_parse_impl::parse_numeric(int mw1, int mw2, int j) + { + // Get first dataword from message field or from second + // vector word if long address + int dw; + if(!d_laddr) { + dw = d_datawords[mw1]; + mw1++; + mw2++; + } + else { + dw = d_datawords[j+1]; + } + + unsigned char digit = 0; + int count = 4; + if(d_type == FLEX_NUMBERED_NUMERIC) + count += 10; // Skip 10 header bits for numbered numeric pages + else + count += 2; // Otherwise skip 2 + + for(int i = mw1; i <= mw2; i++) { + for(int k = 0; k < 21; k++) { + // Shift LSB from data word into digit + digit = (digit >> 1) & 0x0F; + if(dw & 0x01) + digit ^= 0x08; + dw >>= 1; + if(--count == 0) { + if(digit != 0x0C) // Fill + d_payload << flex_bcd[digit]; + count = 4; + } + } + + dw = d_datawords[i]; + } + } + + void + flex_parse_impl::parse_tone_only() + { + } + + void + flex_parse_impl::parse_unknown(int mw1, int mw2) + { + } + + } /* namespace pager */ +} /* namespace gr */ |