From fbbde8d01ab43b7a3ffd5ca9d65cf50a84e2a7be Mon Sep 17 00:00:00 2001
From: Tom Rondeau <tom@trondeau.com>
Date: Mon, 19 May 2014 15:53:10 -0400
Subject: fec: wip: async encoder/decoder working deployments.

Decoder uses API signatures to do shifting, data conversions. New examples showing use.
---
 gr-fec/lib/async_decoder_impl.cc | 172 ++++++++++++++++++++++++++++++++-------
 1 file changed, 142 insertions(+), 30 deletions(-)

(limited to 'gr-fec/lib/async_decoder_impl.cc')

diff --git a/gr-fec/lib/async_decoder_impl.cc b/gr-fec/lib/async_decoder_impl.cc
index d3cfd2c05f..8e9747609c 100644
--- a/gr-fec/lib/async_decoder_impl.cc
+++ b/gr-fec/lib/async_decoder_impl.cc
@@ -26,76 +26,188 @@
 
 #include "async_decoder_impl.h"
 #include <gnuradio/io_signature.h>
+#include <volk/volk.h>
 #include <stdio.h>
 
-
 namespace gr {
   namespace fec {
 
     async_decoder::sptr
     async_decoder::make(generic_decoder::sptr my_decoder,
-                        size_t input_item_size, size_t output_item_size)
+                        bool packed, bool rev_pack)
     {
       return gnuradio::get_initial_sptr
-        (new async_decoder_impl(my_decoder, input_item_size, output_item_size));
+        (new async_decoder_impl(my_decoder, packed, rev_pack));
     }
 
     async_decoder_impl::async_decoder_impl(generic_decoder::sptr my_decoder,
-                                           size_t input_item_size,
-                                           size_t output_item_size)
+                                           bool packed, bool rev_pack)
       : block("async_decoder",
               io_signature::make(0,0,0),
               io_signature::make(0,0,0)),
-        d_input_item_size(input_item_size), d_output_item_size(output_item_size)
+        d_input_item_size(sizeof(float)), d_output_item_size(sizeof(char))
     {
+      d_in_port = pmt::mp("in");
+      d_out_port = pmt::mp("out");
+
       d_decoder = my_decoder;
-      message_port_register_in(pmt::mp("in"));
-      message_port_register_out(pmt::mp("out"));
-      set_msg_handler(pmt::mp("pdus"), boost::bind(&async_decoder_impl::decode, this ,_1));
+
+      if(d_decoder->get_history() > 0) {
+        throw std::runtime_error("async_decoder deploment does not support decoders with history requirements.");
+      }
+
+      d_packed = packed;
+      d_rev_pack = rev_pack;
+
+      message_port_register_in(d_in_port);
+      message_port_register_out(d_out_port);
+
+      if(d_packed) {
+        d_pack = new blocks::kernel::pack_k_bits(8);
+        set_msg_handler(d_in_port, boost::bind(&async_decoder_impl::decode_packed, this ,_1));
+      }
+      else {
+        set_msg_handler(d_in_port, boost::bind(&async_decoder_impl::decode_unpacked, this ,_1));
+      }
+
+      // The maximum frame size is set by the initial frame size of the decoder.
+      d_max_bits_in = d_decoder->get_input_size();
+      d_tmp_f32 = (float*)volk_malloc(d_max_bits_in*sizeof(float),
+                                      volk_get_alignment());
+
+      if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) {
+        d_tmp_u8 = (int8_t*)volk_malloc(d_max_bits_in*sizeof(uint8_t),
+                                        volk_get_alignment());
+      }
+
+      if(d_packed) {
+        int max_bits_out = d_decoder->get_output_size();
+        d_bits_out = (uint8_t*)volk_malloc(max_bits_out*sizeof(uint8_t),
+                                           volk_get_alignment());
+      }
     }
 
     async_decoder_impl::~async_decoder_impl()
     {
+      if(d_packed) {
+        delete d_pack;
+        delete d_bits_out;
+      }
+
+      volk_free(d_tmp_f32);
+
+      if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) {
+        volk_free(d_tmp_u8);
+      }
     }
 
     void
-    async_decoder_impl::decode(pmt::pmt_t msg)
+    async_decoder_impl::decode_unpacked(pmt::pmt_t msg)
     {
       // extract input pdu
       pmt::pmt_t meta(pmt::car(msg));
       pmt::pmt_t bits(pmt::cdr(msg));
 
-      int nbits = pmt::length(bits);
-      int blksize_in = d_decoder->get_input_size();
-      int blksize_out = d_decoder->get_output_size();
-      int nblocks = nbits/blksize_in;
+      // Watch out for this diff. It might be over-specializing to the
+      // CC decoder in terminated mode that has an extra rate(K-1)
+      // bits added on to the transmitted frame.
+      int diff = d_decoder->rate()*d_decoder->get_input_size() - d_decoder->get_output_size();
 
-      // nbits sanity check
-      if(nbits % blksize_in != 0){
-        throw std::runtime_error((boost::format("nbits_in %% blksize_in != 0 in fec_decoder_asyn! %d bits in, %d blksize") \
-                                  % nbits % blksize_in).str());
-      }
+      int nbits_in = pmt::length(bits);
+      int nbits_out = nbits_in*d_decoder->rate() - diff;
 
-      printf("decoder :: blksize_in = %d, blksize_out = %d\n", blksize_in, blksize_out);
+      // Check here if the frame size is larger than what we've
+      // allocated for in the constructor.
+      if(nbits_in > d_max_bits_in) {
+        throw std::runtime_error("async_decoder: Received frame larger than max frame size.");
+      }
 
-      pmt::pmt_t outvec(pmt::make_u8vector(blksize_out * nblocks, 0xFF));
-      printf("decoder :: outvec len = %d (%d blks)\n", blksize_out * nblocks, nblocks);
+      d_decoder->set_frame_size(nbits_out);
 
-      // get pmt buffer pointers
       size_t o0(0);
       const float* f32in = pmt::f32vector_elements(bits, o0);
+      pmt::pmt_t outvec(pmt::make_u8vector(nbits_out, 0x00));
       uint8_t* u8out = pmt::u8vector_writable_elements(outvec, o0);
 
-      // loop over n fec blocks
-      for(int i = 0; i < nblocks; i++) {
-        size_t offset_in = i * blksize_in;
-        size_t offset_out = i * blksize_out;
+      if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) {
+        volk_32f_s32f_multiply_32f(d_tmp_f32, f32in, 48.0f, nbits_in);
+      }
+      else {
+        memcpy(d_tmp_f32, f32in, nbits_in*sizeof(float));
+      }
+
+      if(d_decoder->get_shift() != 0) {
+        for(int n = 0; n < nbits_in; n++)
+          d_tmp_f32[n] += d_decoder->get_shift();
+      }
+
+      if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) {
+        //volk_32f_s32f_convert_8i(d_tmp_u8, d_tmp_f32, 1, nbits_in);
+        for(int n = 0; n < nbits_in; n++)
+          d_tmp_u8[n] = static_cast<uint8_t>(d_tmp_f32[n]);
 
-        // DECODE!
-        d_decoder->generic_work((void*)&f32in[offset_in], (void*)&u8out[offset_out]);
+        d_decoder->generic_work((void*)d_tmp_u8, (void*)u8out);
       }
+      else {
+        d_decoder->generic_work((void*)d_tmp_f32, (void*)u8out);
+      }
+
+      message_port_pub(d_out_port, pmt::cons(meta, outvec));
+    }
+
+    void
+    async_decoder_impl::decode_packed(pmt::pmt_t msg)
+    {
+      // extract input pdu
+      pmt::pmt_t meta(pmt::car(msg));
+      pmt::pmt_t bits(pmt::cdr(msg));
+
+      size_t o0 = 0;
+      int nbits_in = pmt::length(bits);
+      int nbits_out = nbits_in*d_decoder->rate();
+      int nbytes_out = nbits_out/8;
+
+      // Check here if the frame size is larger than what we've
+      // allocated for in the constructor.
+      if(nbits_in > d_max_bits_in) {
+        throw std::runtime_error("async_decoder: Received frame larger than max frame size.");
+      }
+
+      d_decoder->set_frame_size(nbits_out);
+
+      pmt::pmt_t outvec(pmt::make_u8vector(nbytes_out, 0x00));
+      uint8_t* bytes_out = pmt::u8vector_writable_elements(outvec, o0);
+      const float* f32in = pmt::f32vector_elements(bits, o0);
+
+      if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) {
+        volk_32f_s32f_multiply_32f(d_tmp_f32, f32in, 48.0f, nbits_in);
+      }
+      else {
+        memcpy(d_tmp_f32, f32in, nbits_in*sizeof(float));
+      }
+
+      if(d_decoder->get_shift() != 0) {
+        for(int n = 0; n < nbits_in; n++)
+          d_tmp_f32[n] += d_decoder->get_shift();
+      }
+
+      if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) {
+        //volk_32f_s32f_convert_8i(d_tmp_u8, d_tmp_f32, 1.0, nbits_in);
+        for(int n = 0; n < nbits_in; n++)
+          d_tmp_u8[n] = static_cast<uint8_t>(d_tmp_f32[n]);
+
+        d_decoder->generic_work((void*)d_tmp_u8, (void*)d_bits_out);
+      }
+      else {
+        d_decoder->generic_work((void*)d_tmp_f32, (void*)d_bits_out);
+      }
+
+      if(d_rev_pack)
+        d_pack->pack_rev(bytes_out, d_bits_out, nbytes_out);
+      else
+        d_pack->pack(bytes_out, d_bits_out, nbytes_out);
 
-      message_port_pub(pmt::mp("pdus"),  pmt::cons(meta, outvec));
+      message_port_pub(d_out_port,  pmt::cons(meta, outvec));
     }
 
     int
-- 
cgit v1.2.3