diff options
author | Nick Foster <bistromath@gmail.com> | 2014-03-26 18:11:15 -0700 |
---|---|---|
committer | Nick Foster <bistromath@gmail.com> | 2014-03-26 18:11:15 -0700 |
commit | aacdf167e5c21e62e36c9d3088ec207e177b212a (patch) | |
tree | 35c8964c6c91217b096882fb2080d97e6b377248 | |
parent | 1092e685defd10692d3fa47435c716a88dfd8712 (diff) |
Add HDLC deframer to gr-digital. Input unpacked bits, output PDU binary
blobs.
-rw-r--r-- | gr-digital/grc/digital_hdlc_deframer_bp.xml | 33 | ||||
-rw-r--r-- | gr-digital/include/gnuradio/digital/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h | 62 | ||||
-rw-r--r-- | gr-digital/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-digital/lib/hdlc_deframer_bp_impl.cc | 156 | ||||
-rw-r--r-- | gr-digital/lib/hdlc_deframer_bp_impl.h | 52 | ||||
-rw-r--r-- | gr-digital/swig/digital_swig.i | 3 |
7 files changed, 308 insertions, 0 deletions
diff --git a/gr-digital/grc/digital_hdlc_deframer_bp.xml b/gr-digital/grc/digital_hdlc_deframer_bp.xml new file mode 100644 index 0000000000..4609d21d95 --- /dev/null +++ b/gr-digital/grc/digital_hdlc_deframer_bp.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<block> + <name>hdlc_deframer_bp</name> + <key>digital_hdlc_deframer_bp</key> + <category>digital</category> + <import>from gnuradio import digital</import> + <make>digital.hdlc_deframer_bp($frame_tag_name, $min, $max)</make> + <param> + <name>Frame tag name</name> + <key>frame_tag_name</key> + <type>string</type> + </param> + <param> + <name>Min length</name> + <key>min</key> + <value>32</value> + <type>int</type> + </param> + <param> + <name>Max length</name> + <key>max</key> + <value>500</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>message</type> + </source> +</block> diff --git a/gr-digital/include/gnuradio/digital/CMakeLists.txt b/gr-digital/include/gnuradio/digital/CMakeLists.txt index 4d50f42ae0..84a7cee7b7 100644 --- a/gr-digital/include/gnuradio/digital/CMakeLists.txt +++ b/gr-digital/include/gnuradio/digital/CMakeLists.txt @@ -101,6 +101,7 @@ install(FILES glfsr.h glfsr_source_b.h glfsr_source_f.h + hdlc_deframer_bp.h header_payload_demux.h kurtotic_equalizer_cc.h lfsr.h diff --git a/gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h b/gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h new file mode 100644 index 0000000000..191f294344 --- /dev/null +++ b/gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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. + */ + +#ifndef INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_H +#define INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_H + +#include <gnuradio/digital/api.h> +#include <gnuradio/sync_block.h> + +namespace gr { + namespace digital { + + /*! + * \brief HDLC deframer which takes in unpacked bits, and outputs PDU + * binary blobs. This is intended for use with the + * correlate_access_code_tag_bb block, which should have an access code + * of "01111110" for use with HDLC frames. Frames which do not pass CRC are + * rejected. + * + * \ingroup digital + * + */ + class DIGITAL_API hdlc_deframer_bp : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr<hdlc_deframer_bp> sptr; + + /*! + * \brief Return a shared_ptr to a new instance of digital::hdlc_deframer. + * + * \param frame_tag_name: The tag name from an upstream + * correlate_access_code_tag_bb block. + * \param length_min: Minimum frame size (default: 32) + * \param length_max: Maximum frame size (default: 500) + */ + static sptr make(const std::string frame_tag_name, int length_min, int length_max); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_H */ + diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt index 509a9a5bbf..709c74ce80 100644 --- a/gr-digital/lib/CMakeLists.txt +++ b/gr-digital/lib/CMakeLists.txt @@ -137,6 +137,7 @@ list(APPEND digital_sources glfsr.cc glfsr_source_b_impl.cc glfsr_source_f_impl.cc + hdlc_deframer_bp_impl.cc header_payload_demux_impl.cc kurtotic_equalizer_cc_impl.cc lms_dd_equalizer_cc_impl.cc diff --git a/gr-digital/lib/hdlc_deframer_bp_impl.cc b/gr-digital/lib/hdlc_deframer_bp_impl.cc new file mode 100644 index 0000000000..d5fd20338f --- /dev/null +++ b/gr-digital/lib/hdlc_deframer_bp_impl.cc @@ -0,0 +1,156 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <gnuradio/io_signature.h> +#include <gnuradio/tags.h> +#include "hdlc_deframer_bp_impl.h" + +namespace gr { + namespace digital { + + hdlc_deframer_bp::sptr + hdlc_deframer_bp::make(const std::string frame_tag_name, + int length_min=32, + int length_max=500) + { + return gnuradio::get_initial_sptr + (new hdlc_deframer_bp_impl(frame_tag_name, length_min, length_max)); + } + + /* + * The private constructor + */ + hdlc_deframer_bp_impl::hdlc_deframer_bp_impl(const std::string frame_tag_name, + int length_min, + int length_max) + : gr::sync_block("hdlc_deframer_bp", + gr::io_signature::make(1, 1, sizeof(unsigned char)), + gr::io_signature::make(0, 0, 0)), + d_frame_tag_name(frame_tag_name), + d_length_min(length_min), + d_length_max(length_max) + { + set_output_multiple(length_max*2); + message_port_register_out(pmt::mp("out")); + } + + /* + * Our virtual destructor. + */ + hdlc_deframer_bp_impl::~hdlc_deframer_bp_impl() + { + } + + //undo HDLC bit stuffing operation. + static void unstuff(std::vector<unsigned char> &pkt) { + int consec = 0; + for(size_t i=0; i<pkt.size(); i++) { + if(pkt[i]) { + consec++; + } else { + if(consec == 5) { + pkt.erase(pkt.begin()+i); + i--; + } + consec = 0; + } + } + } + + //pack unpacked (1 bit per byte) data into bytes, in reverse bit order + //we reverse the bit order because HDLC uses LSbit format. + std::vector<unsigned char> pack(std::vector<unsigned char> &data) + { + std::vector<unsigned char> output(std::ceil(data.size()/8.0f), 0); + for(size_t i=0; i<data.size(); i++) { + output[i/8] |= (data[i]<<(i%8)); + } + return output; + } + + unsigned int crc_ccitt(std::vector<unsigned char> &data) { + unsigned int POLY=0x8408; //reflected 0x1021 + unsigned short crc=0xFFFF; + for(size_t i=0; i<data.size(); i++) { + crc ^= data[i]; + for(size_t j=0; j<8; j++) { + if(crc&0x01) crc = (crc >> 1) ^ POLY; + else crc = (crc >> 1); + } + } + return crc ^ 0xFFFF; + } + + int + hdlc_deframer_bp_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + + //look for frame delimiter tags + std::vector<gr::tag_t> frame_tags; + uint64_t abs_sample_cnt = nitems_read(0); + get_tags_in_range(frame_tags, 0, abs_sample_cnt, abs_sample_cnt + noutput_items, pmt::string_to_symbol(d_frame_tag_name)); + + if(frame_tags.size() == 0) return noutput_items; + int start_pos = frame_tags[0].offset - abs_sample_cnt; + if(frame_tags.size() == 1) return start_pos; //start here next time + int end_pos = frame_tags[1].offset - abs_sample_cnt; + int pkt_len = frame_tags[1].offset - frame_tags[0].offset - 8; //omit EOF delim + if(pkt_len > 500) return end_pos; //arbitrary, too long for a real pkt + if(pkt_len <= 32) return end_pos; + + //get bit array + std::vector<unsigned char> pkt_bits(pkt_len); + memcpy(&pkt_bits[0], &in[start_pos], pkt_bits.size()); + + unstuff(pkt_bits); + + //pack into bytes (and correct bit order) + std::vector<unsigned char> pkt_bytes = pack(pkt_bits); + + //strip off the CRC + unsigned int crc = (int(pkt_bytes[pkt_bytes.size()-1]) << 8) + + pkt_bytes[pkt_bytes.size()-2]; + pkt_bytes.erase(pkt_bytes.end()-2, pkt_bytes.end()); + unsigned int calc_crc = crc_ccitt(pkt_bytes); + + if(crc == calc_crc) { + //publish + //TODO manage padding + pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL, + pmt::make_blob(&pkt_bytes[0], pkt_bytes.size()))); + message_port_pub(pmt::mp("out"), pdu); + } + + // Tell runtime system how many output items we produced. + return end_pos; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/hdlc_deframer_bp_impl.h b/gr-digital/lib/hdlc_deframer_bp_impl.h new file mode 100644 index 0000000000..a8baf810ea --- /dev/null +++ b/gr-digital/lib/hdlc_deframer_bp_impl.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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. + */ + +#ifndef INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_IMPL_H +#define INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_IMPL_H + +#include <gnuradio/digital/hdlc_deframer_bp.h> + +namespace gr { + namespace digital { + + class hdlc_deframer_bp_impl : public hdlc_deframer_bp + { + private: + std::string d_frame_tag_name; + int d_length_min; + int d_length_max; + + public: + hdlc_deframer_bp_impl(const std::string frame_tag_name, int length_min, int length_max); + ~hdlc_deframer_bp_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_IMPL_H */ + diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i index 5a0cb4f415..729450ed22 100644 --- a/gr-digital/swig/digital_swig.i +++ b/gr-digital/swig/digital_swig.i @@ -67,6 +67,7 @@ #include "gnuradio/digital/framer_sink_1.h" #include "gnuradio/digital/glfsr_source_b.h" #include "gnuradio/digital/glfsr_source_f.h" +#include "gnuradio/digital/hdlc_deframer_bp.h" #include "gnuradio/digital/header_payload_demux.h" #include "gnuradio/digital/kurtotic_equalizer_cc.h" #include "gnuradio/digital/lfsr.h" @@ -138,6 +139,7 @@ %include "gnuradio/digital/framer_sink_1.h" %include "gnuradio/digital/glfsr_source_b.h" %include "gnuradio/digital/glfsr_source_f.h" +%include "gnuradio/digital/hdlc_deframer_bp.h" %include "gnuradio/digital/header_payload_demux.h" %include "gnuradio/digital/kurtotic_equalizer_cc.h" %include "gnuradio/digital/lfsr.h" @@ -203,6 +205,7 @@ GR_SWIG_BLOCK_MAGIC2(digital, fll_band_edge_cc); GR_SWIG_BLOCK_MAGIC2(digital, framer_sink_1); GR_SWIG_BLOCK_MAGIC2(digital, glfsr_source_b); GR_SWIG_BLOCK_MAGIC2(digital, glfsr_source_f); +GR_SWIG_BLOCK_MAGIC2(digital, hdlc_deframer_bp); GR_SWIG_BLOCK_MAGIC2(digital, header_payload_demux); GR_SWIG_BLOCK_MAGIC2(digital, kurtotic_equalizer_cc); GR_SWIG_BLOCK_MAGIC2(digital, lms_dd_equalizer_cc); |