commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] [gnuradio] 24/24: digital: fixed up some header_buffer


From: git
Subject: [Commit-gnuradio] [gnuradio] 24/24: digital: fixed up some header_buffer issues and added QA.
Date: Tue, 14 Jun 2016 00:41:02 +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 93acb5ba759b64ddbbc7c5c9dd1a810a9842285b
Author: Tom Rondeau <address@hidden>
Date:   Fri Apr 29 15:20:59 2016 -0400

    digital: fixed up some header_buffer issues and added QA.
---
 .../include/gnuradio/digital/header_buffer.h       |  67 ++--
 gr-digital/lib/CMakeLists.txt                      |   1 +
 gr-digital/lib/header_buffer.cc                    |  47 +--
 gr-digital/lib/header_format_crc.cc                |   4 +-
 gr-digital/lib/header_format_default.cc            |   2 +-
 gr-digital/lib/header_format_ofdm.cc               |   4 +-
 gr-digital/lib/qa_digital.cc                       |   2 +
 gr-digital/lib/qa_header_buffer.cc                 | 364 +++++++++++++++++++++
 gr-digital/lib/qa_header_buffer.h                  |  59 ++++
 9 files changed, 494 insertions(+), 56 deletions(-)

diff --git a/gr-digital/include/gnuradio/digital/header_buffer.h 
b/gr-digital/include/gnuradio/digital/header_buffer.h
index b3f3e2c..ddcc2a8 100644
--- a/gr-digital/include/gnuradio/digital/header_buffer.h
+++ b/gr-digital/include/gnuradio/digital/header_buffer.h
@@ -24,6 +24,7 @@
 
 #include <gnuradio/digital/api.h>
 #include <vector>
+#include <stdint.h>
 
 namespace gr {
   namespace digital {
@@ -60,11 +61,9 @@ namespace gr {
      * digital::header_format_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.
+     * are to be transmitted in network byte order. We can adjust the
+     * direction of the bytes by setting the byte-swap flag, \p bs, to
+     * true or false.
      *
      * The length argument (\p len) for all add_field[N] calls is the
      * number of bytes actually accounted for in the data
@@ -117,8 +116,8 @@ namespace gr {
      * 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.
+     * current header, call clear() 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
@@ -191,6 +190,19 @@ namespace gr {
       ~header_buffer();
 
       /*!
+       * Clears the header.
+       *
+       * In transmit mode, this resets the current offset so new
+       * add_field functions start adding data to the start of the
+       * buffer.
+       *
+       * In receive mode, this clears the buffer that we have inserted
+       * bits in to.
+       */
+      void clear();
+
+
+      /*!
        * In transmit mode, this returns the length of the data in
        * the buffer (not the allocated buffer length).
        *
@@ -209,36 +221,36 @@ namespace gr {
        *
        * \param data The 8-bit data item.
        * \param len Length (in bits) of \p data.
-       * \param be Set to 'true' if data is already big endian.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      void add_field8(uint8_t data, int len=8, bool be=false);
+      void add_field8(uint8_t data, int len=8, bool bs=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.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      void add_field16(uint16_t data, int len=16, bool be=false);
+      void add_field16(uint16_t data, int len=16, bool bs=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.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      void add_field32(uint32_t data, int len=32, bool be=false);
+      void add_field32(uint32_t data, int len=32, bool bs=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.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      void add_field64(uint64_t data, int len=64, bool be=false);
+      void add_field64(uint64_t data, int len=64, bool bs=false);
 
 
 
@@ -247,52 +259,49 @@ namespace gr {
        *****************************************************/
 
       /*!
-       * Insert a new bit on the back of the input buffer.
+       * Insert a new bit on the back of the input buffer. This
+       * function is used in receive mode to add new bits as they are
+       * received for later use of the extract_field functions.
        *
        * \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.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      uint8_t extract_field8(int pos, int len=8, bool be=false);
+      uint8_t extract_field8(int pos, int len=8, bool bs=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.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      uint16_t extract_field16(int pos, int len=16, bool be=false);
+      uint16_t extract_field16(int pos, int len=16, bool bs=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.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      uint32_t extract_field32(int pos, int len=32, bool be=false);
+      uint32_t extract_field32(int pos, int len=32, bool bs=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.
+       * \param bs Set to 'true' to byte swap the data.
        */
-      uint64_t extract_field64(int pos, int len=64, bool be=false);
+      uint64_t extract_field64(int pos, int len=64, bool bs=false);
     };
 
   } // namespace digital
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index 7e9ebed..84f53ec 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -215,6 +215,7 @@ if(ENABLE_TESTING)
     ${CMAKE_CURRENT_SOURCE_DIR}/test_gr_digital.cc
     ${CMAKE_CURRENT_SOURCE_DIR}/qa_digital.cc
     ${CMAKE_CURRENT_SOURCE_DIR}/qa_header_format.cc
+    ${CMAKE_CURRENT_SOURCE_DIR}/qa_header_buffer.cc
     )
 
   add_executable(test-gr-digital ${test_gr_digital_sources})
diff --git a/gr-digital/lib/header_buffer.cc b/gr-digital/lib/header_buffer.cc
index 8cb0b17..04233da 100644
--- a/gr-digital/lib/header_buffer.cc
+++ b/gr-digital/lib/header_buffer.cc
@@ -42,12 +42,21 @@ namespace gr {
     {
     }
 
+    void
+    header_buffer::clear()
+    {
+      if(d_buffer) // TX mode
+        d_offset = 0;
+      else // RX mode
+        d_input.clear();
+    }
+
     size_t
     header_buffer::length() const
     {
-      if(d_buffer)
+      if(d_buffer) // TX mode
         return d_offset;
-      else
+      else // RX mode
         return d_input.size();
     }
 
@@ -58,7 +67,7 @@ namespace gr {
     }
 
     void
-    header_buffer::add_field8(uint8_t data, int len, bool be)
+    header_buffer::add_field8(uint8_t data, int len, bool bs)
     {
       int nbytes = len/8;
       if(d_buffer) {
@@ -68,12 +77,12 @@ namespace gr {
     }
 
     void
-    header_buffer::add_field16(uint16_t data, int len, bool be)
+    header_buffer::add_field16(uint16_t data, int len, bool bs)
     {
       int nbytes = len/8;
       if(d_buffer) {
         uint16_t x = data;
-        if(!be) {
+        if(!bs) {
           volk_16u_byteswap(&x, 1);
           x = x >> (16-len);
         }
@@ -83,12 +92,12 @@ namespace gr {
     }
 
     void
-    header_buffer::add_field32(uint32_t data, int len, bool be)
+    header_buffer::add_field32(uint32_t data, int len, bool bs)
     {
       int nbytes = len/8;
       if(d_buffer) {
         uint32_t x = data;
-        if(!be) {
+        if(!bs) {
           volk_32u_byteswap(&x, 1);
           x = x >> (32-len);
         }
@@ -98,12 +107,12 @@ namespace gr {
     }
 
     void
-    header_buffer::add_field64(uint64_t data, int len, bool be)
+    header_buffer::add_field64(uint64_t data, int len, bool bs)
     {
       int nbytes = len/8;
       if(d_buffer) {
         uint64_t x = data;
-        if(!be) {
+        if(!bs) {
           volk_64u_byteswap(&x, 1);
           x = x >> (64-len);
         }
@@ -118,14 +127,8 @@ namespace gr {
       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)
+    header_buffer::extract_field8(int pos, int len, bool bs)
     {
       if(len > 8) {
         throw std::runtime_error("header_buffer::extract_field for "
@@ -142,7 +145,7 @@ namespace gr {
     }
 
     uint16_t
-    header_buffer::extract_field16(int pos, int len, bool be)
+    header_buffer::extract_field16(int pos, int len, bool bs)
     {
       if(len > 16) {
         throw std::runtime_error("header_buffer::extract_field for "
@@ -155,7 +158,7 @@ namespace gr {
         field = (field << 1) | ((*itr) & 0x1);
       }
 
-      if(be) {
+      if(bs) {
         volk_16u_byteswap(&field, 1);
       }
 
@@ -163,7 +166,7 @@ namespace gr {
     }
 
     uint32_t
-    header_buffer::extract_field32(int pos, int len, bool be)
+    header_buffer::extract_field32(int pos, int len, bool bs)
     {
       if(len > 32) {
         throw std::runtime_error("header_buffer::extract_field for "
@@ -176,7 +179,7 @@ namespace gr {
         field = (field << 1) | ((*itr) & 0x1);
       }
 
-      if(be) {
+      if(bs) {
         volk_32u_byteswap(&field, 1);
       }
 
@@ -184,7 +187,7 @@ namespace gr {
     }
 
     uint64_t
-    header_buffer::extract_field64(int pos, int len, bool be)
+    header_buffer::extract_field64(int pos, int len, bool bs)
     {
       if(len > 64) {
         throw std::runtime_error("header_buffer::extract_field for "
@@ -197,7 +200,7 @@ namespace gr {
         field = (field << 1) | ((*itr) & 0x1);
       }
 
-      if(be) {
+      if(bs) {
         volk_64u_byteswap(&field, 1);
       }
 
diff --git a/gr-digital/lib/header_format_crc.cc 
b/gr-digital/lib/header_format_crc.cc
index 73d95df..7594449 100644
--- a/gr-digital/lib/header_format_crc.cc
+++ b/gr-digital/lib/header_format_crc.cc
@@ -104,11 +104,11 @@ namespace gr {
             int payload_len = header_payload();
             enter_have_header(payload_len);
             info.push_back(d_info);
-            d_hdr_reg.clear_input();
+            d_hdr_reg.clear();
             return true;
           }
           else {
-            d_hdr_reg.clear_input();
+            d_hdr_reg.clear();
             return false;
           }
           break;
diff --git a/gr-digital/lib/header_format_default.cc 
b/gr-digital/lib/header_format_default.cc
index 2ddc729..1b7a60e 100644
--- a/gr-digital/lib/header_format_default.cc
+++ b/gr-digital/lib/header_format_default.cc
@@ -187,7 +187,7 @@ namespace gr {
     header_format_default::enter_have_sync()
     {
       d_state = STATE_HAVE_SYNC;
-      d_hdr_reg.clear_input();
+      d_hdr_reg.clear();
     }
 
     inline void
diff --git a/gr-digital/lib/header_format_ofdm.cc 
b/gr-digital/lib/header_format_ofdm.cc
index adc217d..acaf53b 100644
--- a/gr-digital/lib/header_format_ofdm.cc
+++ b/gr-digital/lib/header_format_ofdm.cc
@@ -122,11 +122,11 @@ namespace gr {
             int payload_len = header_payload();
             enter_have_header(payload_len);
             info.push_back(d_info);
-            d_hdr_reg.clear_input();
+            d_hdr_reg.clear();
             return true;
           }
           else {
-            d_hdr_reg.clear_input();
+            d_hdr_reg.clear();
             return false;
           }
           break;
diff --git a/gr-digital/lib/qa_digital.cc b/gr-digital/lib/qa_digital.cc
index 07e19f4..2888d21 100644
--- a/gr-digital/lib/qa_digital.cc
+++ b/gr-digital/lib/qa_digital.cc
@@ -27,6 +27,7 @@
 
 #include "qa_digital.h"
 #include "qa_header_format.h"
+#include "qa_header_buffer.h"
 
 CppUnit::TestSuite *
 qa_digital::suite()
@@ -34,6 +35,7 @@ qa_digital::suite()
   CppUnit::TestSuite *s = new CppUnit::TestSuite("gr-digital");
 
   s->addTest(qa_header_format::suite());
+  s->addTest(qa_header_buffer::suite());
 
   return s;
 }
diff --git a/gr-digital/lib/qa_header_buffer.cc 
b/gr-digital/lib/qa_header_buffer.cc
new file mode 100644
index 0000000..321e901
--- /dev/null
+++ b/gr-digital/lib/qa_header_buffer.cc
@@ -0,0 +1,364 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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/attributes.h>
+
+#include <stdio.h>
+#include <cppunit/TestAssert.h>
+
+#include "qa_header_buffer.h"
+#include <gnuradio/digital/header_buffer.h>
+
+void
+qa_header_buffer::test_add8()
+{
+  size_t len = sizeof(uint8_t);
+  uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+  gr::digital::header_buffer header(buf);
+  header.add_field8(0xAF);
+
+  CPPUNIT_ASSERT_EQUAL(len, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+
+  header.clear();
+  CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+  volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add16()
+{
+  size_t len = sizeof(uint16_t);
+  uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+  uint16_t data = 0xAF5C;
+
+  gr::digital::header_buffer header(buf);
+  header.add_field16(data);
+
+  // Test standard add of a uint16
+  CPPUNIT_ASSERT_EQUAL(len, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[1]);
+
+  // Clear; test to make sure it's clear
+  header.clear();
+  CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+  // Test adding some subset of bits (must be a byte boundary)
+  header.add_field16(data, 8);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[0]);
+  header.clear();
+
+  // Test adding and byte swapping
+  header.add_field16(data, 16, true);
+  CPPUNIT_ASSERT_EQUAL((size_t)2, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[1]);
+  header.clear();
+
+  // Test adding some subset of bits and byte swapping
+  header.add_field16(data, 8, true);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[0]);
+  header.clear();
+
+  volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add32()
+{
+  size_t len = sizeof(uint32_t);
+  uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+  uint32_t data = 0xAF5C7654;
+
+  gr::digital::header_buffer header(buf);
+  header.add_field32(data);
+
+  // Test standard add of a uint32
+  CPPUNIT_ASSERT_EQUAL(len, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[2]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[3]);
+
+  // Clear; test to make sure it's clear
+  header.clear();
+  CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+  // Test adding some subset of bits (must be a byte boundary)
+  header.add_field32(data, 8);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[0]);
+  header.clear();
+
+  // Test adding and byte swapping
+  header.add_field32(data, 32, true);
+  CPPUNIT_ASSERT_EQUAL((size_t)4, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[2]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[3]);
+  header.clear();
+
+  // Test adding some subset of bits and byte swapping
+  header.add_field32(data, 24, true);
+  CPPUNIT_ASSERT_EQUAL((size_t)3, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[2]);
+  header.clear();
+
+  volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add64()
+{
+  size_t len = sizeof(uint64_t);
+  uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+  uint64_t data = 0xAF5C765432104567;
+
+  gr::digital::header_buffer header(buf);
+  header.add_field64(data);
+
+  // Test standard add of a uint64
+  CPPUNIT_ASSERT_EQUAL(len, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[2]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[3]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[4]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[5]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[6]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[7]);
+
+  // Clear; test to make sure it's clear
+  header.clear();
+  CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+  // Test adding some subset of bits (must be a byte boundary)
+  header.add_field64(data, 48);
+  CPPUNIT_ASSERT_EQUAL((size_t)6, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[2]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[3]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[4]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[5]);
+  header.clear();
+
+  // Test adding and byte swapping
+  header.add_field64(data, 64, true);
+  CPPUNIT_ASSERT_EQUAL((size_t)8, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[2]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[3]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[4]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[5]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[6]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[7]);
+  header.clear();
+
+  // Test adding some subset of bits and byte swapping
+  header.add_field64(data, 40, true);
+  CPPUNIT_ASSERT_EQUAL((size_t)5, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[2]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[3]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[4]);
+  header.clear();
+
+  volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add_many()
+{
+  size_t len = (32+64+8+16+32)/8;
+  uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+  gr::digital::header_buffer header(buf);
+  header.add_field32(0x01234567);
+  header.add_field64(0x89ABCDEFFEDCBA98);
+  header.add_field8(0x76);
+  header.add_field16(0x5432);
+  header.add_field32(0x10012345);
+
+  CPPUNIT_ASSERT_EQUAL(len, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x01, header.header()[0]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x23, header.header()[1]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[2]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[3]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x89, header.header()[4]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xAB, header.header()[5]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xCD, header.header()[6]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xEF, header.header()[7]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xFE, header.header()[8]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xDC, header.header()[9]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0xBA, header.header()[10]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x98, header.header()[11]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[12]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[13]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[14]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[15]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x01, header.header()[16]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x23, header.header()[17]);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[18]);
+}
+
+void
+qa_header_buffer::test_extract8()
+{
+  gr::digital::header_buffer header;
+
+  uint64_t data = 0x0123456701234567;
+
+  // Packed format: 0x80C4A2E680C4A2E6
+
+  volk_64u_byteswap(&data, 1);
+  for(int i = 0; i < 64; i++) {
+    header.insert_bit((data >> i) & 0x01);
+  }
+
+  uint8_t x0 = header.extract_field8(0);
+  uint8_t x1 = header.extract_field8(12, 8);
+  uint8_t x2 = header.extract_field8(12, 4);
+
+  CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x80, x0);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x4A, x1);
+  CPPUNIT_ASSERT_EQUAL((uint8_t)0x04, x2);
+}
+
+void
+qa_header_buffer::test_extract16()
+{
+  gr::digital::header_buffer header;
+
+  uint64_t data = 0x0123456701234567;
+
+  // Packed format: 0x80C4A2E680C4A2E6
+
+  volk_64u_byteswap(&data, 1);
+  for(int i = 0; i < 64; i++) {
+    header.insert_bit((data >> i) & 0x01);
+  }
+
+  uint16_t x0 = header.extract_field16(0);
+  uint16_t x1 = header.extract_field16(12, 16);
+  uint16_t x2 = header.extract_field16(12, 12);
+
+  CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint16_t)0x80C4, x0);
+  CPPUNIT_ASSERT_EQUAL((uint16_t)0x4A2E, x1);
+  CPPUNIT_ASSERT_EQUAL((uint16_t)0x04A2, x2);
+}
+
+void
+qa_header_buffer::test_extract32()
+{
+  gr::digital::header_buffer header;
+
+  uint64_t data = 0x0123456701234567;
+
+  // Packed format: 0x80C4A2E680C4A2E6
+
+  volk_64u_byteswap(&data, 1);
+  for(int i = 0; i < 64; i++) {
+    header.insert_bit((data >> i) & 0x01);
+  }
+
+  uint32_t x0 = header.extract_field32(0);
+  uint32_t x1 = header.extract_field32(12, 32);
+  uint32_t x2 = header.extract_field32(12, 24);
+
+  CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint32_t)0x80C4A2E6, x0);
+  CPPUNIT_ASSERT_EQUAL((uint32_t)0x4A2E680C, x1);
+  CPPUNIT_ASSERT_EQUAL((uint32_t)0x004A2E68, x2);
+}
+
+void
+qa_header_buffer::test_extract64()
+{
+  gr::digital::header_buffer header;
+
+  uint64_t data = 0x0123456701234567;
+
+  // Packed format: 0x80C4A2E680C4A2E6
+
+  volk_64u_byteswap(&data, 1);
+  for(int i = 0; i < 64; i++) {
+    header.insert_bit((data >> i) & 0x01);
+  }
+
+  uint64_t x0 = header.extract_field64(0);
+  uint64_t x1 = header.extract_field64(0, 32);
+  uint64_t x2 = header.extract_field64(0, 44);
+
+  CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint64_t)0x80C4A2E680C4A2E6, x0);
+  CPPUNIT_ASSERT_EQUAL((uint64_t)0x0000000080C4A2E6, x1);
+  CPPUNIT_ASSERT_EQUAL((uint64_t)0x0000080C4A2E680C, x2);
+}
+
+void
+qa_header_buffer::test_extract_many()
+{
+  gr::digital::header_buffer header;
+
+  uint64_t data = 0x0123456701234567;
+
+  // Packed format: 0x80C4A2E680C4A2E6
+
+  volk_64u_byteswap(&data, 1);
+  for(int i = 0; i < 64; i++) {
+    header.insert_bit((data >> i) & 0x01);
+  }
+
+  uint64_t x0 = header.extract_field64(0);
+  uint16_t x1 = header.extract_field16(28, 12);
+  uint32_t x2 = header.extract_field32(40, 21);
+  uint16_t x3 = header.extract_field16(1, 12);
+  uint8_t  x4 = header.extract_field8 (7, 5);
+
+  CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+  CPPUNIT_ASSERT_EQUAL((uint64_t)0x80C4A2E680C4A2E6, x0);
+  CPPUNIT_ASSERT_EQUAL((uint16_t)0x0680, x1);
+  CPPUNIT_ASSERT_EQUAL((uint32_t)0x0018945C, x2);
+  CPPUNIT_ASSERT_EQUAL((uint16_t)0x0018, x3);
+  CPPUNIT_ASSERT_EQUAL((uint8_t) 0x0C, x4);
+}
diff --git a/gr-digital/lib/qa_header_buffer.h 
b/gr-digital/lib/qa_header_buffer.h
new file mode 100644
index 0000000..48ab086
--- /dev/null
+++ b/gr-digital/lib/qa_header_buffer.h
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_HEADER_BUFFER_H_
+#define _QA_DIGITAL_HEADER_BUFFER_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_header_buffer : public CppUnit::TestCase
+{
+  CPPUNIT_TEST_SUITE(qa_header_buffer);
+  CPPUNIT_TEST(test_add8);
+  CPPUNIT_TEST(test_add16);
+  CPPUNIT_TEST(test_add32);
+  CPPUNIT_TEST(test_add64);
+  CPPUNIT_TEST(test_add_many);
+
+  CPPUNIT_TEST(test_extract8);
+  CPPUNIT_TEST(test_extract16);
+  CPPUNIT_TEST(test_extract32);
+  CPPUNIT_TEST(test_extract64);
+  CPPUNIT_TEST(test_extract_many);
+  CPPUNIT_TEST_SUITE_END();
+
+ private:
+  void test_add8();
+  void test_add16();
+  void test_add32();
+  void test_add64();
+  void test_add_many();
+
+  void test_extract8();
+  void test_extract16();
+  void test_extract32();
+  void test_extract64();
+  void test_extract_many();
+};
+
+#endif /* _QA_DIGITAL_HEADER_BUFFER_H_ */



reply via email to

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