commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 09/17: Add matching HDLC framer. Fix defram


From: git
Subject: [Commit-gnuradio] [gnuradio] 09/17: Add matching HDLC framer. Fix deframer max/min.
Date: Mon, 31 Mar 2014 20:15:53 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit 655646c7bb84a14341dc1e06f955103aa28464c5
Author: Nick Foster <address@hidden>
Date:   Thu Mar 27 15:45:42 2014 -0700

    Add matching HDLC framer. Fix deframer max/min.
---
 gr-digital/grc/digital_hdlc_framer_pb.xml          |  21 +++
 gr-digital/include/gnuradio/digital/CMakeLists.txt |   1 +
 .../gnuradio/digital/hdlc_framer_pb.h}             |  48 +++---
 gr-digital/lib/CMakeLists.txt                      |   1 +
 gr-digital/lib/hdlc_deframer_bp_impl.cc            |  10 +-
 gr-digital/lib/hdlc_deframer_bp_impl.h             |   2 +
 gr-digital/lib/hdlc_framer_pb_impl.cc              | 184 +++++++++++++++++++++
 ...lc_deframer_bp_impl.h => hdlc_framer_pb_impl.h} |  23 +--
 gr-digital/swig/digital_swig.i                     |   3 +
 9 files changed, 258 insertions(+), 35 deletions(-)

diff --git a/gr-digital/grc/digital_hdlc_framer_pb.xml 
b/gr-digital/grc/digital_hdlc_framer_pb.xml
new file mode 100644
index 0000000..540764c
--- /dev/null
+++ b/gr-digital/grc/digital_hdlc_framer_pb.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<block>
+  <name>hdlc_framer_pb</name>
+  <key>digital_hdlc_framer_pb</key>
+  <category>digital</category>
+  <import>from gnuradio import digital</import>
+  <make>digital.hdlc_framer_pb($frame_tag_name)</make>
+  <param>
+    <name>Frame tag name</name>
+    <key>frame_tag_name</key>
+    <type>string</type>
+  </param>
+  <sink>
+    <name>in</name>
+    <type>message</type>
+  </sink>
+  <source>
+    <name>out</name>
+    <type>byte</type>
+  </source>
+</block>
diff --git a/gr-digital/include/gnuradio/digital/CMakeLists.txt 
b/gr-digital/include/gnuradio/digital/CMakeLists.txt
index 84a7cee..63b65b9 100644
--- a/gr-digital/include/gnuradio/digital/CMakeLists.txt
+++ b/gr-digital/include/gnuradio/digital/CMakeLists.txt
@@ -102,6 +102,7 @@ install(FILES
     glfsr_source_b.h
     glfsr_source_f.h
     hdlc_deframer_bp.h
+    hdlc_framer_pb.h
     header_payload_demux.h
     kurtotic_equalizer_cc.h
     lfsr.h
diff --git a/gr-digital/lib/hdlc_deframer_bp_impl.h 
b/gr-digital/include/gnuradio/digital/hdlc_framer_pb.h
similarity index 50%
copy from gr-digital/lib/hdlc_deframer_bp_impl.h
copy to gr-digital/include/gnuradio/digital/hdlc_framer_pb.h
index a8baf81..f516628 100644
--- a/gr-digital/lib/hdlc_deframer_bp_impl.h
+++ b/gr-digital/include/gnuradio/digital/hdlc_framer_pb.h
@@ -1,52 +1,58 @@
 /* -*- 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
+#ifndef INCLUDED_DIGITAL_HDLC_FRAMER_PB_H
+#define INCLUDED_DIGITAL_HDLC_FRAMER_PB_H
 
-#include <gnuradio/digital/hdlc_deframer_bp.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/sync_block.h>
 
 namespace gr {
   namespace digital {
 
-    class hdlc_deframer_bp_impl : public hdlc_deframer_bp
+    /*!
+     * \brief HDLC framer which takes in PDU blobs (char data) and outputs HDLC
+     * frames as unpacked bits, with CRC and bit stuffing added. The first 
sample
+     * of the frame is tagged with the tag frame_tag_name and includes a
+     * length field for tagged_stream use.
+     *
+     * \ingroup digital
+     *
+     */
+    class DIGITAL_API hdlc_framer_pb : virtual public gr::sync_block
     {
-     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);
+      typedef boost::shared_ptr<hdlc_framer_pb> sptr;
+
+      /*!
+       * \brief Return a shared_ptr to a new instance of digital::hdlc_framer.
+       *
+       * \param frame_tag_name: The tag to add to the first sample of each 
frame.
+       */
+      static sptr make(const std::string frame_tag_name);
     };
 
   } // namespace digital
 } // namespace gr
 
-#endif /* INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_IMPL_H */
+#endif /* INCLUDED_DIGITAL_HDLC_FRAMER_PB_H */
 
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index 709c74c..00200d1 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -138,6 +138,7 @@ list(APPEND digital_sources
     glfsr_source_b_impl.cc
     glfsr_source_f_impl.cc
     hdlc_deframer_bp_impl.cc
+    hdlc_framer_pb_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
index d5fd203..c0e52cb 100644
--- a/gr-digital/lib/hdlc_deframer_bp_impl.cc
+++ b/gr-digital/lib/hdlc_deframer_bp_impl.cc
@@ -82,7 +82,8 @@ namespace gr {
 
     //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>
+    hdlc_deframer_bp_impl::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++) {
@@ -91,7 +92,8 @@ namespace gr {
         return output;
     }
 
-    unsigned int crc_ccitt(std::vector<unsigned char> &data) {
+    unsigned int
+    hdlc_deframer_bp_impl::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++) {
@@ -121,8 +123,8 @@ namespace gr {
         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;
+        if(pkt_len > d_length_max) return end_pos; //arbitrary, too long for a 
real pkt
+        if(pkt_len <= d_length_min)  return end_pos;
 
         //get bit array
         std::vector<unsigned char> pkt_bits(pkt_len);
diff --git a/gr-digital/lib/hdlc_deframer_bp_impl.h 
b/gr-digital/lib/hdlc_deframer_bp_impl.h
index a8baf81..de8f6b3 100644
--- a/gr-digital/lib/hdlc_deframer_bp_impl.h
+++ b/gr-digital/lib/hdlc_deframer_bp_impl.h
@@ -34,6 +34,8 @@ namespace gr {
         std::string d_frame_tag_name;
         int d_length_min;
         int d_length_max;
+        unsigned int crc_ccitt(std::vector<unsigned char> &data);
+        std::vector<unsigned char> pack(std::vector<unsigned char> &pkt);
 
      public:
       hdlc_deframer_bp_impl(const std::string frame_tag_name, int length_min, 
int length_max);
diff --git a/gr-digital/lib/hdlc_framer_pb_impl.cc 
b/gr-digital/lib/hdlc_framer_pb_impl.cc
new file mode 100644
index 0000000..0111f60
--- /dev/null
+++ b/gr-digital/lib/hdlc_framer_pb_impl.cc
@@ -0,0 +1,184 @@
+/* -*- 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_framer_pb_impl.h"
+#include <iostream>
+
+namespace gr {
+  namespace digital {
+
+    hdlc_framer_pb::sptr
+    hdlc_framer_pb::make(const std::string frame_tag_name)
+    {
+      return gnuradio::get_initial_sptr
+        (new hdlc_framer_pb_impl(frame_tag_name));
+    }
+
+    /*
+     * The private constructor
+     */
+    hdlc_framer_pb_impl::hdlc_framer_pb_impl(const std::string frame_tag_name)
+      : gr::sync_block("hdlc_framer_pb",
+              gr::io_signature::make(0, 0, 0),
+              gr::io_signature::make(1, 1, sizeof(unsigned char)))
+    {
+        message_port_register_in(pmt::mp("in"));
+        d_frame_tag = pmt::string_to_symbol(frame_tag_name);
+        std::stringstream str;
+        str << name() << unique_id();
+        d_me = pmt::string_to_symbol(str.str());
+    }
+
+    /*
+     * Our virtual destructor.
+     */
+    hdlc_framer_pb_impl::~hdlc_framer_pb_impl()
+    {
+    }
+
+    //bit stuff
+    void
+    hdlc_framer_pb_impl::stuff(std::vector<unsigned char> &pkt) {
+        int consec = 0;
+        for(size_t i=0; i < pkt.size(); i++) {
+            if(consec == 5) {
+                pkt.insert(pkt.begin()+i, 0);
+                consec = 0;
+            }
+            if(pkt[i]==1) consec++;
+            else consec=0;
+        }
+    }
+
+    //unpack packed (8 bits per byte) into bits, in LSbit order.
+    //TODO: handle non-multiple-of-8 bit lengths (pad low)
+    std::vector<unsigned char>
+    hdlc_framer_pb_impl::unpack(std::vector<unsigned char> &data) {
+        std::vector<unsigned char> output(data.size()*8, 0);
+        for(size_t i=0; i<data.size(); i++) {
+            for(size_t j=0; j<8; j++) {
+                output[i*8+j] = (data[i] >> j) & 1;
+            }
+        }
+        return output;
+    }
+
+    unsigned int
+    hdlc_framer_pb_impl::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_framer_pb_impl::work(int noutput_items,
+                                gr_vector_const_void_star &input_items,
+                                gr_vector_void_star &output_items)
+    {
+        unsigned char *out = (unsigned char *) output_items[0];
+
+        //send leftovers one chunk at a time.
+        //it'd be more efficient to send as much as possible, i.e.
+        //partial packets., but if we're to preserve tag boundaries
+        //this is much, much simpler.
+        int oidx = 0;
+        while(d_leftovers.size() > 0) {
+            if(noutput_items < (oidx+d_leftovers[0].size())) return oidx;
+            memcpy(out+oidx, &d_leftovers[0][0], d_leftovers[0].size());
+            //start tag
+            add_item_tag(0,
+                         nitems_written(0)+oidx,
+                         d_frame_tag,
+                         pmt::from_long(d_leftovers[0].size()),
+                         d_me);
+            oidx += d_leftovers[0].size();
+            d_leftovers.erase(d_leftovers.begin());
+        }
+
+        //get PDU
+        pmt::pmt_t msg(delete_head_nowait(pmt::string_to_symbol("in")));
+        if(msg.get() == NULL) return 0;
+
+        pmt::pmt_t len(pmt::car(msg)); //TODO for non-mult-8 nbits
+        pmt::pmt_t blob(pmt::cdr(msg));
+        if(!pmt::is_blob(blob))
+            throw std::runtime_error("HDLC framer: PMT must be blob");
+        std::vector<unsigned char> pkt(pmt::blob_length(blob));
+        memcpy(&pkt[0], (const unsigned char *) pmt::blob_data(blob), 
pkt.size());
+
+        //calc CRC
+        unsigned int crc = crc_ccitt(pkt);
+
+        //append CRC
+        pkt.insert(pkt.end(), crc & 0xFF);
+        pkt.insert(pkt.end(), (crc >> 8) & 0xFF);
+
+        //unpack to LSb bits
+        std::vector<unsigned char> pkt_bits = unpack(pkt);
+
+        //bitstuff
+        stuff(pkt_bits);
+
+        //add framing
+        const unsigned char framing[] = {0,1,1,1,1,1,1,0};
+        std::vector<unsigned char> framing_vec(framing, 
framing+sizeof(framing));
+        pkt_bits.insert(pkt_bits.begin(), framing_vec.begin(), 
framing_vec.end());
+        pkt_bits.insert(pkt_bits.end(), framing_vec.begin(), 
framing_vec.end());
+
+        //make sure we have the space. unfortunately, we didn't know
+        //until now, since the stuffing must be calculated. we'll just
+        //save it for next time.
+        if(noutput_items < (oidx+pkt_bits.size())) {
+            d_leftovers.insert(d_leftovers.end(), pkt_bits);
+            return oidx;
+        }
+
+        //produce
+        memcpy(out+oidx, &pkt_bits[0], pkt_bits.size());
+        //start tag
+        add_item_tag(0,
+                     nitems_written(0)+oidx,
+                     d_frame_tag,
+                     pmt::from_long(pkt_bits.size()),
+                     d_me);
+        oidx += pkt_bits.size();
+
+        //return # output bits
+        return oidx;
+    }
+
+  } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/hdlc_deframer_bp_impl.h 
b/gr-digital/lib/hdlc_framer_pb_impl.h
similarity index 63%
copy from gr-digital/lib/hdlc_deframer_bp_impl.h
copy to gr-digital/lib/hdlc_framer_pb_impl.h
index a8baf81..90d51a9 100644
--- a/gr-digital/lib/hdlc_deframer_bp_impl.h
+++ b/gr-digital/lib/hdlc_framer_pb_impl.h
@@ -20,24 +20,27 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_IMPL_H
-#define INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_IMPL_H
+#ifndef INCLUDED_DIGITAL_HDLC_FRAMER_PB_IMPL_H
+#define INCLUDED_DIGITAL_HDLC_FRAMER_PB_IMPL_H
 
-#include <gnuradio/digital/hdlc_deframer_bp.h>
+#include <gnuradio/digital/hdlc_framer_pb.h>
+#include <pmt/pmt.h>
 
 namespace gr {
   namespace digital {
 
-    class hdlc_deframer_bp_impl : public hdlc_deframer_bp
+    class hdlc_framer_pb_impl : public hdlc_framer_pb
     {
      private:
-        std::string d_frame_tag_name;
-        int d_length_min;
-        int d_length_max;
+        std::vector<std::vector<unsigned char> > d_leftovers;
+        pmt::pmt_t d_frame_tag, d_me;
+        unsigned int crc_ccitt(std::vector<unsigned char> &data);
+        std::vector<unsigned char> unpack(std::vector<unsigned char> &pkt);
+        void stuff(std::vector<unsigned char> &pkt);
 
      public:
-      hdlc_deframer_bp_impl(const std::string frame_tag_name, int length_min, 
int length_max);
-      ~hdlc_deframer_bp_impl();
+      hdlc_framer_pb_impl(const std::string frame_tag_name);
+      ~hdlc_framer_pb_impl();
 
       // Where all the action really happens
       int work(int noutput_items,
@@ -48,5 +51,5 @@ namespace gr {
   } // namespace digital
 } // namespace gr
 
-#endif /* INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_IMPL_H */
+#endif /* INCLUDED_DIGITAL_HDLC_FRAMER_PB_IMPL_H */
 
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 729450e..ab9794a 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -68,6 +68,7 @@
 #include "gnuradio/digital/glfsr_source_b.h"
 #include "gnuradio/digital/glfsr_source_f.h"
 #include "gnuradio/digital/hdlc_deframer_bp.h"
+#include "gnuradio/digital/hdlc_framer_pb.h"
 #include "gnuradio/digital/header_payload_demux.h"
 #include "gnuradio/digital/kurtotic_equalizer_cc.h"
 #include "gnuradio/digital/lfsr.h"
@@ -140,6 +141,7 @@
 %include "gnuradio/digital/glfsr_source_b.h"
 %include "gnuradio/digital/glfsr_source_f.h"
 %include "gnuradio/digital/hdlc_deframer_bp.h"
+%include "gnuradio/digital/hdlc_framer_pb.h"
 %include "gnuradio/digital/header_payload_demux.h"
 %include "gnuradio/digital/kurtotic_equalizer_cc.h"
 %include "gnuradio/digital/lfsr.h"
@@ -206,6 +208,7 @@ 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, hdlc_framer_pb);
 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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]