commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] [gnuradio] 01/24: digital: New packet management class


From: git
Subject: [Commit-gnuradio] [gnuradio] 01/24: digital: New packet management classes.
Date: Tue, 14 Jun 2016 00:40:54 +0000 (UTC)

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

jcorgan pushed a commit to branch packet2
in repository gnuradio.

commit ff7f8302b1df27854b1a1bc5131ed530bde72242
Author: Tom Rondeau <address@hidden>
Date:   Thu Dec 18 19:08:23 2014 -0500

    digital: New packet management classes.
    
    - default packet formatter: contains access code and payload length
      fields.
    
    - counter packet formatter: also contains the bits/sym in the payload
      modulation and a packet number counter.
    
    - Also adds QA code and the infrastructure for C++ QA code in
      gr-digital.
    
    - New block to use the packet formatter objects.
    
      - The header and payload are transmitted as PDU messages out of different 
ports.
    
    - header_buffer class for header formatting.
    
      - Used by packet_formatter_x classes to more easily add and format
        header data for transmission.
    
    - New blocks that parse headers.
    
      - Handles either hard or soft bits. Produces an info message to
        instruct payload demod.
    
    - 'receive mode' to header_buffer class.
    
      - Designed to make extracting fields from the received header bits
        easier for packet formatter classes. Use extract_field[N] to get
        the different fields out of a collected set of header bits.  *
        Docs describing both functions with small examples for how to use
        them.
    
    - Don't force access code to be a multiple of 8
    
      - need to verify everything else handles this correctly.
    
      - Throw an exception in the ctor if setting the code failed and emit a
        log message.
---
 gr-digital/grc/digital_block_tree.xml              |   3 +
 gr-digital/grc/digital_packet_format_async.xml     |  31 ++
 gr-digital/grc/digital_packet_parse_x.xml          |  46 +++
 .../grc/variable_packet_formatter_default.xml      |  28 ++
 gr-digital/include/gnuradio/digital/CMakeLists.txt |   6 +
 .../include/gnuradio/digital/header_buffer.h       | 301 +++++++++++++++
 .../include/gnuradio/digital/packet_format_async.h |  89 +++++
 .../gnuradio/digital/packet_formatter_counter.h    | 128 +++++++
 .../gnuradio/digital/packet_formatter_default.h    | 300 +++++++++++++++
 .../include/gnuradio/digital/packet_parse_b.h      |  99 +++++
 .../include/gnuradio/digital/packet_parse_f.h      | 105 ++++++
 gr-digital/lib/CMakeLists.txt                      |  40 ++
 gr-digital/lib/header_buffer.cc                    | 208 ++++++++++
 gr-digital/lib/packet_format_async_impl.cc         |  94 +++++
 .../packet_format_async_impl.h}                    |  46 ++-
 gr-digital/lib/packet_formatter_counter.cc         | 126 +++++++
 gr-digital/lib/packet_formatter_default.cc         | 319 ++++++++++++++++
 gr-digital/lib/packet_header_ofdm.cc               |   9 +-
 gr-digital/lib/packet_parse_b_impl.cc              |  93 +++++
 gr-digital/lib/packet_parse_b_impl.h               |  53 +++
 gr-digital/lib/packet_parse_f_impl.cc              |  92 +++++
 gr-digital/lib/packet_parse_f_impl.h               |  53 +++
 .../{swig/packet_header.i => lib/qa_digital.cc}    |  37 +-
 .../{swig/packet_header.i => lib/qa_digital.h}     |  34 +-
 gr-digital/lib/qa_packet_formatters.cc             | 417 +++++++++++++++++++++
 gr-digital/lib/qa_packet_formatters.h              |  49 +++
 .../packet_header.i => lib/test_gr_digital.cc}     |  44 ++-
 gr-digital/python/digital/qa_packet_format.py      | 135 +++++++
 gr-digital/swig/CMakeLists.txt                     |   1 +
 gr-digital/swig/digital_swig.i                     |  13 +
 gr-digital/swig/packet_header.i                    |  20 +-
 31 files changed, 2949 insertions(+), 70 deletions(-)

diff --git a/gr-digital/grc/digital_block_tree.xml 
b/gr-digital/grc/digital_block_tree.xml
index 9bdf6e9..3ae99f3 100644
--- a/gr-digital/grc/digital_block_tree.xml
+++ b/gr-digital/grc/digital_block_tree.xml
@@ -72,6 +72,9 @@
     <block>digital_crc32_bb</block>
     <block>digital_crc32_async_bb</block>
     <block>digital_framer_sink_1</block>
+    <block>variable_packet_formatter_default</block>
+    <block>digital_packet_format_async</block>
+    <block>digital_packet_parse_x</block>
     <block>digital_header_payload_demux</block>
     <block>digital_packet_headergenerator_bb</block>
     <block>digital_packet_headergenerator_bb_default</block>
diff --git a/gr-digital/grc/digital_packet_format_async.xml 
b/gr-digital/grc/digital_packet_format_async.xml
new file mode 100644
index 0000000..95f6b4f
--- /dev/null
+++ b/gr-digital/grc/digital_packet_format_async.xml
@@ -0,0 +1,31 @@
+<block>
+  <name>Packet Header Formatter</name>
+  <key>digital_packet_format_async</key>
+  <import>from gnuradio import digital</import>
+  <make>digital.packet_format_async($formatter)</make>
+
+  <param>
+    <name>Formatter</name>
+    <key>formatter</key>
+    <type>raw</type>
+  </param>
+
+  <sink>
+    <name>in</name>
+    <type>message</type>
+    <optional>1</optional>
+  </sink>
+
+  <source>
+    <name>header</name>
+    <type>message</type>
+    <optional>1</optional>
+  </source>
+
+  <source>
+    <name>payload</name>
+    <type>message</type>
+    <optional>1</optional>
+  </source>
+
+</block>
diff --git a/gr-digital/grc/digital_packet_parse_x.xml 
b/gr-digital/grc/digital_packet_parse_x.xml
new file mode 100644
index 0000000..493b916
--- /dev/null
+++ b/gr-digital/grc/digital_packet_parse_x.xml
@@ -0,0 +1,46 @@
+<block>
+  <name>Packet Parser</name>
+  <key>digital_packet_parse_x</key>
+  <import>from gnuradio import digital</import>
+  <make>digital.packet_parse_$(type)($formatter, $threshold)</make>
+
+  <param>
+    <name>Type</name>
+    <key>type</key>
+    <type>enum</type>
+    <option>
+      <name>Hard Bits</name>
+      <key>b</key>
+      <opt>input:byte</opt>
+    </option>
+    <option>
+      <name>Soft Bits</name>
+      <key>f</key>
+      <opt>input:float</opt>
+    </option>
+  </param>
+
+  <param>
+    <name>Formatter</name>
+    <key>formatter</key>
+    <type>raw</type>
+  </param>
+
+  <param>
+    <name>Threshold</name>
+    <key>threshold</key>
+    <value>0</value>
+    <type>int</type>
+  </param>
+
+  <sink>
+    <name>in</name>
+    <type>$type.input</type>
+  </sink>
+
+  <source>
+    <name>info</name>
+    <type>message</type>
+    <optional>1</optional>
+  </source>
+</block>
diff --git a/gr-digital/grc/variable_packet_formatter_default.xml 
b/gr-digital/grc/variable_packet_formatter_default.xml
new file mode 100644
index 0000000..7ba27fa
--- /dev/null
+++ b/gr-digital/grc/variable_packet_formatter_default.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+# packet_formatter_default object
+###################################################
+ -->
+<block>
+    <name>Default Packet Header Definition</name>
+    <key>variable_packet_formatter_default</key>
+    <import>from gnuradio import digital</import>
+    <var_make>
+#if int($access_code())==0 #
+self.$(id) = $(id) = 
digital.packet_formatter_default(digital.packet_utils.default_access_code)
+#else
+self.$(id) = $(id) = digital.packet_formatter_default($access_code)
+#end if
+    </var_make>
+    <var_value>digital.packet_formatter_default($access_code)</var_value>
+    <make></make>
+
+    <param>
+        <name>Access Code</name>
+        <key>access_code</key>
+        <value>0</value>
+        <type>string</type>
+    </param>
+
+</block>
diff --git a/gr-digital/include/gnuradio/digital/CMakeLists.txt 
b/gr-digital/include/gnuradio/digital/CMakeLists.txt
index d8fe2b6..a2d115d 100644
--- a/gr-digital/include/gnuradio/digital/CMakeLists.txt
+++ b/gr-digital/include/gnuradio/digital/CMakeLists.txt
@@ -65,6 +65,7 @@ install(FILES
     glfsr_source_f.h
     hdlc_deframer_bp.h
     hdlc_framer_pb.h
+    header_buffer.h
     header_payload_demux.h
     kurtotic_equalizer_cc.h
     lfsr.h
@@ -90,6 +91,11 @@ install(FILES
     ofdm_sampler.h
     ofdm_serializer_vcc.h
     ofdm_sync_sc_cfb.h
+    packet_formatter_default.h
+    packet_formatter_counter.h
+    packet_format_async.h
+    packet_parse_b.h
+    packet_parse_f.h
     packet_header_default.h
     packet_header_ofdm.h
     packet_headergenerator_bb.h
diff --git a/gr-digital/include/gnuradio/digital/header_buffer.h 
b/gr-digital/include/gnuradio/digital/header_buffer.h
new file mode 100644
index 0000000..263bc35
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/header_buffer.h
@@ -0,0 +1,301 @@
+/* -*- c++ -*- */
+/* Copyright 2015 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_HEADER_BUFFER_H
+#define INCLUDED_DIGITAL_HEADER_BUFFER_H
+
+#include <gnuradio/digital/api.h>
+#include <vector>
+
+namespace gr {
+  namespace digital {
+
+    /*!
+     * \brief Helper class for handling payload headers.
+     * \ingroup packet_operators_blk
+     *
+     * \details
+     *
+     * This class is used by the packet formatter blocks (e.g.,
+     * digital::packet_formatter_default) to make it easier to deal
+     * with payload headers. This class functions in two different
+     * ways depending on if it is used in a transmitter or
+     * receiver. When used in a transmitter, this class helps us build
+     * headers out of the fields of the protocol. When used in a
+     * receiver, this class helps us parse the received bits into the
+     * protocol's fields.
+     *
+     * This page describes how to work with the different modes,
+     * transmit or receive. The class is instructed as to which mode
+     * it is in by how the constructor is called. If the constructor
+     * is passed a valid array (non NULL), then it is in transmit mode
+     * and will pack this buffer with the header fields. If that
+     * buffer is NULL, the object is in receive mode.
+     *
+     * \section header_buffer_tx Transmit Mode
+     *
+     * When passed a valid buffer in the constructor, this object is in
+     * transmit mode. We can then use the add_field[N] functions to
+     * add new fields to this header. The buffer MUST be large enough
+     * to hold the full header. As this class is meant to work mostly
+     * with the digital::packet_formatter_default and child
+     * classes, the header length can be read from
+     * digital::packet_formatter_default::header_nbytes().
+     *
+     * Each field is a specific length of 8, 16, 32, or 64 bits that
+     * are to be transmitted in network byte order (bit
+     * endian). Generally, data passed to the add_field[N] calls are
+     * formatted little endian, so the data is first converted to big
+     * endian and then added to the back of the buffer. If the data
+     * are already big endian, set the \p be flag to true.
+     *
+     * The length argument (\p len) for all add_field[N] calls is the
+     * number of bytes actually accounted for in the data
+     * structure. Often, we would use the full size of the field,
+     * which is sizeof(dtype), and the add_field[N] call defaults to
+     * len=N. Occasionally, we may need to use fewer bytes than
+     * actually represented by the data type. An example would be the
+     * access code used in the packet_formatter_default, which is a
+     * uint64_t type but may have fewer bytes used in the actual
+     * access code.
+     *
+     * The function that calls this class is expected to handle the
+     * memory handling of the buffer -- both allocating and
+     * deallocating.
+     *
+     * As simple example of using this class in transmit mode:
+     *
+     * \verbatim
+     uint8_t* buffer = (uint8_t*)volk_malloc(header_nbytes(),
+                                             volk_get_alignment());
+
+     header_buffer hdr(buffer);
+     hdr.add_field64(sync_word, sync_word_len);
+     hdr.add_field16(payload_length);
+     hdr.add_field8(header_flags);
+     hdr.add_field8(header_options);
+
+     // Do something with the header
+
+     volk_free(buffer);
+     \endverbatim
+     *
+     * In this example, the header contains four fields:
+     *
+     * \verbatim
+       |0                           15|16          23|24          31|
+       |                          sync word                         |
+       |                                                            |
+       |           length             |     flags    |   options    |
+       \endverbatim
+     *
+     * The sync word can be up to 64-bits, but the add_field64 is also
+     * passed the number of actual bytes in the sync word and so could
+     * be fewer.
+     *
+     * \section header_buffer_rx Receive Mode
+     *
+     * In receive mode, we build up the header as bits are received by
+     * inserting them with insert_bit. We can find out how long the
+     * current header is, in bits, using the call to length(). If the
+     * header is of the appropriate length, we can then start
+     * extracting the fields from it. When we are done with the
+     * current header, call clear_input() to reset the internal buffer
+     * to empty, which will mean that length() returns 0.
+     *
+     * The header fields are extracted using the extract_field[N]
+     * functions. Like the add_field[N] functions, we specify the size
+     * (in bits) of the field we are extracting. We pass this function
+     * the bit-position of the expected field in the received header
+     * buffer. The extract_field[N] assumes that the number of bits
+     * for the field is N, but we can tell the function to use fewer
+     * bits if we want. Setting the length parameter of these
+     * functions greater than N is illegal, and it will throw an
+     * error.
+     *
+     * For example, given a header of | length | seq. num. | where the
+     * length is 16 bits and the sequence number is 32 bits, we would
+     * use:
+     *
+     * \verbatim
+          uint16_t len = d_hdr_reg.extract_field16(0);
+          uint32_t seq = d_hdr_reg.extract_field32(16);
+       \endverbatim
+     *
+     * The extract_field functions are specific to data types of the
+     * field and the number of bits for each field is inferred by the
+     * data type. So extract_field16 assumes we want all 16 bits in
+     * the field represented.
+     *
+     * Some headers have fields that are not standard sizes of
+     * integers, like a 1 bit, 4 bit, or even 12 bit fields. We can
+     * ask for fewer bits for each field. say:
+     *
+     * \verbatim
+       |0          15|16     19|20          31|
+       |     len     |  flags  |   options    |
+       \endverbatim
+     *
+     * We would use the following extraction functions:
+     *
+     * \verbatim
+          uint16_t len   = d_hdr_reg.extract_field16(0);
+          uint8_t  flags = d_hdr_reg.extract_field8(16, 4);
+          uint16_t opts  = d_hdr_reg.extract_field16(20, 12);
+       \endverbatim
+     *
+     * \sa packet_formatter_default
+     * \sa packet_formatter_counter
+     */
+    class DIGITAL_API header_buffer
+    {
+    private:
+      size_t d_offset;
+      uint8_t *d_buffer;
+
+      std::vector<bool> d_input;
+
+    public:
+      /*!
+       * Create a header buffer object with a pre-allocated buffer, \p
+       * buffer, to hold the formatted header data.
+       *
+       * If \p buffer is set to NULL, then this object is in receive
+       * mode meant to receive bits from an incoming data stream and
+       * provide the ability to extract fields. In this mode, calls to
+       * add_field are invalid and will be nops.
+       */
+      header_buffer(uint8_t *buffer=NULL);
+
+      /*!
+       * Class destructor.
+       */
+      ~header_buffer();
+
+      /*!
+       * In transmit mode, this returns the length of the data in
+       * the buffer (not the allocated buffer length).
+       *
+       * In receiving mode, this returns the current length in bits of
+       * the received header.
+       */
+      size_t length() const;
+
+      /*!
+       * Returns a constant pointer to the buffer.
+       */
+      const uint8_t* header() const;
+
+      /*!
+       * Add an 8-bit field to the header.
+       *
+       * \param data The 8-bit data item.
+       * \param len Length (in bits) of \p data (here, always 1).
+       * \param be Set to 'true' if data is already big endian.
+       */
+      void add_field8(uint8_t data, int len=8, bool be=false);
+
+      /*!
+       * Add an 16-bit field to the header.
+       *
+       * \param data The 16-bit data item.
+       * \param len Length (in bits) of \p data.
+       * \param be Set to 'true' if data is already big endian.
+       */
+      void add_field16(uint16_t data, int len=16, bool be=false);
+
+      /*!
+       * Add an 32-bit field to the header.
+       *
+       * \param data The 32-bit data item.
+       * \param len Length (in bits) of \p data.
+       * \param be Set to 'true' if data is already big endian.
+       */
+      void add_field32(uint32_t data, int len=32, bool be=false);
+
+      /*!
+       * Add an 64-bit field to the header.
+       *
+       * \param data The 64-bit data item.
+       * \param len Length (in bits) of \p data.
+       * \param be Set to 'true' if data is already big endian.
+       */
+      void add_field64(uint64_t data, int len=64, bool be=false);
+
+
+
+      /*****************************************************
+       *   Receive mode to build a header from bits        *
+       *****************************************************/
+
+      /*!
+       * Insert a new bit on the back of the input buffer.
+       *
+       * \param bit New bit to add.
+       */
+      void insert_bit(int bit);
+
+      /*!
+       * Clears the input buffer; sets size to 0.
+       */
+      void clear_input();
+
+      /*!
+       * Returns up to an 8-bit field in the packet header.
+       *
+       * \param pos Bit position of the start of the field.
+       * \param len The number of bits in the field.
+       * \param be Set to 'true' to get the field as big endian.
+       */
+      uint8_t extract_field8(int pos, int len=8, bool be=false);
+
+      /*!
+       * Returns up to a 16-bit field in the packet header.
+       *
+       * \param pos Bit position of the start of the field.
+       * \param len The number of bits in the field.
+       * \param be Set to 'true' to get the field as big endian.
+       */
+      uint16_t extract_field16(int pos, int len=16, bool be=false);
+
+      /*!
+       * Returns up to a 32-bit field in the packet header.
+       *
+       * \param pos Bit position of the start of the field.
+       * \param len The number of bits in the field.
+       * \param be Set to 'true' to get the field as big endian.
+       */
+      uint32_t extract_field32(int pos, int len=32, bool be=false);
+
+      /*!
+       * Returns up to a 64-bit field in the packet header.
+       *
+       * \param pos Bit position of the start of the field.
+       * \param len The number of bits in the field.
+       * \param be Set to 'true' to get the field as big endian.
+       */
+      uint64_t extract_field64(int pos, int len=64, bool be=false);
+    };
+
+  } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_BUFFER_H */
diff --git a/gr-digital/include/gnuradio/digital/packet_format_async.h 
b/gr-digital/include/gnuradio/digital/packet_format_async.h
new file mode 100644
index 0000000..2f32065
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/packet_format_async.h
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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_PACKET_FORMAT_ASYNC_H
+#define INCLUDED_DIGITAL_PACKET_FORMAT_ASYNC_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/packet_formatter_default.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+  namespace digital {
+
+    /*!
+     * \brief Uses a header formatter to append a header onto a PDU.
+     * \ingroup packet_operators_blk
+     *
+     * \details
+
+     * This block takes in PDUs and creates a header, generally for
+     * MAC-level processing. Each received PDU is assumed to be its
+     * own frame, so any fragmentation would be done upstream in or
+     * before the flowgraph.
+     *
+     * The header that is created and transmitted out of the 'header'
+     * message port as a PDU. The header is based entirely on the \p
+     * formatter, which is a packet_formatter_default or a child
+     * class. All of these packet header formatters operate the same:
+     * they take in the payload data as well as possible extra
+     * metadata info about the PDU; the formatter then returns the
+     * output PDU as a PMT argument along with any changes to the
+     * metadata info PMT.
+     *
+     * For different packet header formatting needs, we can define new
+     * classes that inherit from the packet_formatter_default block
+     * and which overload the packet_formatter_default::format
+     * function.
+     *
+     * \sa packet_formatter_default
+     * \sa packet_formatter_counter
+     *
+     * This block only uses asynchronous message passing interfaces to
+     * receiver and emit PDUs. The message ports are:
+     *
+     * \li in: receives PDUs for the frame payload
+     * \li header: the header formatted for the given frame
+     * \li payload: the payload
+     */
+    class DIGITAL_API packet_format_async : virtual public block
+    {
+     public:
+      typedef boost::shared_ptr<packet_format_async> sptr;
+
+      /*!
+       * Make a packet header block using a given \p formatter.
+       *
+       * \param formatter The formatter class to use when creating the
+       *        header for the packet. The default formatter is
+       *        packet_formatter_default and just applies an access
+       *        code and a header that repeats the PDU's frame length
+       *        twice.
+       */
+      static sptr make(const packet_formatter_default::sptr &formatter);
+    };
+
+  } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_FORMAT_ASYNC_H */
diff --git a/gr-digital/include/gnuradio/digital/packet_formatter_counter.h 
b/gr-digital/include/gnuradio/digital/packet_formatter_counter.h
new file mode 100644
index 0000000..30578b1
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/packet_formatter_counter.h
@@ -0,0 +1,128 @@
+/* -*- 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_PACKET_FORMATTER_COUNTER_H
+#define INCLUDED_DIGITAL_PACKET_FORMATTER_COUNTER_H
+
+#include <pmt/pmt.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/packet_formatter_default.h>
+
+namespace gr {
+  namespace digital {
+
+    /*!
+     * \brief Header formatter that adds the payload bits/symbol
+     * format and a packet number counter.
+     * \ingroup packet_operators_blk
+     *
+     * \details
+     *
+     * Child class of packet_formatter_default. This version adds two
+     * fields to the header:
+     *
+     * \li bps (16 bits): bits/symbol used when modulating the payload.
+     * \li count (16 bits): a counter for the packet number.
+     *
+     * Like the default packet formatter, the length is encoded as a
+     * 16-bit value repeated twice. The full packet looks like:
+     * \verbatim
+         | access code | hdr | payload |
+       \endverbatim
+     *
+     * Where the access code is <= 64 bits and hdr is:
+     * \verbatim
+         |  0 -- 15 | 16 -- 31 |
+         | pkt len  | pkt len  |
+         | bits/sym | counter  |
+       \endverbatim
+     *
+     * The access code and header are formatted for network byte order.
+     *
+     * \sa packet_formatter_default
+     */
+    class DIGITAL_API packet_formatter_counter
+      : public packet_formatter_default
+    {
+     public:
+      packet_formatter_counter(const std::string &access_code, int bps);
+      virtual ~packet_formatter_counter();
+
+      /*!
+       * Creates a header from the access code and packet length to
+       * build an output packet in the form:
+       *
+       * \verbatim
+           | access code | pkt len | pkt len | bps | counter |
+         \endverbatim
+       *
+       * \param nbytes_in The length (in bytes) of the \p input payload
+       * \param input An array of unsigned chars of the packet payload
+       * \param output A pmt::u8vector with the new header prepended
+       *        onto the input data.
+       * \param info A pmt::dict containing meta data and info about
+       *        the PDU (generally from the metadata portion of the
+       *        input PDU). Data can be extracted from this for the
+       *        header formatting or inserted.
+       */
+      virtual bool format(int nbytes_in,
+                          const unsigned char *input,
+                          pmt::pmt_t &output,
+                          pmt::pmt_t &info);
+
+      /*!
+       * Returns the length of the formatted header in bits.
+       */
+      virtual size_t header_nbits() const;
+
+      /*!
+       * Returns the length of the formatted header in bytes.
+       */
+      virtual size_t header_nbytes() const;
+
+      /*!
+       * Factory to create an async packet header formatter; returns
+       * an sptr to the object.
+       */
+      static sptr make(const std::string &access_code, int bps);
+
+    protected:
+      uint16_t d_counter;    //!< keeps track of the number of packets 
transmitted
+
+      //! Verify that the header is valid
+      bool header_ok();
+
+      /*! Get info from the header; return payload length and package
+       *  rest of data in d_info dictionary.
+       *
+       * Extracts the header of the form:
+       *
+       * \verbatim
+           | access code | pkt len | pkt len | bps | counter | payload |
+         \endverbatim
+       */
+      int header_payload();
+  };
+
+  } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_FORMATTER_COUNTER_H */
diff --git a/gr-digital/include/gnuradio/digital/packet_formatter_default.h 
b/gr-digital/include/gnuradio/digital/packet_formatter_default.h
new file mode 100644
index 0000000..f907e92
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/packet_formatter_default.h
@@ -0,0 +1,300 @@
+/* -*- c++ -*- */
+/* Copyright 2014-2015 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_PACKET_FORMATTER_DEFAULT_H
+#define INCLUDED_DIGITAL_PACKET_FORMATTER_DEFAULT_H
+
+#include <pmt/pmt.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_buffer.h>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace gr {
+  namespace digital {
+
+    /*!
+     * \brief Default header formatter for PDU formatting.
+     * \ingroup packet_operators_blk
+     *
+     * \details
+
+     * Used to handle the default packet header. The formatters manage
+     * two functions:
+     *
+     * \li packet_formatter_default::format: takes in a
+     * payload and creates a header from it.
+     *
+     * \li packet_formatter_default::parse receive bits and
+     * extract the header info.
+     *
+     * Another version of the parser is
+     * packet_formatter_default::parse_soft that receives soft
+     * decisions instead of hard bits.
+     *
+     * This class is specifically designed to work with packets/frames
+     * in the asynchronous PDU architecture of GNU Radio. See the
+     * packet_format_async block for formatting the headers onto
+     * payloads and packet_parse_b and packet_parse_f blocks for
+     * parsing headers in a receiver.
+     *
+     * The Packet Format block takes in a PDU and uses a formatter
+     * class derived from this class to add a header onto the
+     * packet. The Packet Format blocks takes in the PDU, unpacks the
+     * message, and passes it to a formatter class' format function,
+     * which builds a header based on the payload. The header is
+     * passed back and emitted from formatter block as a separate
+     * output. The async format block, packet_format_async, has two
+     * message output ports. The 'header' port passes the header out
+     * as a PDU and the 'payload' passes the payload out as a PDU. The
+     * flowgraph can then separately modulate and combine these two
+     * pieces in the follow-on processing.
+     *
+     * The packet_sync_b and packet_sync_f blocks use the same
+     * formatter class by calling the 'parse' or 'parse_soft' to parse
+     * the received packet headers. These parser blocks are sinks for
+     * the data stream and emit a message from an 'info' port that
+     * contains an PMT dictionary of the information in the
+     * header. The formatter class determines the dictionary keys.
+     *
+     * This is the base class for dealing with formatting headers for
+     * different protocols and purposes. For other header formatting
+     * behaviors, create a child class from here and overload the
+     * format, parse, parse_soft, and parsing state machine functions
+     * as necessary.
+     *
+     * The default header created in this base class consists of an
+     * access code and the packet length. The length is encoded as a
+     * 16-bit value repeated twice:
+     *
+     * \verbatim
+         | access code | hdr | payload |
+       \endverbatim
+     *
+     * Where the access code is <= 64 bits and hdr is:
+     *
+     * \verbatim
+         |  0 -- 15 | 16 -- 31 |
+         | pkt len  | pkt len  |
+       \endverbatim
+     *
+     * The access code and header are formatted for network byte order.
+     *
+     * This header generator does not calculate or append a CRC to the
+     * packet. Use the CRC32 Async block for that before adding the
+     * header. The header's length will then measure the payload plus
+     * the CRC length (4 bytes for a CRC32).
+     *
+     * The default header parser produces a PMT dictionary that
+     * contains the following keys. All formatter blocks MUST produce
+     * these two values in any dictionary.
+     *
+     * \li "skip samps": the number of samples between the end of the
+     * last payload and the beginning of this payload. This is used by
+     * a decoder block to know where in the payload to begin
+     * demodulating the payload.
+     *
+     * \li "payload bits": the number of bits in the payload. The
+     * payload decoder will have to know how this relates to the
+     * number of symbols received.
+     *
+     * \sa packet_formatter_counter
+     * \sa packet_formatter_1
+     * \sa packet_formatter_ofdm
+     */
+    class DIGITAL_API packet_formatter_default
+      : public 
boost::enable_shared_from_this<gr::digital::packet_formatter_default>
+    {
+     public:
+      typedef boost::shared_ptr<packet_formatter_default> sptr;
+
+      packet_formatter_default(const std::string &access_code);
+      virtual ~packet_formatter_default();
+
+      sptr base() { return shared_from_this(); };
+      sptr formatter() { return shared_from_this(); };
+
+      /*!
+       * Creates a header from the access code and packet length and
+       * creates an output header as a PMT vector in the form:
+       *
+       * \verbatim
+           | access code | pkt len | pkt len |
+         \endverbatim
+       *
+       * \param nbytes_in The length (in bytes) of the \p input payload
+       * \param input An array of unsigned chars of the packet payload
+       * \param output A pmt::u8vector with the new header prepended
+       *        onto the input data.
+       * \param info A pmt::dict containing meta data and info about
+       *        the PDU (generally from the metadata portion of the
+       *        input PDU). Data can be extracted from this for the
+       *        header formatting or inserted.
+       */
+      virtual bool format(int nbytes_in,
+                          const unsigned char *input,
+                          pmt::pmt_t &output,
+                          pmt::pmt_t &info);
+
+      /*!
+       * Parses a header of the form:
+       *
+       * \verbatim
+           | access code | pkt len | pkt len | payload |
+         \endverbatim
+       *
+       * This is implemented as a state machine that starts off
+       * searching for the access code. Once found, the access code is
+       * used to find the start of the packet and the following
+       * header. This default header encodes the length of the payload
+       * a 16 bit integer twice. The state machine finds the header
+       * and checks that both payload length values are the same. It
+       * then goes into its final state that reads in the payload
+       * (based on the payload length) and produces a payload as a PMT
+       * u8 vector of packed bytes.
+       *
+       * \param nbits_in The number of bits in the input array.
+       * \param input The input as hard decision bits.
+       * \param info A vector of pmt::dicts to hold any meta data or
+       *        info about the PDU. When parsing the header, the
+       *        formatter can add info from the header into this dict.
+       *        Each packet has a single PMT dictionary of info, so
+       *        the vector length is the number of packets received
+       *        extracted during one call to this parser function.
+       */
+      virtual bool parse(int nbits_in,
+                         const unsigned char *input,
+                         std::vector<pmt::pmt_t> &info);
+
+      /*!
+       * Parses a header of the form:
+       *
+       * \verbatim
+           | access code | pkt len | pkt len | payload |
+         \endverbatim
+       *
+       * This is implemented as a state machine that starts off
+       * searching for the access code. Once found, the access code is
+       * used to find the start of the packet and the following
+       * header. This default header encodes the length of the payload
+       * a 16 bit integer twice. The state machine finds the header
+       * and checks that both payload length values are the same. It
+       * then goes into its final state that reads in the payload
+       * (based on the payload length) and produces a payload as a PMT
+       * f32 vector of soft decision bits.
+       *
+       * This form of the header parser is specifically intended for
+       * use with FEC decoders, in particular the
+       * gr::fec::async_decoder.
+       *
+       * \param nbits_in The number of soft decisions in the input array.
+       * \param input The input as soft decision floats.
+       * \param info A vector of pmt::dicts to hold any meta data or
+       *        info about the PDU. When parsing the header, the
+       *        formatter can add info from the header into this dict.
+       *        Each packet has a single PMT dictionary of info, so
+       *        the vector length is the number of packets received
+       *        extracted during one call to this parser function.
+       */
+      virtual bool parse_soft(int nbits_in,
+                              const float *input,
+                              std::vector<pmt::pmt_t> &info);
+
+      /*!
+       * Returns the length of the formatted header in bits.
+       */
+      virtual size_t header_nbits() const;
+
+      /*!
+       * Returns the length of the formatted header in bytes.
+       */
+      virtual size_t header_nbytes() const;
+
+      /*!
+       * Updates the access code. Must be a string of 1's and 0's and
+       * <= 64 bits.
+       */
+      bool set_access_code(const std::string &access_code);
+
+      /*!
+       * Returns the formatted access code as a 64-bit register.
+       */
+      unsigned long long access_code() const;
+
+      /*!
+       * Sets the threshold for number of access code bits can be in
+       * error before detection. Defaults to 0.
+       */
+      void set_threshold(unsigned int thresh=0);
+
+      /*!
+       * Returns threshold value for access code detection.
+       */
+      unsigned int threshold() const;
+
+      /*!
+       * Factory to create an async packet header formatter; returns
+       * an sptr to the object.
+       */
+      static sptr make(const std::string &access_code);
+
+    protected:
+      enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER};
+
+      uint64_t d_access_code;        //!< register to hold the access code
+      size_t d_access_code_len;      //!< length in bits of the access code
+
+      state_t d_state;               //!< state of the state machine
+      unsigned long long d_data_reg; //!< used to look for access_code
+      unsigned long long d_mask;     /*!< masks access_code bits (top N bits 
are set where
+                                       N is the number of bits in the access 
code) */
+      unsigned int d_threshold;      //!< how many bits may be wrong in sync 
vector
+
+      header_buffer d_hdr_reg;
+
+      int d_pkt_len;                 //!< Length of the packet to put into the 
output buffer
+      int d_pkt_count;               //!< Number of bytes/soft bits already 
received
+      pmt::pmt_t d_info;             //!< info captured from the header
+      int d_count;                   //!< count samples since last payload 
start
+
+      uint16_t d_bps;                //!< bits/sec of payload modulation
+
+      //! Enter Search state of the state machine to find the access code.
+      virtual void enter_search();
+
+      //! Access code found, start getting the header
+      virtual void enter_have_sync();
+
+      //! Header found, setup for pulling in the hard decision bits
+      virtual void enter_have_header(int payload_len);
+
+      //! Verify that the header is valid
+      virtual bool header_ok();
+
+      /*! Get info from the header; return payload length and package
+       *  rest of data in d_info dictionary.
+       */
+      virtual int header_payload();
+  };
+
+  } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_FORMATTER_DEFAULT_H */
diff --git a/gr-digital/include/gnuradio/digital/packet_parse_b.h 
b/gr-digital/include/gnuradio/digital/packet_parse_b.h
new file mode 100644
index 0000000..a87beb5
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/packet_parse_b.h
@@ -0,0 +1,99 @@
+/* -*- 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_PACKET_PARSE_B_H
+#define INCLUDED_DIGITAL_PACKET_PARSE_B_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/packet_formatter_default.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+  namespace digital {
+
+    /*!
+     * \brief Block that synchronizes to a header based on a header
+     * formatter class. Designed to accept hard bits and produce PDUs
+     * with packed bytes (pmt::u8vector).
+     *
+     * \ingroup packet_operators_blk
+     *
+     * \details
+     *
+     * A packet synchronizer block. This block takes in hard bits
+     * (unpacked bytes; 1's and 0's as the LSB) and finds the access
+     * code as a sync word to find the start of a frame.
+     *
+     * The block uses a formatter derived from a
+     * packet_formatter_default formatter class. The only thing
+     * this class is required to have in the header is an access code
+     * of up to 64 bits. This block uses the formatter and access code
+     * to do the frame synchronization. An access code is found if the
+     * received bits have fewer than \p threshold errors detected.
+     *
+     * Once the frame access code is detected, the block uses the
+     * formatter's parse_header to decode the remaining
+     * header. Generally, as in the default header case, the header
+     * will contain the length of the frame's payload. That and
+     * anything else in the header will generally go into the PDU's
+     * meta-data dictionary.
+     *
+     * The block will output a PDU that contains frame's header info
+     * in the meta-data portion of the PDU and the payload itself. The
+     * payload is packed hard bits as taken from the input stream.
+     *
+     * \sa packet_sync_ff for a soft decision version.
+     */
+    class DIGITAL_API packet_parse_b : virtual public sync_block
+    {
+     public:
+      typedef boost::shared_ptr<packet_parse_b> sptr;
+
+      /*!
+       * Make a packet header block using a given \p formatter.
+       *
+       * \param formatter The formatter class to use when reading the
+       *        header.
+       * \param threshold How many bits in the access code the
+       *        \p formatter can miss and still trigger a hit.
+       */
+      static sptr make(const packet_formatter_default::sptr &formatter,
+                       unsigned int threshold=0);
+
+      /*!
+       * Sets the threshold level for the formatter when finding the
+       * access code. See packet_formatter_default::set_threshold
+       * for more details.
+       */
+      virtual void set_threshold(unsigned int thresh) = 0;
+
+      /*!
+       * Gets the access code detection threshold from the formatter.
+       */
+      virtual unsigned int threshold() const = 0;
+    };
+
+  } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_PARSE_B_H */
diff --git a/gr-digital/include/gnuradio/digital/packet_parse_f.h 
b/gr-digital/include/gnuradio/digital/packet_parse_f.h
new file mode 100644
index 0000000..d146702
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/packet_parse_f.h
@@ -0,0 +1,105 @@
+/* -*- 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_PACKET_PARSE_F_H
+#define INCLUDED_DIGITAL_PACKET_PARSE_F_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/packet_formatter_default.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+  namespace digital {
+
+    /*!
+     * \brief Block that synchronizes to a header based on a header
+     * formatter class. Designed to accept soft decisions and produce
+     * PDUs with soft decisions (pmt::f32vector).
+     *
+     * \ingroup packet_operators_blk
+     *
+     * \details
+     *
+     * A packet synchronizer block. This block takes in soft decision
+     * bits (floats) and finds the access code as a sync word to find
+     * the start of a frame.
+     *
+     * The block uses a formatter derived from a
+     * packet_formatter_default formatter class. The only thing
+     * this class is required to have in the header is an access code
+     * of up to 64 bits. This block uses the formatter and access code
+     * to do the frame synchronization. An access code is found if the
+     * received bits have fewer than \p threshold errors detected.
+     *
+     * As soft decisions are received, the header is generally uncoded
+     * or the formatter will understand the code and handle it
+     * itself. Mostly, the header_parser will just slice the decisions
+     * at 0 and convert to hard 1's and 0's.
+     *
+     * Once the frame access code is detected, the block uses the
+     * formatter's parse_header to decode the remaining
+     * header. Generally, as in the default header case, the header
+     * will contain the length of the frame's payload. That and
+     * anything else in the header will generally go into the PDU's
+     * meta-data dictionary.
+     *
+     * The block will output a PDU that contains frame's header info
+     * in the meta-data portion of the PDU and the payload itself. The
+     * payload will be the input soft decision values, so the payload
+     * will be a float vector.
+     *
+     * \sa packet_sync_bb for a hard decision version.
+     */
+    class DIGITAL_API packet_parse_f : virtual public sync_block
+    {
+     public:
+      typedef boost::shared_ptr<packet_parse_f> sptr;
+
+      /*!
+       * Make a packet header block using a given \p formatter.
+       *
+       * \param formatter The formatter class to use when reading the
+       *        header.
+       * \param threshold How many bits in the access code the
+       *        \p formatter can miss and still trigger a hit.
+       */
+      static sptr make(const packet_formatter_default::sptr &formatter,
+                       unsigned int threshold=0);
+
+      /*!
+       * Sets the threshold level for the formatter when finding the
+       * access code. See packet_formatter_default::set_threshold
+       * for more details.
+       */
+      virtual void set_threshold(unsigned int thresh) = 0;
+
+      /*!
+       * Gets the access code detection threshold from the formatter.
+       */
+      virtual unsigned int threshold() const = 0;
+    };
+
+  } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_PARSE_F_H */
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index daa577f..9432082 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -83,6 +83,7 @@ list(APPEND digital_sources
     glfsr_source_f_impl.cc
     hdlc_deframer_bp_impl.cc
     hdlc_framer_pb_impl.cc
+    header_buffer.cc
     header_payload_demux_impl.cc
     kurtotic_equalizer_cc_impl.cc
     lms_dd_equalizer_cc_impl.cc
@@ -106,6 +107,11 @@ list(APPEND digital_sources
     ofdm_sampler_impl.cc
     ofdm_serializer_vcc_impl.cc
     ofdm_sync_sc_cfb_impl.cc
+    packet_formatter_default.cc
+    packet_formatter_counter.cc
+    packet_format_async_impl.cc
+    packet_parse_b_impl.cc
+    packet_parse_f_impl.cc
     packet_header_default.cc
     packet_header_ofdm.cc
     packet_headergenerator_bb_impl.cc
@@ -189,3 +195,37 @@ if(ENABLE_STATIC_LIBS)
     ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT "digital_devel"   # .lib 
file
     )
 endif(ENABLE_STATIC_LIBS)
+
+
+########################################################################
+# QA C++ Code for gr-blocks
+########################################################################
+if(ENABLE_TESTING)
+  include(GrTest)
+
+  include_directories(
+    ${GR_DIGITAL_INCLUDE_DIRS}
+    ${CPPUNIT_INCLUDE_DIRS})
+  link_directories(${CPPUNIT_LIBRARY_DIRS})
+
+  list(APPEND test_gr_digital_sources
+    ${CMAKE_CURRENT_SOURCE_DIR}/test_gr_digital.cc
+    ${CMAKE_CURRENT_SOURCE_DIR}/qa_digital.cc
+    ${CMAKE_CURRENT_SOURCE_DIR}/qa_packet_formatters.cc
+    )
+
+  add_executable(test-gr-digital ${test_gr_digital_sources})
+
+  list(APPEND GR_TEST_TARGET_DEPS test-gr-digital gnuradio-digital)
+
+  target_link_libraries(
+    test-gr-digital
+    gnuradio-runtime
+    gnuradio-digital
+    ${Boost_LIBRARIES}
+    ${CPPUNIT_LIBRARIES}
+    ${LOG4CPP_LIBRARIES}
+  )
+
+  GR_ADD_TEST(test_gr_digital test-gr-digital)
+endif(ENABLE_TESTING)
diff --git a/gr-digital/lib/header_buffer.cc b/gr-digital/lib/header_buffer.cc
new file mode 100644
index 0000000..8cb0b17
--- /dev/null
+++ b/gr-digital/lib/header_buffer.cc
@@ -0,0 +1,208 @@
+/* -*- c++ -*- */
+/* Copyright 2015 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 <string.h>
+#include <algorithm>
+#include <stdexcept>
+#include <volk/volk.h>
+#include <gnuradio/digital/header_buffer.h>
+
+namespace gr {
+  namespace digital {
+
+    header_buffer::header_buffer(uint8_t *bytes_out)
+    {
+      d_offset = 0;
+      d_buffer = bytes_out;
+    }
+
+    header_buffer::~header_buffer()
+    {
+    }
+
+    size_t
+    header_buffer::length() const
+    {
+      if(d_buffer)
+        return d_offset;
+      else
+        return d_input.size();
+    }
+
+    const uint8_t*
+    header_buffer::header() const
+    {
+      return d_buffer;
+    }
+
+    void
+    header_buffer::add_field8(uint8_t data, int len, bool be)
+    {
+      int nbytes = len/8;
+      if(d_buffer) {
+        memcpy(&d_buffer[d_offset], &data, nbytes);
+        d_offset += nbytes;
+      }
+    }
+
+    void
+    header_buffer::add_field16(uint16_t data, int len, bool be)
+    {
+      int nbytes = len/8;
+      if(d_buffer) {
+        uint16_t x = data;
+        if(!be) {
+          volk_16u_byteswap(&x, 1);
+          x = x >> (16-len);
+        }
+        memcpy(&d_buffer[d_offset], &x, nbytes);
+        d_offset += nbytes;
+      }
+    }
+
+    void
+    header_buffer::add_field32(uint32_t data, int len, bool be)
+    {
+      int nbytes = len/8;
+      if(d_buffer) {
+        uint32_t x = data;
+        if(!be) {
+          volk_32u_byteswap(&x, 1);
+          x = x >> (32-len);
+        }
+        memcpy(&d_buffer[d_offset], &x, nbytes);
+        d_offset += nbytes;
+      }
+    }
+
+    void
+    header_buffer::add_field64(uint64_t data, int len, bool be)
+    {
+      int nbytes = len/8;
+      if(d_buffer) {
+        uint64_t x = data;
+        if(!be) {
+          volk_64u_byteswap(&x, 1);
+          x = x >> (64-len);
+        }
+        memcpy(&d_buffer[d_offset], &x, nbytes);
+        d_offset += nbytes;
+      }
+    }
+
+    void
+    header_buffer::insert_bit(int bit)
+    {
+      d_input.push_back(bit);
+    }
+
+    void
+    header_buffer::clear_input()
+    {
+      d_input.clear();
+    }
+
+    uint8_t
+    header_buffer::extract_field8(int pos, int len, bool be)
+    {
+      if(len > 8) {
+        throw std::runtime_error("header_buffer::extract_field for "
+                                 "uint8_t length must be <= 8");
+      }
+
+      uint8_t field = 0x00;
+      std::vector<bool>::iterator itr;
+      for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+        field = (field << 1) | ((*itr) & 0x1);
+      }
+
+      return field;
+    }
+
+    uint16_t
+    header_buffer::extract_field16(int pos, int len, bool be)
+    {
+      if(len > 16) {
+        throw std::runtime_error("header_buffer::extract_field for "
+                                 "uint16_t length must be <= 16");
+      }
+
+      uint16_t field = 0x0000;
+      std::vector<bool>::iterator itr;
+      for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+        field = (field << 1) | ((*itr) & 0x1);
+      }
+
+      if(be) {
+        volk_16u_byteswap(&field, 1);
+      }
+
+      return field;
+    }
+
+    uint32_t
+    header_buffer::extract_field32(int pos, int len, bool be)
+    {
+      if(len > 32) {
+        throw std::runtime_error("header_buffer::extract_field for "
+                                 "uint32_t length must be <= 32");
+      }
+
+      uint32_t field = 0x00000000;
+      std::vector<bool>::iterator itr;
+      for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+        field = (field << 1) | ((*itr) & 0x1);
+      }
+
+      if(be) {
+        volk_32u_byteswap(&field, 1);
+      }
+
+      return field;
+    }
+
+    uint64_t
+    header_buffer::extract_field64(int pos, int len, bool be)
+    {
+      if(len > 64) {
+        throw std::runtime_error("header_buffer::extract_field for "
+                                 "uint64_t length must be <= 64");
+      }
+
+      uint64_t field = 0x0000000000000000;
+      std::vector<bool>::iterator itr;
+      for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+        field = (field << 1) | ((*itr) & 0x1);
+      }
+
+      if(be) {
+        volk_64u_byteswap(&field, 1);
+      }
+
+      return field;
+    }
+
+  } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/packet_format_async_impl.cc 
b/gr-digital/lib/packet_format_async_impl.cc
new file mode 100644
index 0000000..2f1ccdc
--- /dev/null
+++ b/gr-digital/lib/packet_format_async_impl.cc
@@ -0,0 +1,94 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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 <volk/volk.h>
+#include <gnuradio/io_signature.h>
+#include "packet_format_async_impl.h"
+#include <stdio.h>
+
+namespace gr {
+  namespace digital {
+
+    packet_format_async::sptr
+    packet_format_async::make(const packet_formatter_default::sptr &formatter)
+    {
+      return gnuradio::get_initial_sptr
+        (new packet_format_async_impl(formatter));
+    }
+
+    packet_format_async_impl::packet_format_async_impl(const 
packet_formatter_default::sptr &formatter)
+      : block("packet_format_async",
+              io_signature::make(0, 0, 0),
+              io_signature::make(0, 0, 0))
+    {
+      d_formatter = formatter;
+
+      d_in_port = pmt::mp("in");
+      d_hdr_port = pmt::mp("header");
+      d_pld_port = pmt::mp("payload");
+
+      message_port_register_in(d_in_port);
+      message_port_register_out(d_hdr_port);
+      message_port_register_out(d_pld_port);
+
+      set_msg_handler(d_in_port,
+                      boost::bind(&packet_format_async_impl::append, this ,_1) 
);
+    }
+
+    packet_format_async_impl::~packet_format_async_impl()
+    {
+    }
+
+    void
+    packet_format_async_impl::append(pmt::pmt_t msg)
+    {
+      // extract input pdu
+      pmt::pmt_t meta(pmt::car(msg));
+      pmt::pmt_t input(pmt::cdr(msg));
+      pmt::pmt_t header, output;
+
+      size_t pkt_len = 0;
+      const uint8_t* bytes_in = pmt::u8vector_elements(input, pkt_len);
+
+      // Pad the payload with 0's
+      uint8_t* payload = (uint8_t*)volk_malloc(pkt_len*sizeof(uint8_t),
+                                               volk_get_alignment());
+      memcpy(payload, bytes_in, pkt_len*sizeof(uint8_t));
+      output = pmt::init_u8vector(pkt_len, payload);
+      volk_free(payload);
+
+      // Build the header from the input, metadata, and formatter
+      d_formatter->format(pkt_len, bytes_in, header, meta);
+
+      // Package and publish
+      pmt::pmt_t hdr_pdu = pmt::cons(meta, header);
+      pmt::pmt_t pld_pdu = pmt::cons(meta, output);
+      message_port_pub(d_hdr_port, hdr_pdu);
+      message_port_pub(d_pld_port, pld_pdu);
+    }
+
+  } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/swig/packet_header.i 
b/gr-digital/lib/packet_format_async_impl.h
similarity index 50%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/packet_format_async_impl.h
index 7c06d19..2792a25 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/packet_format_async_impl.h
@@ -1,34 +1,50 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2012 Free Software Foundation, Inc.
- * 
+ * Copyright 2015 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.
  */
 
-%template(packet_header_default_sptr) 
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+#ifndef INCLUDED_DIGITAL_PACKET_FORMAT_ASYNC_IMPL_H
+#define INCLUDED_DIGITAL_PACKET_FORMAT_ASYNC_IMPL_H
 
-%template(packet_header_ofdm_sptr) 
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+#include <gnuradio/digital/packet_format_async.h>
 
+namespace gr {
+  namespace digital {
+
+    class packet_format_async_impl
+      : public packet_format_async
+    {
+     private:
+      packet_formatter_default::sptr d_formatter;
+
+      pmt::pmt_t d_in_port;
+      pmt::pmt_t d_hdr_port, d_pld_port;
+
+      void append(pmt::pmt_t msg);
+
+     public:
+      packet_format_async_impl(const packet_formatter_default::sptr 
&formatter);
+      ~packet_format_async_impl();
+    };
+
+  } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_FORMAT_ASYNC_IMPL_H */
diff --git a/gr-digital/lib/packet_formatter_counter.cc 
b/gr-digital/lib/packet_formatter_counter.cc
new file mode 100644
index 0000000..494f514
--- /dev/null
+++ b/gr-digital/lib/packet_formatter_counter.cc
@@ -0,0 +1,126 @@
+/* -*- 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 <iostream>
+#include <iomanip>
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/digital/packet_formatter_counter.h>
+#include <gnuradio/digital/header_buffer.h>
+#include <gnuradio/math.h>
+
+namespace gr {
+  namespace digital {
+
+    packet_formatter_counter::sptr
+    packet_formatter_counter::make(const std::string &access_code, int bps)
+    {
+      return packet_formatter_counter::sptr
+        (new packet_formatter_counter(access_code, bps));
+    }
+
+    packet_formatter_counter::packet_formatter_counter(const std::string 
&access_code, int bps)
+      : packet_formatter_default(access_code)
+    {
+      d_bps = bps;
+      d_counter = 0;
+    }
+
+    packet_formatter_counter::~packet_formatter_counter()
+    {
+    }
+
+    bool
+    packet_formatter_counter::format(int nbytes_in,
+                                     const unsigned char *input,
+                                     pmt::pmt_t &output,
+                                     pmt::pmt_t &info)
+
+    {
+      uint8_t* bytes_out = (uint8_t*)volk_malloc(header_nbytes(),
+                                                 volk_get_alignment());
+
+      header_buffer header(bytes_out);
+      header.add_field64(d_access_code, d_access_code_len);
+      header.add_field16((uint16_t)(nbytes_in));
+      header.add_field16((uint16_t)(nbytes_in));
+      header.add_field16((uint16_t)(d_bps));
+      header.add_field16((uint16_t)(d_counter));
+
+      // Package output data into a PMT vector
+      output = pmt::init_u8vector(header_nbytes(), bytes_out);
+
+      // Creating the output pmt copies data; free our own here.
+      volk_free(bytes_out);
+
+      d_counter++;
+
+      return true;
+    }
+
+    size_t
+    packet_formatter_counter::header_nbits() const
+    {
+      return d_access_code_len + 8*4*sizeof(uint16_t);
+    }
+
+    size_t
+    packet_formatter_counter::header_nbytes() const
+    {
+      return d_access_code_len/8 + 4*sizeof(uint16_t);
+    }
+
+    bool
+    packet_formatter_counter::header_ok()
+    {
+      // confirm that two copies of header info are identical
+      uint16_t len0 = d_hdr_reg.extract_field16(0);
+      uint16_t len1 = d_hdr_reg.extract_field16(16);
+      return (len0 ^ len1) == 0;
+    }
+
+    int
+    packet_formatter_counter::header_payload()
+    {
+      uint16_t len = d_hdr_reg.extract_field16(0);
+      uint16_t bps = d_hdr_reg.extract_field16(32);
+      uint16_t counter = d_hdr_reg.extract_field16(48);
+
+      d_bps = bps;
+
+      d_info = pmt::make_dict();
+      d_info = pmt::dict_add(d_info, pmt::intern("skip samps"),
+                             pmt::from_long(d_count));
+      d_info = pmt::dict_add(d_info, pmt::intern("payload bits"),
+                             pmt::from_long(8*len));
+      d_info = pmt::dict_add(d_info, pmt::intern("bps"),
+                             pmt::from_long(bps));
+      d_info = pmt::dict_add(d_info, pmt::intern("counter"),
+                             pmt::from_long(counter));
+      return static_cast<int>(len);
+    }
+
+  } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/packet_formatter_default.cc 
b/gr-digital/lib/packet_formatter_default.cc
new file mode 100644
index 0000000..66f4795
--- /dev/null
+++ b/gr-digital/lib/packet_formatter_default.cc
@@ -0,0 +1,319 @@
+/* -*- c++ -*- */
+/* Copyright 2014-2015 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 <iostream>
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/digital/packet_formatter_default.h>
+#include <gnuradio/math.h>
+
+namespace gr {
+  namespace digital {
+
+    packet_formatter_default::sptr
+    packet_formatter_default::make(const std::string &access_code)
+    {
+      return packet_formatter_default::sptr
+        (new packet_formatter_default(access_code));
+    }
+
+    packet_formatter_default::packet_formatter_default(const std::string 
&access_code)
+    {
+      if(!set_access_code(access_code)) {
+        throw std::runtime_error("packet_formatter_default: Setting access 
code failed");
+      }
+
+      d_count = 0;
+      d_pkt_len = 0;
+      enter_search();
+      d_threshold = 0;
+      d_data_reg = 0;
+      d_bps = 1; // set in child classes that use this
+    }
+
+    packet_formatter_default::~packet_formatter_default()
+    {
+    }
+
+    bool
+    packet_formatter_default::set_access_code(const std::string &access_code)
+    {
+      d_access_code_len = access_code.length();        // # of bits in the 
access code
+
+      //if((access_code.size() % 8 != 0) || (access_code.size() > 64)) {
+      if(access_code.size() > 64) {
+        return false;
+      }
+
+      // set len top bits to 1.
+      d_mask = ((~0ULL) >> (64 - d_access_code_len));
+
+      d_access_code = 0;
+      for(unsigned i = 0; i < d_access_code_len; i++) {
+        d_access_code = (d_access_code << 1) | (access_code[i] & 1);
+      }
+
+      return true;
+    }
+
+    unsigned long long
+    packet_formatter_default::access_code() const
+    {
+      return d_access_code;
+    }
+
+    void
+    packet_formatter_default::set_threshold(unsigned int thresh)
+    {
+      if(d_threshold > d_access_code_len)
+        throw std::runtime_error("packet_formatter_default: Cannot set 
threshold " \
+                                 "larger than the access code length.");
+      d_threshold = thresh;
+    }
+
+    unsigned int
+    packet_formatter_default::threshold() const
+    {
+      return d_threshold;
+    }
+
+    bool
+    packet_formatter_default::format(int nbytes_in,
+                                     const unsigned char *input,
+                                     pmt::pmt_t &output,
+                                     pmt::pmt_t &info)
+    {
+      uint8_t* bytes_out = (uint8_t*)volk_malloc(header_nbytes(),
+                                                 volk_get_alignment());
+
+      header_buffer header(bytes_out);
+      header.add_field64(d_access_code, d_access_code_len);
+      header.add_field16((uint16_t)(nbytes_in));
+      header.add_field16((uint16_t)(nbytes_in));
+
+      // Package output data into a PMT vector
+      output = pmt::init_u8vector(header_nbytes(), bytes_out);
+
+      // Creating the output pmt copies data; free our own here.
+      volk_free(bytes_out);
+
+      return true;
+    }
+
+    bool
+    packet_formatter_default::parse(int nbits_in,
+                                    const unsigned char *input,
+                                    std::vector<pmt::pmt_t> &info)
+    {
+      int count = 0;
+
+      while(count < nbits_in) {
+        switch(d_state) {
+       case STATE_SYNC_SEARCH:    // Look for the access code correlation
+
+         while(count < nbits_in) {
+            // shift in new data
+            d_data_reg = (d_data_reg << 1) | ((input[count++]) & 0x1);
+            d_count++;
+
+            // compute hamming distance between desired access code and 
current data
+            uint64_t wrong_bits = 0;
+            uint64_t nwrong = d_threshold+1;
+
+            wrong_bits = (d_data_reg ^ d_access_code) & d_mask;
+            volk_64u_popcnt(&nwrong, wrong_bits);
+
+            if(nwrong <= d_threshold) {
+              enter_have_sync();
+              break;
+            }
+          }
+          break;
+
+       case STATE_HAVE_SYNC:
+         while(count < nbits_in) {    // Shift bits one at a time into header
+            d_hdr_reg.insert_bit(input[count++]);
+            d_count++;
+
+            if(d_hdr_reg.length() == (header_nbits()-d_access_code_len)) {
+             // we have a full header, check to see if it has been received 
properly
+             if(header_ok()) {
+                int payload_len = header_payload();
+               enter_have_header(payload_len);
+                info.push_back(d_info);
+              }
+             else {
+               enter_search();    // bad header
+              }
+              break;
+            }
+          }
+          break;
+
+       case STATE_HAVE_HEADER:
+         while(count < nbits_in) {
+            if(d_pkt_count < d_pkt_len/d_bps) {
+              count++;
+              d_pkt_count++;
+            }
+            if(d_pkt_count == d_pkt_len/d_bps) {
+              enter_search();
+              break;
+            }
+          }
+          break;
+        }
+      }
+
+      return true;
+    }
+
+    bool
+    packet_formatter_default::parse_soft(int nbits_in,
+                                         const float *input,
+                                         std::vector<pmt::pmt_t> &info)
+    {
+      int count = 0;
+
+      while(count < nbits_in) {
+        switch(d_state) {
+       case STATE_SYNC_SEARCH:    // Look for the access code correlation
+
+         while(count < nbits_in) {
+            // shift in new data
+            d_data_reg = (d_data_reg << 1) | 
(gr::branchless_binary_slicer(input[count++]) & 0x1);
+            d_count++;
+
+            // compute hamming distance between desired access code and 
current data
+            uint64_t wrong_bits = 0;
+            uint64_t nwrong = d_threshold+1;
+
+            wrong_bits = (d_data_reg ^ d_access_code) & d_mask;
+            volk_64u_popcnt(&nwrong, wrong_bits);
+
+            if(nwrong <= d_threshold) {
+              enter_have_sync();
+              break;
+            }
+          }
+          break;
+
+       case STATE_HAVE_SYNC:
+         while(count < nbits_in) {    // Shift bits one at a time into header
+            d_hdr_reg.insert_bit(gr::branchless_binary_slicer(input[count++]));
+            d_count++;
+
+            if(d_hdr_reg.length() == (header_nbits()-d_access_code_len)) {
+             // we have a full header, check to see if it has been received 
properly
+             if(header_ok()) {
+                int payload_len = header_payload();
+               enter_have_header(8*payload_len);
+                info.push_back(d_info);
+              }
+             else {
+               enter_search();    // bad header
+              }
+              break;
+            }
+          }
+          break;
+
+       case STATE_HAVE_HEADER:
+         while(count < nbits_in) {
+            if(d_pkt_count < d_pkt_len/d_bps) {
+              count++;
+              d_pkt_count++;
+            }
+            if(d_pkt_count == d_pkt_len/d_bps) {
+              enter_search();
+              break;
+            }
+          }
+          break;
+        }
+      }
+
+      return true;
+    }
+
+
+    size_t
+    packet_formatter_default::header_nbits() const
+    {
+      return d_access_code_len + 8*2*sizeof(uint16_t);
+    }
+
+    size_t
+    packet_formatter_default::header_nbytes() const
+    {
+      return d_access_code_len/8 + 2*sizeof(uint16_t);
+    }
+
+    inline void
+    packet_formatter_default::enter_search()
+    {
+      d_state = STATE_SYNC_SEARCH;
+    }
+
+    inline void
+    packet_formatter_default::enter_have_sync()
+    {
+      d_state = STATE_HAVE_SYNC;
+      d_hdr_reg.clear_input();
+    }
+
+    inline void
+    packet_formatter_default::enter_have_header(int payload_len)
+    {
+      d_state = STATE_HAVE_HEADER;
+      d_pkt_len = payload_len;
+      d_pkt_count = 0;
+      d_count = 0;
+    }
+
+    bool
+    packet_formatter_default::header_ok()
+    {
+      // confirm that two copies of header info are identical
+      uint16_t len0 = d_hdr_reg.extract_field16(0, 16);
+      uint16_t len1 = d_hdr_reg.extract_field16(16, 16);
+      return (len0 ^ len1) == 0;
+    }
+
+    int
+    packet_formatter_default::header_payload()
+    {
+      uint16_t len = d_hdr_reg.extract_field16(0, 16);
+
+      d_info = pmt::make_dict();
+      d_info = pmt::dict_add(d_info, pmt::intern("skip samps"),
+                             pmt::from_long(d_count));
+      d_info = pmt::dict_add(d_info, pmt::intern("payload bits"),
+                             pmt::from_long(8*len));
+      return static_cast<int>(len);
+    }
+
+  } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/packet_header_ofdm.cc 
b/gr-digital/lib/packet_header_ofdm.cc
index 7a95586..22d62df 100644
--- a/gr-digital/lib/packet_header_ofdm.cc
+++ b/gr-digital/lib/packet_header_ofdm.cc
@@ -1,18 +1,18 @@
 /* -*- c++ -*- */
 /* Copyright 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,
@@ -148,4 +148,3 @@ namespace gr {
 
   } /* namespace digital */
 } /* namespace gr */
-
diff --git a/gr-digital/lib/packet_parse_b_impl.cc 
b/gr-digital/lib/packet_parse_b_impl.cc
new file mode 100644
index 0000000..01f1653
--- /dev/null
+++ b/gr-digital/lib/packet_parse_b_impl.cc
@@ -0,0 +1,93 @@
+/* -*- 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 "packet_parse_b_impl.h"
+#include <gnuradio/io_signature.h>
+#include <stdexcept>
+#include <volk/volk.h>
+#include <iostream>
+
+namespace gr {
+  namespace digital {
+
+    packet_parse_b::sptr
+    packet_parse_b::make(const packet_formatter_default::sptr &formatter,
+                         unsigned int threshold)
+    {
+      return gnuradio::get_initial_sptr
+       (new packet_parse_b_impl(formatter, threshold));
+    }
+
+
+    packet_parse_b_impl::packet_parse_b_impl(const 
packet_formatter_default::sptr &formatter,
+                                             unsigned int threshold)
+      : sync_block("packet_parse_b",
+                   io_signature::make(1, 1, sizeof(char)),
+                   io_signature::make(0, 0, 0))
+    {
+      d_formatter = formatter;
+      set_threshold(threshold);
+
+      d_out_port = pmt::mp("info");
+      message_port_register_out(d_out_port);
+    }
+
+    packet_parse_b_impl::~packet_parse_b_impl()
+    {
+    }
+
+    void
+    packet_parse_b_impl::set_threshold(unsigned int thresh)
+    {
+      d_formatter->set_threshold(thresh);
+    }
+
+
+    unsigned int
+    packet_parse_b_impl::threshold() const
+    {
+      return d_formatter->threshold();
+    }
+
+    int
+    packet_parse_b_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];
+
+      std::vector<pmt::pmt_t> info;
+      d_formatter->parse(noutput_items, in, info);
+
+      for(size_t i = 0; i < info.size(); i++) {
+        message_port_pub(d_out_port, info[i]);
+      }
+
+      return noutput_items;
+    }
+
+  } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/packet_parse_b_impl.h 
b/gr-digital/lib/packet_parse_b_impl.h
new file mode 100644
index 0000000..4263ca4
--- /dev/null
+++ b/gr-digital/lib/packet_parse_b_impl.h
@@ -0,0 +1,53 @@
+/* -*- 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_PACKET_PARSE_B_IMPL_H
+#define INCLUDED_DIGITAL_PACKET_PARSE_B_IMPL_H
+
+#include <gnuradio/digital/packet_parse_b.h>
+
+namespace gr {
+  namespace digital {
+
+    class packet_parse_b_impl : public packet_parse_b
+    {
+     private:
+      packet_formatter_default::sptr d_formatter;
+      pmt::pmt_t d_out_port;
+
+     public:
+      packet_parse_b_impl(const packet_formatter_default::sptr &formatter,
+                          unsigned int threshold=0);
+      ~packet_parse_b_impl();
+
+      void set_threshold(unsigned int thresh);
+      unsigned int threshold() const;
+
+      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_PACKET_PARSE_B_IMPL_H */
diff --git a/gr-digital/lib/packet_parse_f_impl.cc 
b/gr-digital/lib/packet_parse_f_impl.cc
new file mode 100644
index 0000000..8a45e11
--- /dev/null
+++ b/gr-digital/lib/packet_parse_f_impl.cc
@@ -0,0 +1,92 @@
+/* -*- 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 "packet_parse_f_impl.h"
+#include <gnuradio/io_signature.h>
+#include <stdexcept>
+#include <volk/volk.h>
+#include <iostream>
+
+namespace gr {
+  namespace digital {
+
+    packet_parse_f::sptr
+    packet_parse_f::make(const packet_formatter_default::sptr &formatter,
+                         unsigned int threshold)
+    {
+      return gnuradio::get_initial_sptr
+       (new packet_parse_f_impl(formatter, threshold));
+    }
+
+
+    packet_parse_f_impl::packet_parse_f_impl(const 
packet_formatter_default::sptr &formatter,
+                                             unsigned int threshold)
+      : sync_block("packet_parse_f",
+                   io_signature::make(1, 1, sizeof(float)),
+                   io_signature::make(0, 0, 0))
+    {
+      d_formatter = formatter;
+      set_threshold(threshold);
+
+      d_out_port = pmt::mp("info");
+      message_port_register_out(d_out_port);
+    }
+
+    packet_parse_f_impl::~packet_parse_f_impl()
+    {
+    }
+
+    void
+    packet_parse_f_impl::set_threshold(unsigned int thresh)
+    {
+      d_formatter->set_threshold(thresh);
+    }
+
+    unsigned int
+    packet_parse_f_impl::threshold() const
+    {
+      return d_formatter->threshold();
+    }
+
+    int
+    packet_parse_f_impl::work(int noutput_items,
+                              gr_vector_const_void_star &input_items,
+                              gr_vector_void_star &output_items)
+    {
+      const float *in = (const float*)input_items[0];
+
+      std::vector<pmt::pmt_t> info;
+      d_formatter->parse_soft(noutput_items, in, info);
+
+      for(size_t i = 0; i < info.size(); i++) {
+        message_port_pub(d_out_port, info[i]);
+      }
+
+      return noutput_items;
+    }
+
+  } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/packet_parse_f_impl.h 
b/gr-digital/lib/packet_parse_f_impl.h
new file mode 100644
index 0000000..2c38975
--- /dev/null
+++ b/gr-digital/lib/packet_parse_f_impl.h
@@ -0,0 +1,53 @@
+/* -*- 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_PACKET_PARSE_F_IMPL_H
+#define INCLUDED_DIGITAL_PACKET_PARSE_F_IMPL_H
+
+#include <gnuradio/digital/packet_parse_f.h>
+
+namespace gr {
+  namespace digital {
+
+    class packet_parse_f_impl : public packet_parse_f
+    {
+     private:
+      packet_formatter_default::sptr d_formatter;
+      pmt::pmt_t d_out_port;
+
+     public:
+      packet_parse_f_impl(const packet_formatter_default::sptr &formatter,
+                          unsigned int threshold=0);
+      ~packet_parse_f_impl();
+
+      void set_threshold(unsigned int thresh);
+      unsigned int threshold() const;
+
+      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_PACKET_PARSE_F_IMPL_H */
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/lib/qa_digital.cc
similarity index 57%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/qa_digital.cc
index 7c06d19..ad88de5 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/qa_digital.cc
@@ -1,34 +1,39 @@
-/* -*- c++ -*- */
 /*
- * Copyright 2012 Free Software Foundation, Inc.
- * 
+ * 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.
  */
 
-%template(packet_header_default_sptr) 
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+/*
+ * This class gathers together all the test cases for the gr-digital
+ * directory into a single test suite.  As you create new test cases,
+ * add them here.
+ */
+
+#include "qa_digital.h"
+#include "qa_packet_formatters.h"
+
+CppUnit::TestSuite *
+qa_digital::suite()
+{
+  CppUnit::TestSuite *s = new CppUnit::TestSuite("gr-digital");
 
-%template(packet_header_ofdm_sptr) 
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+  s->addTest(qa_packet_formatters::suite());
 
+  return s;
+}
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/lib/qa_digital.h
similarity index 59%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/qa_digital.h
index 7c06d19..c5f3592 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/qa_digital.h
@@ -1,34 +1,38 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2012 Free Software Foundation, Inc.
- * 
+ * 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.
  */
 
-%template(packet_header_default_sptr) 
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+#ifndef _QA_GR_DIGITAL_H_
+#define _QA_GR_DIGITAL_H_
 
-%template(packet_header_ofdm_sptr) 
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+#include <gnuradio/attributes.h>
+#include <cppunit/TestSuite.h>
 
+//! collect all the tests for the gr-digital directory
+
+class __GR_ATTR_EXPORT qa_digital
+{
+ public:
+  //! return suite of tests for all of gr-digital directory
+  static CppUnit::TestSuite *suite();
+};
+
+#endif /* _QA_GR_DIGITAL_H_ */
diff --git a/gr-digital/lib/qa_packet_formatters.cc 
b/gr-digital/lib/qa_packet_formatters.cc
new file mode 100644
index 0000000..a36c55a
--- /dev/null
+++ b/gr-digital/lib/qa_packet_formatters.cc
@@ -0,0 +1,417 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2013 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/attributes.h>
+
+#include <stdio.h>
+#include <cmath>
+#include <volk/volk.h>
+#include <gnuradio/expj.h>
+#include <cppunit/TestAssert.h>
+
+#include "qa_packet_formatters.h"
+#include <gnuradio/digital/packet_formatter_counter.h>
+#include <gnuradio/digital/packet_formatter_default.h>
+#include <gnuradio/blocks/unpack_k_bits.h>
+
+void
+qa_packet_formatters::test_default_format()
+{
+  static const int N = 4800;
+  int upper8 = (N >> 8) & 0xFF;
+  int lower8 = N & 0xFF;
+
+  std::string ac = "1010101010101010"; //0xAAAA
+  unsigned char *data = (unsigned char*)volk_malloc(N*sizeof(unsigned char),
+                                                    volk_get_alignment());
+  srand (time(NULL));
+  for(unsigned int i = 0; i < N; i++) {
+    data[i] = rand() % 256;
+  }
+
+  gr::digital::packet_formatter_default::sptr formatter;
+  formatter = gr::digital::packet_formatter_default::make(ac);
+
+  pmt::pmt_t output;
+  pmt::pmt_t info = pmt::make_dict();
+
+  bool ret = formatter->format(N, data, output, info);
+  size_t length = pmt::length(output);
+
+  CPPUNIT_ASSERT(ret);
+  CPPUNIT_ASSERT_EQUAL(length, formatter->header_nbytes());
+  CPPUNIT_ASSERT_EQUAL(8*length, formatter->header_nbits());
+
+  // Test access code formatted correctly
+  unsigned char h0 = pmt::u8vector_ref(output, 0);
+  unsigned char h1 = pmt::u8vector_ref(output, 1);
+  CPPUNIT_ASSERT_EQUAL(0xAA, (int)h0);
+  CPPUNIT_ASSERT_EQUAL(0xAA, (int)h1);
+
+  // Test upper and lower portion of length field, repeated twice
+  unsigned char h2 = pmt::u8vector_ref(output, 2);
+  unsigned char h3 = pmt::u8vector_ref(output, 3);
+  unsigned char h4 = pmt::u8vector_ref(output, 4);
+  unsigned char h5 = pmt::u8vector_ref(output, 5);
+  CPPUNIT_ASSERT_EQUAL(upper8, (int)h2);
+  CPPUNIT_ASSERT_EQUAL(lower8, (int)h3);
+  CPPUNIT_ASSERT_EQUAL(upper8, (int)h4);
+  CPPUNIT_ASSERT_EQUAL(lower8, (int)h5);
+
+  volk_free(data);
+}
+
+
+void
+qa_packet_formatters::test_default_parse()
+{
+  static const int nbytes = 106;
+  static const int nbits = 8*nbytes;
+  unsigned char *bytes = (unsigned char*)volk_malloc(nbytes*sizeof(unsigned 
char),
+                                                     volk_get_alignment());
+  unsigned char *bits = (unsigned char*)volk_malloc(nbits*sizeof(unsigned 
char),
+                                                    volk_get_alignment());
+
+  srand(time(NULL));
+
+  // Fill bytes with random values
+  for(unsigned int i = 0; i < nbytes; i++) {
+    bytes[i] = rand() % 256;
+  }
+
+  int index = 0;
+  bytes[index+0] = 0xAA;
+  bytes[index+1] = 0xAA;
+  bytes[index+2] = 0x00;
+  bytes[index+3] = 0x64;
+  bytes[index+4] = 0x00;
+  bytes[index+5] = 0x64;
+
+  gr::blocks::kernel::unpack_k_bits unpacker = 
gr::blocks::kernel::unpack_k_bits(8);
+  unpacker.unpack(bits, bytes, nbytes);
+
+  std::string ac = "1010101010101010"; //0xAAAA
+  gr::digital::packet_formatter_default::sptr formatter;
+  formatter = gr::digital::packet_formatter_default::make(ac);
+  formatter->set_threshold(0);
+
+  std::vector<pmt::pmt_t> info;
+  bool ret = formatter->parse(nbits, bits, info);
+
+  CPPUNIT_ASSERT(ret);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, info.size());
+
+  pmt::pmt_t dict = info[0];
+  int payload_bits = pmt::to_long(pmt::dict_ref(dict, pmt::intern("payload 
bits"),
+                                                pmt::PMT_NIL));
+  int skip_samps = pmt::to_long(pmt::dict_ref(dict, pmt::intern("skip samps"),
+                                              pmt::PMT_NIL));
+
+  int hdr_bits = (int)formatter->header_nbits();
+  int expected_bits = nbits - hdr_bits;
+  int expected_skip = index * 8 + hdr_bits;
+  CPPUNIT_ASSERT_EQUAL(expected_bits, payload_bits);
+  CPPUNIT_ASSERT_EQUAL(expected_skip, skip_samps);
+
+  volk_free(bytes);
+  volk_free(bits);
+}
+
+void
+qa_packet_formatters::test_default_parse_soft()
+{
+  static const int nbytes = 106;
+  static const int nbits = 8*nbytes;
+  unsigned char *bytes = (unsigned char*)volk_malloc(nbytes*sizeof(unsigned 
char),
+                                                     volk_get_alignment());
+  unsigned char *bits = (unsigned char*)volk_malloc(nbits*sizeof(unsigned 
char),
+                                                    volk_get_alignment());
+  float *soft = (float*)volk_malloc(nbits*sizeof(float),
+                                    volk_get_alignment());
+
+  srand(time(NULL));
+
+  // Fill bytes with random values
+  for(unsigned int i = 0; i < nbytes; i++) {
+    bytes[i] = rand() % 256;
+  }
+
+  int index = 0;
+  bytes[index+0] = 0xAA;
+  bytes[index+1] = 0xAA;
+  bytes[index+2] = 0x00;
+  bytes[index+3] = 0x64;
+  bytes[index+4] = 0x00;
+  bytes[index+5] = 0x64;
+
+  gr::blocks::kernel::unpack_k_bits unpacker = 
gr::blocks::kernel::unpack_k_bits(8);
+  unpacker.unpack(bits, bytes, nbytes);
+
+  // Convert bits to +/-1 and add a small bit of noise
+  std::vector<float> sub(nbits, 1.0f);
+  volk_8i_s32f_convert_32f(soft, (const int8_t*)bits, 1.0, nbits);
+  volk_32f_s32f_multiply_32f(soft, soft, 2.0, nbits);
+  volk_32f_x2_subtract_32f(soft, soft, &sub[0], nbits);
+  for(unsigned int i = 0; i < nbits; i++) {
+    soft[i] += 0.1 * ((float)rand() / (float)RAND_MAX - 0.5);
+  }
+
+  std::string ac = "1010101010101010"; //0xAAAA
+  gr::digital::packet_formatter_default::sptr formatter;
+  formatter = gr::digital::packet_formatter_default::make(ac);
+  formatter->set_threshold(0);
+
+  std::vector<pmt::pmt_t> info;
+  bool ret = formatter->parse_soft(nbits, soft, info);
+
+  CPPUNIT_ASSERT(ret);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, info.size());
+
+  pmt::pmt_t dict = info[0];
+  int payload_bits = pmt::to_long(pmt::dict_ref(dict, pmt::intern("payload 
bits"),
+                                                pmt::PMT_NIL));
+  int skip_samps = pmt::to_long(pmt::dict_ref(dict, pmt::intern("skip samps"),
+                                              pmt::PMT_NIL));
+
+  int hdr_bits = (int)formatter->header_nbits();
+  int expected_bits = nbits - hdr_bits;
+  int expected_skip = index * 8 + hdr_bits;
+  CPPUNIT_ASSERT_EQUAL(expected_bits, payload_bits);
+  CPPUNIT_ASSERT_EQUAL(expected_skip, skip_samps);
+
+  volk_free(bytes);
+  volk_free(bits);
+}
+
+
+void
+qa_packet_formatters::test_counter_format()
+{
+  static const int N = 4800;
+  int upper8 = (N >> 8) & 0xFF;
+  int lower8 = N & 0xFF;
+
+  std::string ac = "1010101010101010"; //0xAAAA
+  unsigned char *data = (unsigned char*)volk_malloc(N*sizeof(unsigned char),
+                                                    volk_get_alignment());
+  srand (time(NULL));
+  for(unsigned int i = 0; i < N; i++) {
+    data[i] = rand() % 256;
+  }
+
+  uint16_t expected_bps = 2;
+  gr::digital::packet_formatter_counter::sptr formatter;
+  formatter = gr::digital::packet_formatter_counter::make(ac, expected_bps);
+
+  pmt::pmt_t output;
+  pmt::pmt_t info = pmt::make_dict();
+
+  bool ret = formatter->format(N, data, output, info);
+  size_t length = pmt::length(output);
+
+  CPPUNIT_ASSERT(ret);
+  CPPUNIT_ASSERT_EQUAL(length, formatter->header_nbytes());
+  CPPUNIT_ASSERT_EQUAL(8*length, formatter->header_nbits());
+
+  // Test access code formatted correctly
+  unsigned char h0 = pmt::u8vector_ref(output, 0);
+  unsigned char h1 = pmt::u8vector_ref(output, 1);
+  CPPUNIT_ASSERT_EQUAL(0xAA, (int)h0);
+  CPPUNIT_ASSERT_EQUAL(0xAA, (int)h1);
+
+  // Test upper and lower portion of length field, repeated twice
+  unsigned char h2 = pmt::u8vector_ref(output, 2);
+  unsigned char h3 = pmt::u8vector_ref(output, 3);
+  unsigned char h4 = pmt::u8vector_ref(output, 4);
+  unsigned char h5 = pmt::u8vector_ref(output, 5);
+  CPPUNIT_ASSERT_EQUAL(upper8, (int)h2);
+  CPPUNIT_ASSERT_EQUAL(lower8, (int)h3);
+  CPPUNIT_ASSERT_EQUAL(upper8, (int)h4);
+  CPPUNIT_ASSERT_EQUAL(lower8, (int)h5);
+
+  uint16_t h6 = (uint16_t)pmt::u8vector_ref(output, 6);
+  uint16_t h7 = (uint16_t)pmt::u8vector_ref(output, 7);
+  uint16_t bps = ((h6 << 8) & 0xFF00) | (h7 & 0x00FF);
+  CPPUNIT_ASSERT_EQUAL(expected_bps, bps);
+
+  uint16_t h8 = pmt::u8vector_ref(output, 8);
+  uint16_t h9 = pmt::u8vector_ref(output, 9);
+  uint16_t counter = ((h8 << 8) & 0xFF00) | (h9 & 0x00FF);
+  CPPUNIT_ASSERT_EQUAL((uint16_t)0, counter);
+
+  // Run another format to increment the counter to 1 and test.
+  ret = formatter->format(N, data, output, info);
+  h8 = pmt::u8vector_ref(output, 8);
+  h9 = pmt::u8vector_ref(output, 9);
+  counter = ((h8 << 8) & 0xFF00) | (h9 & 0x00FF);
+  CPPUNIT_ASSERT_EQUAL((uint16_t)1, counter);
+
+  volk_free(data);
+}
+
+
+void
+qa_packet_formatters::test_counter_parse()
+{
+  static const int nbytes = 110;
+  static const int nbits = 8*nbytes;
+  unsigned char *bytes = (unsigned char*)volk_malloc(nbytes*sizeof(unsigned 
char),
+                                                     volk_get_alignment());
+  unsigned char *bits = (unsigned char*)volk_malloc(nbits*sizeof(unsigned 
char),
+                                                    volk_get_alignment());
+
+  srand(time(NULL));
+
+  // Fill bytes with random values
+  for(unsigned int i = 0; i < nbytes; i++) {
+    bytes[i] = rand() % 256;
+  }
+
+  int index = 0;
+  bytes[index+0] = 0xAA;
+  bytes[index+1] = 0xAA;
+  bytes[index+2] = 0x00;
+  bytes[index+3] = 0x64;
+  bytes[index+4] = 0x00;
+  bytes[index+5] = 0x64;
+  bytes[index+6] = 0x00;
+  bytes[index+7] = 0x02;
+  bytes[index+8] = 0x00;
+  bytes[index+9] = 0x00;
+
+  gr::blocks::kernel::unpack_k_bits unpacker = 
gr::blocks::kernel::unpack_k_bits(8);
+  unpacker.unpack(bits, bytes, nbytes);
+
+  uint16_t expected_bps = 2;
+  std::string ac = "1010101010101010"; //0xAAAA
+  gr::digital::packet_formatter_counter::sptr formatter;
+  formatter = gr::digital::packet_formatter_counter::make(ac, expected_bps);
+  formatter->set_threshold(0);
+
+  std::vector<pmt::pmt_t> info;
+  bool ret = formatter->parse(nbits, bits, info);
+
+  CPPUNIT_ASSERT(ret);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, info.size());
+
+  pmt::pmt_t dict = info[0];
+  int payload_bits = pmt::to_long(pmt::dict_ref(dict, pmt::intern("payload 
bits"),
+                                                pmt::PMT_NIL));
+  int skip_samps = pmt::to_long(pmt::dict_ref(dict, pmt::intern("skip samps"),
+                                              pmt::PMT_NIL));
+  int bps = pmt::to_long(pmt::dict_ref(dict, pmt::intern("bps"),
+                                       pmt::PMT_NIL));
+  int counter = pmt::to_long(pmt::dict_ref(dict, pmt::intern("counter"),
+                                           pmt::PMT_NIL));
+
+  int hdr_bits = (int)formatter->header_nbits();
+  int expected_bits = nbits - hdr_bits;
+  int expected_skip = index * 8 + hdr_bits;
+  CPPUNIT_ASSERT_EQUAL(expected_bits, payload_bits);
+  CPPUNIT_ASSERT_EQUAL(expected_skip, skip_samps);
+  CPPUNIT_ASSERT_EQUAL(expected_bps, (uint16_t)bps);
+  CPPUNIT_ASSERT_EQUAL(0, counter);
+
+  volk_free(bytes);
+  volk_free(bits);
+}
+
+void
+qa_packet_formatters::test_counter_parse_soft()
+{
+  static const int nbytes = 110;
+  static const int nbits = 8*nbytes;
+  unsigned char *bytes = (unsigned char*)volk_malloc(nbytes*sizeof(unsigned 
char),
+                                                     volk_get_alignment());
+  unsigned char *bits = (unsigned char*)volk_malloc(nbits*sizeof(unsigned 
char),
+                                                    volk_get_alignment());
+  float *soft = (float*)volk_malloc(nbits*sizeof(float),
+                                    volk_get_alignment());
+
+  srand(time(NULL));
+
+  // Fill bytes with random values
+  for(unsigned int i = 0; i < nbytes; i++) {
+    bytes[i] = rand() % 256;
+  }
+
+  int index = 0;
+  bytes[index+0] = 0xAA;
+  bytes[index+1] = 0xAA;
+  bytes[index+2] = 0x00;
+  bytes[index+3] = 0x64;
+  bytes[index+4] = 0x00;
+  bytes[index+5] = 0x64;
+  bytes[index+6] = 0x00;
+  bytes[index+7] = 0x02;
+  bytes[index+8] = 0x00;
+  bytes[index+9] = 0x00;
+
+  gr::blocks::kernel::unpack_k_bits unpacker = 
gr::blocks::kernel::unpack_k_bits(8);
+  unpacker.unpack(bits, bytes, nbytes);
+
+  // Convert bits to +/-1 and add a small bit of noise
+  std::vector<float> sub(nbits, 1.0f);
+  volk_8i_s32f_convert_32f(soft, (const int8_t*)bits, 1.0, nbits);
+  volk_32f_s32f_multiply_32f(soft, soft, 2.0, nbits);
+  volk_32f_x2_subtract_32f(soft, soft, &sub[0], nbits);
+  for(unsigned int i = 0; i < nbits; i++) {
+    soft[i] += 0.1 * ((float)rand() / (float)RAND_MAX - 0.5);
+  }
+
+  uint16_t expected_bps = 2;
+  std::string ac = "1010101010101010"; //0xAAAA
+  gr::digital::packet_formatter_counter::sptr formatter;
+  formatter = gr::digital::packet_formatter_counter::make(ac, expected_bps);
+  formatter->set_threshold(0);
+
+  std::vector<pmt::pmt_t> info;
+  bool ret = formatter->parse_soft(nbits, soft, info);
+
+  CPPUNIT_ASSERT(ret);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, info.size());
+
+  pmt::pmt_t dict = info[0];
+  int payload_bits = pmt::to_long(pmt::dict_ref(dict, pmt::intern("payload 
bits"),
+                                                pmt::PMT_NIL));
+  int skip_samps = pmt::to_long(pmt::dict_ref(dict, pmt::intern("skip samps"),
+                                              pmt::PMT_NIL));
+  int bps = pmt::to_long(pmt::dict_ref(dict, pmt::intern("bps"),
+                                       pmt::PMT_NIL));
+  int counter = pmt::to_long(pmt::dict_ref(dict, pmt::intern("counter"),
+                                           pmt::PMT_NIL));
+
+  int hdr_bits = (int)formatter->header_nbits();
+  int expected_bits = nbits - hdr_bits;
+  int expected_skip = index * 8 + hdr_bits;
+  CPPUNIT_ASSERT_EQUAL(expected_bits, payload_bits);
+  CPPUNIT_ASSERT_EQUAL(expected_skip, skip_samps);
+  CPPUNIT_ASSERT_EQUAL(expected_bps, (uint16_t)bps);
+  CPPUNIT_ASSERT_EQUAL(0, counter);
+
+  volk_free(bytes);
+  volk_free(bits);
+}
diff --git a/gr-digital/lib/qa_packet_formatters.h 
b/gr-digital/lib/qa_packet_formatters.h
new file mode 100644
index 0000000..83ed270
--- /dev/null
+++ b/gr-digital/lib/qa_packet_formatters.h
@@ -0,0 +1,49 @@
+/* -*- 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 _QA_DIGITAL_PACKET_FORMATTERS_H_
+#define _QA_DIGITAL_PACKET_FORMATTERS_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_packet_formatters : public CppUnit::TestCase
+{
+  CPPUNIT_TEST_SUITE(qa_packet_formatters);
+  CPPUNIT_TEST(test_default_format);
+  CPPUNIT_TEST(test_default_parse);
+  CPPUNIT_TEST(test_default_parse_soft);
+  CPPUNIT_TEST(test_counter_format);
+  CPPUNIT_TEST(test_counter_parse);
+  CPPUNIT_TEST(test_counter_parse_soft);
+  CPPUNIT_TEST_SUITE_END();
+
+ private:
+  void test_default_format();
+  void test_default_parse();
+  void test_default_parse_soft();
+  void test_counter_format();
+  void test_counter_parse();
+  void test_counter_parse_soft();
+};
+
+#endif /* _QA_DIGITAL_PACKET_FORMATTERS_H_ */
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/lib/test_gr_digital.cc
similarity index 53%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/test_gr_digital.cc
index 7c06d19..7a6049d 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/test_gr_digital.cc
@@ -1,34 +1,48 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2012 Free Software Foundation, Inc.
- * 
+ * 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.
  */
 
-%template(packet_header_default_sptr) 
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
-%template(packet_header_ofdm_sptr) 
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+#include <cppunit/TextTestRunner.h>
+#include <cppunit/XmlOutputter.h>
 
+#include <gnuradio/unittests.h>
+#include "qa_digital.h"
+#include <iostream>
+#include <fstream>
+
+int
+main(int argc, char **argv)
+{
+  CppUnit::TextTestRunner runner;
+  std::ofstream xmlfile(get_unittest_path("digital.xml").c_str());
+  CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), 
xmlfile);
+
+  runner.addTest(qa_digital::suite());
+  runner.setOutputter(xmlout);
+
+  bool was_successful = runner.run("", false);
+
+  return was_successful ? 0 : 1;
+}
diff --git a/gr-digital/python/digital/qa_packet_format.py 
b/gr-digital/python/digital/qa_packet_format.py
new file mode 100644
index 0000000..40bc144
--- /dev/null
+++ b/gr-digital/python/digital/qa_packet_format.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+import random, time, struct
+import pmt
+from gnuradio import gr, gr_unittest, digital, blocks
+from gnuradio.digital import packet_utils
+
+class test_packet_format_fb(gr_unittest.TestCase):
+
+    def setUp(self):
+        self.tb = gr.top_block()
+
+    def tearDown(self):
+        self.tb = None
+
+    def test_packet_format_async_default(self):
+        ac = packet_utils.default_access_code
+        formatter = digital.packet_formatter_default(ac)
+
+        pkt_header = digital.packet_format_async(formatter)
+        snk_hdr = blocks.message_debug()
+        snk_pld = blocks.message_debug()
+
+        self.tb.msg_connect(pkt_header, 'header', snk_hdr, 'store')
+        self.tb.msg_connect(pkt_header, 'payload', snk_pld, 'store')
+
+
+        send_str = "Hello World"
+        send_pmt = pmt.make_u8vector(len(send_str), ord(' '))
+        for i in range(len(send_str)):
+            pmt.u8vector_set(send_pmt, i, ord(send_str[i]))
+        msg = pmt.cons(pmt.PMT_NIL, send_pmt)
+
+        port = pmt.intern("in")
+        pkt_header.to_basic_block()._post(port, msg)
+
+        self.tb.start()
+        while (snk_hdr.num_messages() < 1) and (snk_pld.num_messages() < 1):
+            time.sleep(0.1)
+        self.tb.stop()
+        self.tb.wait()
+
+        result_hdr_pmt = pmt.cdr(snk_hdr.get_message(0))
+        result_pld_pmt = pmt.cdr(snk_pld.get_message(0))
+
+        result_hdr = pmt.u8vector_elements(result_hdr_pmt)
+        result_pld = pmt.u8vector_elements(result_pld_pmt)
+        header = "".join([chr(r) for r in result_hdr])
+        payload = "".join([chr(r) for r in result_pld])
+
+        access_code = 
packet_utils.conv_1_0_string_to_packed_binary_string(packet_utils.default_access_code)[0]
+        rx_access_code = header[0:len(access_code)]
+
+        length = len(send_str)
+        rx_length = struct.unpack_from("!H", header, len(access_code))[0]
+
+        self.assertEqual(access_code, rx_access_code)
+        self.assertEqual(length, rx_length)
+        self.assertEqual(length, len(payload))
+        self.assertEqual(send_str, payload[0:length])
+
+
+    def test_packet_format_async_counter(self):
+        bps = 2
+        ac = packet_utils.default_access_code
+        formatter = digital.packet_formatter_counter(ac, 2)
+
+        pkt_header = digital.packet_format_async(formatter)
+        snk_hdr = blocks.message_debug()
+        snk_pld = blocks.message_debug()
+
+        self.tb.msg_connect(pkt_header, 'header', snk_hdr, 'store')
+        self.tb.msg_connect(pkt_header, 'payload', snk_pld, 'store')
+
+
+        send_str = "Hello World" + 1000*"xxx"
+        send_pmt = pmt.make_u8vector(len(send_str), ord(' '))
+        for i in range(len(send_str)):
+            pmt.u8vector_set(send_pmt, i, ord(send_str[i]))
+        msg = pmt.cons(pmt.PMT_NIL, send_pmt)
+
+        port = pmt.intern("in")
+        pkt_header.to_basic_block()._post(port, msg)
+
+        self.tb.start()
+        while (snk_hdr.num_messages() < 1) and (snk_pld.num_messages() < 1):
+            time.sleep(0.1)
+        self.tb.stop()
+        self.tb.wait()
+
+        result_hdr_pmt = pmt.cdr(snk_hdr.get_message(0))
+        result_pld_pmt = pmt.cdr(snk_pld.get_message(0))
+
+        result_hdr = pmt.u8vector_elements(result_hdr_pmt)
+        result_pld = pmt.u8vector_elements(result_pld_pmt)
+        header = "".join([chr(r) for r in result_hdr])
+        payload = "".join([chr(r) for r in result_pld])
+
+        access_code = 
packet_utils.conv_1_0_string_to_packed_binary_string(packet_utils.default_access_code)[0]
+        rx_access_code = header[0:len(access_code)]
+
+        length = len(send_str)
+        rx_length = struct.unpack_from("!H", header, len(access_code))[0]
+        rx_bps = struct.unpack_from("!H", header, len(access_code)+4)[0]
+        rx_counter = struct.unpack_from("!H", header, len(access_code)+6)[0]
+
+        self.assertEqual(access_code, rx_access_code)
+        self.assertEqual(length, rx_length)
+        self.assertEqual(bps, rx_bps)
+        self.assertEqual(0, rx_counter)
+        self.assertEqual(length, len(payload))
+        self.assertEqual(send_str, payload[0:length])
+
+if __name__ == '__main__':
+    gr_unittest.run(test_packet_format_fb, "test_packet_format_fb.xml")
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index d87b7e9..2f00dc1 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -30,6 +30,7 @@ set(GR_SWIG_INCLUDE_DIRS
     ${GR_FFT_INCLUDE_DIRS}
     ${GR_FILTER_INCLUDE_DIRS}
     ${GNURADIO_RUNTIME_SWIG_INCLUDE_DIRS}
+    ${VOLK_INCLUDE_DIRS}
     ${Boost_INCLUDE_DIRS}
 )
 
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index d7a3b81..b0fe202 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -100,6 +100,11 @@
 #include "gnuradio/digital/ofdm_sampler.h"
 #include "gnuradio/digital/ofdm_serializer_vcc.h"
 #include "gnuradio/digital/ofdm_sync_sc_cfb.h"
+#include "gnuradio/digital/packet_formatter_default.h"
+#include "gnuradio/digital/packet_formatter_counter.h"
+#include "gnuradio/digital/packet_format_async.h"
+#include "gnuradio/digital/packet_parse_b.h"
+#include "gnuradio/digital/packet_parse_f.h"
 #include "gnuradio/digital/packet_header_default.h"
 #include "gnuradio/digital/packet_header_ofdm.h"
 #include "gnuradio/digital/packet_headergenerator_bb.h"
@@ -181,6 +186,11 @@
 %include "gnuradio/digital/ofdm_sampler.h"
 %include "gnuradio/digital/ofdm_serializer_vcc.h"
 %include "gnuradio/digital/ofdm_sync_sc_cfb.h"
+%include "gnuradio/digital/packet_formatter_default.h"
+%include "gnuradio/digital/packet_formatter_counter.h"
+%include "gnuradio/digital/packet_format_async.h"
+%include "gnuradio/digital/packet_parse_b.h"
+%include "gnuradio/digital/packet_parse_f.h"
 %include "gnuradio/digital/packet_header_default.h"
 %include "gnuradio/digital/packet_header_ofdm.h"
 %include "gnuradio/digital/packet_headergenerator_bb.h"
@@ -249,6 +259,9 @@ GR_SWIG_BLOCK_MAGIC2(digital, ofdm_mapper_bcv);
 GR_SWIG_BLOCK_MAGIC2(digital, ofdm_sampler);
 GR_SWIG_BLOCK_MAGIC2(digital, ofdm_serializer_vcc);
 GR_SWIG_BLOCK_MAGIC2(digital, ofdm_sync_sc_cfb);
+GR_SWIG_BLOCK_MAGIC2(digital, packet_format_async);
+GR_SWIG_BLOCK_MAGIC2(digital, packet_parse_b);
+GR_SWIG_BLOCK_MAGIC2(digital, packet_parse_f);
 GR_SWIG_BLOCK_MAGIC2(digital, packet_headergenerator_bb);
 GR_SWIG_BLOCK_MAGIC2(digital, packet_headerparser_b);
 GR_SWIG_BLOCK_MAGIC2(digital, packet_sink);
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/swig/packet_header.i
index 7c06d19..86ee8d9 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/swig/packet_header.i
@@ -1,19 +1,19 @@
 /* -*- c++ -*- */
 /*
  * Copyright 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,
@@ -32,3 +32,15 @@ packet_header_ofdm_sptr.__repr__ = lambda self: 
"<packet_header_ofdm>"
 packet_header_ofdm = packet_header_ofdm .make;
 %}
 
+%template(packet_formatter_default_sptr) 
boost::shared_ptr<gr::digital::packet_formatter_default>;
+%pythoncode %{
+packet_formatter_default_sptr.__repr__ = lambda self: 
"<packet_formatter_default>"
+packet_formatter_default = packet_formatter_default .make;
+%}
+
+
+%template(packet_formatter_counter_sptr) 
boost::shared_ptr<gr::digital::packet_formatter_counter>;
+%pythoncode %{
+packet_formatter_counter_sptr.__repr__ = lambda self: 
"<packet_formatter_counter>"
+packet_formatter_counter = packet_formatter_counter .make;
+%}



reply via email to

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