From dd782308940e4b206e798eb2f0fa203b6e8c7f07 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Sat, 12 Nov 2011 15:45:52 -0800
Subject: convert: made conversion functions into classes so they can keep
 state

---
 host/include/uhd/convert.hpp                     | 39 ++++++++++++++++++------
 host/lib/convert/convert_common.hpp              | 26 ++++++++--------
 host/lib/convert/convert_impl.cpp                |  4 +--
 host/lib/convert/gen_convert_general.py          | 10 ------
 host/lib/transport/super_recv_packet_handler.hpp | 13 +++-----
 host/lib/transport/super_send_packet_handler.hpp | 13 +++-----
 host/tests/convert_test.cpp                      | 24 +++++++++++----
 7 files changed, 72 insertions(+), 57 deletions(-)

diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp
index c42edfdec..6cc729819 100644
--- a/host/include/uhd/convert.hpp
+++ b/host/include/uhd/convert.hpp
@@ -20,17 +20,35 @@
 
 #include <uhd/config.hpp>
 #include <uhd/types/ref_vector.hpp>
+#include <boost/shared_ptr.hpp>
 #include <boost/function.hpp>
 #include <boost/operators.hpp>
 #include <string>
 
 namespace uhd{ namespace convert{
 
-    typedef uhd::ref_vector<void *> output_type;
-    typedef uhd::ref_vector<const void *> input_type;
+    //! A conversion class that implements a conversion from inputs -> outputs.
+    class converter{
+    public:
+        typedef boost::shared_ptr<converter> sptr;
+        typedef uhd::ref_vector<void *> output_type;
+        typedef uhd::ref_vector<const void *> input_type;
 
-    //! input vectors, output vectors, num samples, scale factor
-    typedef boost::function<void(const input_type&, const output_type&, const size_t, const double)> function_type;
+        //! Set the scale factor (used in floating point conversions)
+        virtual void set_scalar(const double) = 0;
+
+        //! The public conversion method to convert inputs -> outputs
+        UHD_INLINE void conv(const input_type &in, const output_type &out, const size_t num){
+            if (num != 0) (*this)(in, out, num);
+        }
+
+    private:
+        //! Callable method: input vectors, output vectors, num samples
+        virtual void operator()(const input_type&, const output_type&, const size_t) = 0;
+    };
+
+    //! Conversion factory function typedef
+    typedef boost::function<converter::sptr(void)> function_type;
 
     /*!
      * Describe the priority of a converter function.
@@ -43,7 +61,8 @@ namespace uhd{ namespace convert{
         PRIORITY_GENERAL = 0,
         PRIORITY_LIBORC = 1,
         PRIORITY_SIMD = 2,
-        PRIORITY_CUSTOM = 3,
+        PRIORITY_TABLE = 3,
+        PRIORITY_CUSTOM = 4,
         PRIORITY_EMPTY = -1,
     };
 
@@ -62,19 +81,19 @@ namespace uhd{ namespace convert{
     /*!
      * Register a converter function.
      * \param id identify the conversion
-     * \param fcn a pointer to the converter
+     * \param fcn makes a new converter
      * \param prio the function priority
      */
     UHD_API void register_converter(
         const id_type &id,
-        function_type fcn,
-        priority_type prio
+        const function_type &fcn,
+        const priority_type prio
     );
 
     /*!
-     * Get a converter function.
+     * Get a converter factory function.
      * \param id identify the conversion
-     * \return the converter function
+     * \return the converter factory function
      */
     UHD_API function_type get_converter(const id_type &id);
 
diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp
index 34fb848c3..ce82f6216 100644
--- a/host/lib/convert/convert_common.hpp
+++ b/host/lib/convert/convert_common.hpp
@@ -21,30 +21,30 @@
 #include <uhd/convert.hpp>
 #include <uhd/utils/static.hpp>
 #include <boost/cstdint.hpp>
+#include <boost/bind.hpp>
 #include <complex>
 
-#define _DECLARE_CONVERTER(fcn, in_form, num_in, out_form, num_out, prio) \
-    static void fcn( \
-        const uhd::convert::input_type &inputs, \
-        const uhd::convert::output_type &outputs, \
-        const size_t nsamps, const double scale_factor \
-    ); \
-    UHD_STATIC_BLOCK(__register_##fcn##_##prio){ \
+#define _DECLARE_CONVERTER(name, in_form, num_in, out_form, num_out, prio) \
+    struct name : public uhd::convert::converter{ \
+        static sptr make(void){return sptr(new name());} \
+        double scale_factor; \
+        void set_scalar(const double s){scale_factor = s;} \
+        void operator()(const input_type&, const output_type&, const size_t); \
+    }; \
+    UHD_STATIC_BLOCK(__register_##name##_##prio){ \
         uhd::convert::id_type id; \
         id.input_format = #in_form; \
         id.num_inputs = num_in; \
         id.output_format = #out_form; \
         id.num_outputs = num_out; \
-        uhd::convert::register_converter(id, fcn, prio); \
+        uhd::convert::register_converter(id, boost::bind(&name::make), prio); \
     } \
-    static void fcn( \
-        const uhd::convert::input_type &inputs, \
-        const uhd::convert::output_type &outputs, \
-        const size_t nsamps, const double scale_factor \
+    void name::operator()( \
+        const input_type &inputs, const output_type &outputs, const size_t nsamps \
     )
 
 #define DECLARE_CONVERTER(in_form, num_in, out_form, num_out, prio) \
-    _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out, in_form, num_in, out_form, num_out, prio)
+    _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out##_##prio, in_form, num_in, out_form, num_out, prio)
 
 /***********************************************************************
  * Typedefs
diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp
index f05be6ada..12ad54486 100644
--- a/host/lib/convert/convert_impl.cpp
+++ b/host/lib/convert/convert_impl.cpp
@@ -69,8 +69,8 @@ UHD_SINGLETON_FCN(fcn_table_type, get_table);
  **********************************************************************/
 void uhd::convert::register_converter(
     const id_type &id,
-    function_type fcn,
-    priority_type prio
+    const function_type &fcn,
+    const priority_type prio
 ){
     //get a reference to the function table
     fcn_table_type &table = get_table();
diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py
index 52b4212b4..a1bc7aaaf 100644
--- a/host/lib/convert/gen_convert_general.py
+++ b/host/lib/convert/gen_convert_general.py
@@ -33,8 +33,6 @@ DECLARE_CONVERTER(item32, 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){
     const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
     item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
 
-    if (scale_factor == 0){} //avoids unused warning
-
     for (size_t i = 0; i < nsamps; i++){
         output[i] = $(to_wire)(input[i]);
     }
@@ -44,8 +42,6 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, item32, 1, PRIORITY_GENERAL){
     const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
     item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
 
-    if (scale_factor == 0){} //avoids unused warning
-
     for (size_t i = 0; i < nsamps; i++){
         output[i] = $(to_host)(input[i]);
     }
@@ -103,8 +99,6 @@ DECLARE_CONVERTER($(cpu_type), $(width), sc16_item16_usrp1, 1, PRIORITY_GENERAL)
     #end for
     boost::uint16_t *output = reinterpret_cast<boost::uint16_t *>(outputs[0]);
 
-    if (scale_factor == 0){} //avoids unused warning
-
     for (size_t i = 0, j = 0; i < nsamps; i++){
         #for $w in range($width)
         output[j++] = $(to_wire)(boost::int16_t(input$(w)[i].real()$(do_scale)));
@@ -119,8 +113,6 @@ DECLARE_CONVERTER(sc16_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL)
     $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]);
     #end for
 
-    if (scale_factor == 0){} //avoids unused warning
-
     for (size_t i = 0, j = 0; i < nsamps; i++){
         #for $w in range($width)
         output$(w)[i] = $(cpu_type)_t(
@@ -138,8 +130,6 @@ DECLARE_CONVERTER(sc8_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){
     $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]);
     #end for
 
-    if (scale_factor == 0){} //avoids unused warning
-
     for (size_t i = 0, j = 0; i < nsamps; i++){
         #for $w in range($width)
         {
diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp
index 57aae96b1..05cad93ea 100644
--- a/host/lib/transport/super_recv_packet_handler.hpp
+++ b/host/lib/transport/super_recv_packet_handler.hpp
@@ -71,7 +71,6 @@ public:
     {
         this->resize(size);
         set_alignment_failure_threshold(1000);
-        this->set_scale_factor(1/32767.);
     }
 
     //! Resize the number of transport channels
@@ -124,7 +123,8 @@ public:
     //! Set the conversion routine for all channels
     void set_converter(const uhd::convert::id_type &id){
         _io_buffs.resize(id.num_outputs);
-        _converter = uhd::convert::get_converter(id);
+        _converter = uhd::convert::get_converter(id)();
+        this->set_scale_factor(1/32767.); //update after setting converter
         _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_format);
         _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_format);
     }
@@ -136,7 +136,7 @@ public:
 
     //! Set the scale factor used in float conversion
     void set_scale_factor(const double scale_factor){
-        _scale_factor = scale_factor;
+        _converter->set_scalar(scale_factor);
     }
 
     /*******************************************************************
@@ -207,8 +207,7 @@ private:
     std::vector<void *> _io_buffs; //used in conversion
     size_t _bytes_per_otw_item; //used in conversion
     size_t _bytes_per_cpu_item; //used in conversion
-    uhd::convert::function_type _converter; //used in conversion
-    double _scale_factor;
+    uhd::convert::converter::sptr _converter; //used in conversion
 
     //! information stored for a received buffer
     struct per_buffer_info_type{
@@ -523,9 +522,7 @@ private:
             }
 
             //copy-convert the samples from the recv buffer
-            if (nsamps_to_copy_per_io_buff != 0) _converter(
-                buff_info.copy_buff, _io_buffs, nsamps_to_copy_per_io_buff, _scale_factor
-            );
+            _converter->conv(buff_info.copy_buff, _io_buffs, nsamps_to_copy_per_io_buff);
 
             //update the rx copy buffer to reflect the bytes copied
             buff_info.copy_buff += bytes_to_copy;
diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp
index c3ffcc861..5ed8e0143 100644
--- a/host/lib/transport/super_send_packet_handler.hpp
+++ b/host/lib/transport/super_send_packet_handler.hpp
@@ -56,7 +56,6 @@ public:
         _next_packet_seq(0)
     {
         this->resize(size);
-        this->set_scale_factor(32767.);
     }
 
     //! Resize the number of transport channels
@@ -100,7 +99,8 @@ public:
     //! Set the conversion routine for all channels
     void set_converter(const uhd::convert::id_type &id){
         _io_buffs.resize(id.num_inputs);
-        _converter = uhd::convert::get_converter(id);
+        _converter = uhd::convert::get_converter(id)();
+        this->set_scale_factor(32767.); //update after setting converter
         _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_format);
         _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_format);
     }
@@ -116,7 +116,7 @@ public:
 
     //! Set the scale factor used in float conversion
     void set_scale_factor(const double scale_factor){
-        _scale_factor = scale_factor;
+        _converter->set_scalar(scale_factor);
     }
 
     /*******************************************************************
@@ -202,11 +202,10 @@ private:
     std::vector<const void *> _io_buffs; //used in conversion
     size_t _bytes_per_otw_item; //used in conversion
     size_t _bytes_per_cpu_item; //used in conversion
-    uhd::convert::function_type _converter; //used in conversion
+    uhd::convert::converter::sptr _converter; //used in conversion
     size_t _max_samples_per_packet;
     std::vector<const void *> _zero_buffs;
     size_t _next_packet_seq;
-    double _scale_factor;
 
     /*******************************************************************
      * Send a single packet:
@@ -239,9 +238,7 @@ private:
             otw_mem += if_packet_info.num_header_words32;
 
             //copy-convert the samples into the send buffer
-            if (nsamps_per_buff != 0) _converter(
-                _io_buffs, otw_mem, nsamps_per_buff, _scale_factor
-            );
+            _converter->conv(_io_buffs, otw_mem, nsamps_per_buff);
 
             //commit the samples to the zero-copy interface
             size_t num_bytes_total = (_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t);
diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp
index b63ff6752..1a5d30080 100644
--- a/host/tests/convert_test.cpp
+++ b/host/tests/convert_test.cpp
@@ -53,10 +53,14 @@ template <typename Range> static void loopback(
     std::vector<void *> output0(1, &interm[0]), output1(1, &output[0]);
 
     //convert to intermediate type
-    convert::get_converter(in_id)(input0, output0, nsamps, 32767.);
+    convert::converter::sptr c0 = convert::get_converter(in_id)();
+    c0->set_scalar(32767.);
+    c0->conv(input0, output0, nsamps);
 
     //convert back to host type
-    convert::get_converter(out_id)(input1, output1, nsamps, 1/32767.);
+    convert::converter::sptr c1 = convert::get_converter(out_id)();
+    c1->set_scalar(1/32767.);
+    c1->conv(input1, output1, nsamps);
 }
 
 /***********************************************************************
@@ -216,10 +220,14 @@ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){
     std::vector<void *> output0(1, &interm[0]), output1(1, &output[0]);
 
     //convert float to intermediate
-    convert::get_converter(in_id)(input0, output0, nsamps, 32767.);
+    convert::converter::sptr c0 = convert::get_converter(in_id)();
+    c0->set_scalar(32767.);
+    c0->conv(input0, output0, nsamps);
 
     //convert intermediate to short
-    convert::get_converter(out_id)(input1, output1, nsamps, 1/32767.);
+    convert::converter::sptr c1 = convert::get_converter(out_id)();
+    c1->set_scalar(1/32767.);
+    c1->conv(input1, output1, nsamps);
 
     //test that the inputs and outputs match
     for (size_t i = 0; i < nsamps; i++){
@@ -257,10 +265,14 @@ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){
     std::vector<void *> output0(1, &interm[0]), output1(1, &output[0]);
 
     //convert short to intermediate
-    convert::get_converter(in_id)(input0, output0, nsamps, 32767.);
+    convert::converter::sptr c0 = convert::get_converter(in_id)();
+    c0->set_scalar(32767.);
+    c0->conv(input0, output0, nsamps);
 
     //convert intermediate to float
-    convert::get_converter(out_id)(input1, output1, nsamps, 1/32767.);
+    convert::converter::sptr c1 = convert::get_converter(out_id)();
+    c1->set_scalar(1/32767.);
+    c1->conv(input1, output1, nsamps);
 
     //test that the inputs and outputs match
     for (size_t i = 0; i < nsamps; i++){
-- 
cgit v1.2.3