From d195fb943fa7677959d8df9abc1b66c3fae7982d Mon Sep 17 00:00:00 2001
From: Martin Braun <martin.braun@kit.edu>
Date: Sun, 7 Apr 2013 22:23:56 +0200
Subject: digital: OFDM frame equalizer now as an option to work w/o len tag

---
 gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'gr-digital/include/digital')

diff --git a/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h b/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h
index 21a976071d..23f3041e27 100644
--- a/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h
+++ b/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h
@@ -52,7 +52,8 @@ namespace gr {
       static sptr make(
 	   digital_ofdm_equalizer_base_sptr equalizer,
 	   const std::string &len_tag_key = "frame_len",
-	   bool propagate_channel_state=false
+	   bool propagate_channel_state=false,
+	   int fixed_frame_len=0
       );
     };
 
-- 
cgit v1.2.3


From 719c8be76751cb4fb88fa8ca4149bbf1cf1db763 Mon Sep 17 00:00:00 2001
From: Martin Braun <martin.braun@kit.edu>
Date: Sun, 7 Apr 2013 22:22:55 +0200
Subject: digital: fix some issues w/ header parser/gen; QA, wrong OFDM symbol
 number calculation, bug that always returns PMT_NIL

---
 gr-digital/include/digital/packet_header_default.h |  7 +-
 gr-digital/include/digital/packet_header_ofdm.h    | 39 ++++++---
 gr-digital/lib/packet_header_ofdm.cc               | 18 ++--
 gr-digital/lib/packet_headerparser_b_impl.cc       |  2 +-
 gr-digital/python/qa_ofdm_serializer_vcc.py        |  3 +-
 gr-digital/python/qa_ofdm_sync_sc_cfb.py           |  3 +-
 gr-digital/python/qa_packet_headergenerator_bb.py  |  8 +-
 gr-digital/python/qa_packet_headerparser_b.py      | 96 ++++++++++++++++++----
 8 files changed, 129 insertions(+), 47 deletions(-)

(limited to 'gr-digital/include/digital')

diff --git a/gr-digital/include/digital/packet_header_default.h b/gr-digital/include/digital/packet_header_default.h
index 64804e6d6a..e4c994593f 100644
--- a/gr-digital/include/digital/packet_header_default.h
+++ b/gr-digital/include/digital/packet_header_default.h
@@ -76,7 +76,7 @@ namespace gr {
        * If the header length is smaller than 29, bits are simply left out. For this
        * reason, they always start with the LSB.
        */
-      bool header_formatter(
+      virtual bool header_formatter(
 	  long packet_len,
 	  unsigned char *out,
 	  const std::vector<gr_tag_t> &tags=std::vector<gr_tag_t>()
@@ -85,10 +85,9 @@ namespace gr {
       /*!
        * \brief Inverse function to header_formatter().
        *
-       * Reads the bit stream in and writes a corresponding tag into \p tags.
-       *
+       * Reads the bit stream in \p header and writes a corresponding tag into \p tags.
        */
-      bool header_parser(
+      virtual bool header_parser(
 	const unsigned char *header,
 	std::vector<gr_tag_t> &tags);
 
diff --git a/gr-digital/include/digital/packet_header_ofdm.h b/gr-digital/include/digital/packet_header_ofdm.h
index 9f70900b49..de4f0a5000 100644
--- a/gr-digital/include/digital/packet_header_ofdm.h
+++ b/gr-digital/include/digital/packet_header_ofdm.h
@@ -42,10 +42,11 @@ namespace gr {
       packet_header_ofdm(
 		      const std::vector<std::vector<int> > &occupied_carriers,
 		      int n_syms,
-		      const std::string &len_tag_key="packet_len",
-		      const std::string &frame_len_tag_key="frame_len",
-		      const std::string &num_tag_key="packet_num",
-		      int bits_per_sym=1);
+		      const std::string &len_tag_key,
+		      const std::string &frame_len_tag_key,
+		      const std::string &num_tag_key,
+		      int bits_per_header_sym,
+		      int bits_per_payload_sym);
       ~packet_header_ofdm();
 
       /*!
@@ -62,19 +63,37 @@ namespace gr {
 	const unsigned char *header,
 	std::vector<gr_tag_t> &tags);
 
+      /*!
+       * \param occupied_carriers See carrier allocator
+       * \param n_syms The number of OFDM symbols the header should be (usually 1)
+       * \param len_tag_key The tag key used for the packet length (number of bytes)
+       * \param frame_len_tag_key The tag key used for the frame length (number of
+       *                          OFDM symbols, this is the tag key required for the
+       *                          frame equalizer etc.)
+       * \param bits_per_header_sym Bits per complex symbol in the header, e.g. 1 if
+       *                            the header is BPSK modulated, 2 if it's QPSK
+       *                            modulated etc.
+       * \param bits_per_payload_sym Bits per complex symbol in the payload. This is
+       *                             required to figure out how many OFDM symbols
+       *                             are necessary to encode the given number of
+       *                             bytes.
+       */
       static sptr make(
-		      const std::vector<std::vector<int> > &occupied_carriers,
-		      int n_syms,
-		      const std::string &len_tag_key="packet_len",
-		      const std::string &frame_len_tag_key="frame_len",
-		      const std::string &num_tag_key="packet_num",
-		      int bits_per_sym=1);
+	    const std::vector<std::vector<int> > &occupied_carriers,
+	    int n_syms,
+	    const std::string &len_tag_key="packet_len",
+	    const std::string &frame_len_tag_key="frame_len",
+	    const std::string &num_tag_key="packet_num",
+	    int bits_per_header_sym=1,
+	    int bits_per_payload_sym=1
+      );
 
 
      protected:
       pmt::pmt_t d_frame_len_tag_key;
       const std::vector<std::vector<int> > d_occupied_carriers; //!< Which carriers/symbols carry data
       int d_syms_per_set; //!< Helper variable: Total number of elements in d_occupied_carriers
+      int d_bits_per_payload_sym;
     };
 
   } // namespace digital
diff --git a/gr-digital/lib/packet_header_ofdm.cc b/gr-digital/lib/packet_header_ofdm.cc
index db190c13bb..6d40fcfffa 100644
--- a/gr-digital/lib/packet_header_ofdm.cc
+++ b/gr-digital/lib/packet_header_ofdm.cc
@@ -45,11 +45,12 @@ namespace gr {
 		      const std::string &len_tag_key,
 		      const std::string &frame_len_tag_key,
 		      const std::string &num_tag_key,
-		      int bits_per_sym)
+		      int bits_per_header_sym,
+		      int bits_per_payload_sym)
     {
       return packet_header_ofdm::sptr(
 	  new packet_header_ofdm(
-	    occupied_carriers, n_syms, len_tag_key, frame_len_tag_key, num_tag_key, bits_per_sym
+	    occupied_carriers, n_syms, len_tag_key, frame_len_tag_key, num_tag_key, bits_per_header_sym, bits_per_payload_sym
 	  )
       );
     }
@@ -60,15 +61,17 @@ namespace gr {
 		    const std::string &len_tag_key,
 		    const std::string &frame_len_tag_key,
 		    const std::string &num_tag_key,
-		    int bits_per_sym)
+		    int bits_per_header_sym,
+		    int bits_per_payload_sym)
       : packet_header_default(
 	  _get_header_len_from_occupied_carriers(occupied_carriers, n_syms),
 	  len_tag_key,
 	  num_tag_key,
-	  bits_per_sym),
+	  bits_per_header_sym),
       d_frame_len_tag_key(pmt::pmt_string_to_symbol(frame_len_tag_key)),
       d_occupied_carriers(occupied_carriers),
-      d_syms_per_set(0)
+      d_syms_per_set(0),
+      d_bits_per_payload_sym(bits_per_payload_sym)
     {
       for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
 	d_syms_per_set += d_occupied_carriers[i].size();
@@ -87,14 +90,17 @@ namespace gr {
       if (!packet_header_default::header_parser(in, tags)) {
 	return false;
       }
-      int packet_len = 0; // # of OFDM symbols
+      int packet_len = 0; // # of bytes in this frame
       for (unsigned i = 0; i < tags.size(); i++) {
 	if (pmt::pmt_equal(tags[i].key, d_len_tag_key)) {
 	  packet_len = pmt::pmt_to_long(tags[i].value);
 	  break;
 	}
       }
+      // Convert bytes to complex symbols:
+      packet_len = packet_len * 8 / d_bits_per_payload_sym;
 
+      // frame_len == # of OFDM symbols in this frame
       int frame_len = packet_len / d_syms_per_set;
       int k = 0;
       int i = frame_len * d_syms_per_set;
diff --git a/gr-digital/lib/packet_headerparser_b_impl.cc b/gr-digital/lib/packet_headerparser_b_impl.cc
index 5f8f0cd560..e7e949e387 100644
--- a/gr-digital/lib/packet_headerparser_b_impl.cc
+++ b/gr-digital/lib/packet_headerparser_b_impl.cc
@@ -79,7 +79,7 @@ namespace gr {
       } else {
 	pmt::pmt_t dict(pmt::pmt_make_dict());
 	for (unsigned i = 0; i < tags.size(); i++) {
-	  pmt::pmt_dict_add(dict, tags[i].key, tags[i].value);
+	  dict = pmt::pmt_dict_add(dict, tags[i].key, tags[i].value);
 	}
 	message_port_pub(msg_port_id, dict);
       }
diff --git a/gr-digital/python/qa_ofdm_serializer_vcc.py b/gr-digital/python/qa_ofdm_serializer_vcc.py
index 537e19b593..5914df9a56 100755
--- a/gr-digital/python/qa_ofdm_serializer_vcc.py
+++ b/gr-digital/python/qa_ofdm_serializer_vcc.py
@@ -207,6 +207,5 @@ class qa_ofdm_serializer_vcc (gr_unittest.TestCase):
 
 
 if __name__ == '__main__':
-    #gr_unittest.run(qa_ofdm_serializer_vcc, "qa_ofdm_serializer_vcc.xml")
-    gr_unittest.run(qa_ofdm_serializer_vcc)
+    gr_unittest.run(qa_ofdm_serializer_vcc, "qa_ofdm_serializer_vcc.xml")
 
diff --git a/gr-digital/python/qa_ofdm_sync_sc_cfb.py b/gr-digital/python/qa_ofdm_sync_sc_cfb.py
index bed8e9c3ae..f6ae001ea3 100755
--- a/gr-digital/python/qa_ofdm_sync_sc_cfb.py
+++ b/gr-digital/python/qa_ofdm_sync_sc_cfb.py
@@ -192,6 +192,5 @@ Detection error was: %d """ % (numpy.sum(sink_detect.data()) - n_bursts)
 
 
 if __name__ == '__main__':
-    #gr_unittest.run(qa_ofdm_sync_sc_cfb, "qa_ofdm_sync_sc_cfb.xml")
-    gr_unittest.run(qa_ofdm_sync_sc_cfb)
+    gr_unittest.run(qa_ofdm_sync_sc_cfb, "qa_ofdm_sync_sc_cfb.xml")
 
diff --git a/gr-digital/python/qa_packet_headergenerator_bb.py b/gr-digital/python/qa_packet_headergenerator_bb.py
index 11f6ebfe79..2dbe5604fa 100755
--- a/gr-digital/python/qa_packet_headergenerator_bb.py
+++ b/gr-digital/python/qa_packet_headergenerator_bb.py
@@ -33,8 +33,8 @@ class qa_packet_headergenerator_bb (gr_unittest.TestCase):
         self.tb = None
 
     def test_001_12bits (self):
-        # 3 PDUs: |           |     |         |
-        data   = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4)
+        # 3 PDUs: |           |       |
+        data   = (1, 2, 3, 4, 1, 2) + tuple(range(25))
         tagname = "packet_len"
         tag1 = gr.gr_tag_t()
         tag1.offset = 0
@@ -47,7 +47,7 @@ class qa_packet_headergenerator_bb (gr_unittest.TestCase):
         tag3 = gr.gr_tag_t()
         tag3.offset = 6
         tag3.key = pmt.pmt_string_to_symbol(tagname)
-        tag3.value = pmt.pmt_from_long(4)
+        tag3.value = pmt.pmt_from_long(25)
         src = gr.vector_source_b(data, False, 1, (tag1, tag2, tag3))
         header = digital.packet_headergenerator_bb(12, tagname)
         sink = gr.vector_sink_b()
@@ -56,7 +56,7 @@ class qa_packet_headergenerator_bb (gr_unittest.TestCase):
         expected_data = (
                 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0
         )
         self.assertEqual(sink.data(), expected_data)
 
diff --git a/gr-digital/python/qa_packet_headerparser_b.py b/gr-digital/python/qa_packet_headerparser_b.py
index 13dc46f9e3..fd6fdd2b68 100755
--- a/gr-digital/python/qa_packet_headerparser_b.py
+++ b/gr-digital/python/qa_packet_headerparser_b.py
@@ -20,10 +20,12 @@
 # 
 
 import time
+import random
 from gnuradio import gr, gr_unittest
 try: import pmt
 except: from gruel import pmt
 import digital_swig as digital
+from utils import tagged_streams
 
 class qa_packet_headerparser_b (gr_unittest.TestCase):
 
@@ -34,38 +36,96 @@ class qa_packet_headerparser_b (gr_unittest.TestCase):
         self.tb = None
 
     def test_001_t (self):
-        expected_data = (
-            #   | Number of symbols                  | Packet number                                  | Parity
+        """
+        First header: Packet length 4, packet num 0
+        Second header: Packet 2, packet num 1
+        Third header: Invalid (parity bit does not check) (would be len 4, num 2)
+        """
+        encoded_headers = (
+            #   | Number of bytes                    | Packet number                                  | Parity
                 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0,
                 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,
                 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0
         )
-        tagname = "packet_len"
+        packet_len_tagname = "packet_len"
 
-        src = gr.vector_source_b(expected_data)
-        parser = digital.packet_headerparser_b(32, tagname)
+        src = gr.vector_source_b(encoded_headers)
+        parser = digital.packet_headerparser_b(32, packet_len_tagname)
         sink = gr.message_debug()
-
         self.tb.connect(src, parser)
         self.tb.msg_connect(parser, "header_data", sink, "store")
-        self.tb.start ()
+        self.tb.start()
         time.sleep(1)
         self.tb.stop()
         self.tb.wait()
-
         self.assertEqual(sink.num_messages(), 3)
-        msg = sink.get_message(0)
-        #try:
-        #self.assertEqual(4, pmt.pmt_to_long(pmt.pmt_dict_ref(msg, pmt.pmt_string_to_symbol(tagname), pmt.PMT_F)))
-        #self.assertEqual(0, pmt.pmt_to_long(pmt.pmt_dict_ref(msg, pmt.pmt_string_to_symbol("packet_num"), pmt.PMT_F)))
-
-        #except:
-            #self.fail()
-        # msg1: length 4, number 0
-        # msg2: length 2, number 1
-        # msg3: PMT_F because parity fail
+        msg1 = pmt.to_python(sink.get_message(0))
+        msg2 = pmt.to_python(sink.get_message(1))
+        msg3 = pmt.to_python(sink.get_message(2))
+        self.assertEqual(msg1, {'packet_len': 4, 'packet_num': 0})
+        self.assertEqual(msg2, {'packet_len': 2, 'packet_num': 1})
+        self.assertEqual(msg3, False)
 
+    def test_002_pipe(self):
+        """
+        Create N packets of random length, pipe them through header generator,
+        back to header parser, make sure output is the same.
+        """
+        N = 20
+        header_len = 32
+        packet_len_tagname = "packet_len"
+        packet_lengths = [random.randint(1, 100) for x in range(N)]
+        data, tags = tagged_streams.packets_to_vectors([range(packet_lengths[i]) for i in range(N)], packet_len_tagname)
+        src = gr.vector_source_b(data, False, 1, tags)
+        header_gen = digital.packet_headergenerator_bb(header_len, packet_len_tagname)
+        header_parser = digital.packet_headerparser_b(header_len, packet_len_tagname)
+        sink = gr.message_debug()
+        self.tb.connect(src, header_gen, header_parser)
+        self.tb.msg_connect(header_parser, "header_data", sink, "store")
+        self.tb.start()
+        time.sleep(1)
+        self.tb.stop()
+        self.tb.wait()
+        self.assertEqual(sink.num_messages(), N)
+        for i in xrange(N):
+            msg = pmt.to_python(sink.get_message(i))
+            self.assertEqual(msg, {'packet_len': packet_lengths[i], 'packet_num': i})
 
+    def test_003_ofdm (self):
+        """ Header 1: 193 bytes
+        Header 2: 8 bytes
+        2 bits per complex symbol, 32 carriers => 64 bits = 8 bytes per OFDM symbol
+        """
+        encoded_headers = (
+            #   | Number of bytes                    | Packet number                                  | Parity
+                1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0,
+                0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,
+        )
+        packet_len_tagname = "packet_len"
+        frame_len_tagname = "frame_len"
+        src = gr.vector_source_b(encoded_headers)
+        header_formatter = digital.packet_header_ofdm(
+                (range(32),), # 32 carriers are occupied (which doesn't matter here)
+                1,         # 1 OFDM symbol per header (= 32 bits)
+                packet_len_tagname,
+                frame_len_tagname,
+                "packet_num",
+                1,         # 1 bit per header symbols (BPSK)
+                2          # 2 bits per payload symbol (QPSK)
+        )
+        parser = digital.packet_headerparser_b(header_formatter.base())
+        sink = gr.message_debug()
+        self.tb.connect(src, parser)
+        self.tb.msg_connect(parser, "header_data", sink, "store")
+        self.tb.start()
+        time.sleep(1)
+        self.tb.stop()
+        self.tb.wait()
+        self.assertEqual(sink.num_messages(), 2)
+        msg1 = pmt.to_python(sink.get_message(0))
+        msg2 = pmt.to_python(sink.get_message(1))
+        self.assertEqual(msg1, {'packet_len': 193, 'frame_len': 25, 'packet_num': 0})
+        self.assertEqual(msg2, {'packet_len': 8, 'frame_len': 1, 'packet_num': 1})
 
 if __name__ == '__main__':
     gr_unittest.run(qa_packet_headerparser_b, "qa_packet_headerparser_b.xml")
-- 
cgit v1.2.3