From 893af3dc280a5d85be2a5beb266dba9bb538292c Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Tue, 7 Feb 2012 11:59:42 -0800
Subject: uhd: added sc8 conversion tests

---
 host/lib/convert/convert_common.hpp      |  2 +-
 host/lib/convert/convert_with_tables.cpp | 71 +++++++++++++++++++++++++++++-
 host/lib/convert/gen_convert_general.py  |  2 +-
 host/tests/convert_test.cpp              | 74 +++++++++++++++++++++++++++++---
 4 files changed, 139 insertions(+), 10 deletions(-)

(limited to 'host')

diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp
index aab59de4b..55bc2e99d 100644
--- a/host/lib/convert/convert_common.hpp
+++ b/host/lib/convert/convert_common.hpp
@@ -1,5 +1,5 @@
 //
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 Ettus Research LLC
 //
 // This program is free software: you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
diff --git a/host/lib/convert/convert_with_tables.cpp b/host/lib/convert/convert_with_tables.cpp
index 2379739a7..4a3ce29b2 100644
--- a/host/lib/convert/convert_with_tables.cpp
+++ b/host/lib/convert/convert_with_tables.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 Ettus Research LLC
 //
 // This program is free software: you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -26,6 +26,55 @@ static const size_t sc16_table_len = size_t(1 << 16);
 
 typedef boost::uint16_t (*tohost16_type)(boost::uint16_t);
 
+/***********************************************************************
+ * Implementation for sc16 to sc8 lookup table
+ *  - Lookup the real and imaginary parts individually
+ **********************************************************************/
+template <bool swap>
+class convert_sc16_1_to_sc8_item32_1 : public converter{
+public:
+    convert_sc16_1_to_sc8_item32_1(void): _table(sc16_table_len){}
+
+    void set_scalar(const double scalar){
+        for (size_t i = 0; i < sc16_table_len; i++){
+            const boost::int16_t val = boost::uint16_t(i);
+            _table[i] = boost::int8_t(boost::math::iround(val * scalar / 32767.));
+        }
+    }
+
+    void operator()(const input_type &inputs, const output_type &outputs, const size_t nsamps){
+        const sc16_t *input = reinterpret_cast<const sc16_t *>(inputs[0]);
+        item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+        const size_t num_pairs = nsamps/2;
+        for (size_t i = 0, j = 0; i < num_pairs; i++, j+=2){
+            output[i] = this->lookup(input[j], input[j+1]);
+        }
+
+        if (nsamps != num_pairs*2){
+            output[num_pairs] = this->lookup(input[nsamps-1], 0);;
+        }
+    }
+
+    item32_t lookup(const sc16_t &in0, const sc16_t &in1){
+        if (swap){ //hope this compiles out, its a template constant
+            return
+            (item32_t(_table[size_t(in0.real())]) << 16) |
+            (item32_t(_table[size_t(in0.imag())]) << 24) |
+            (item32_t(_table[size_t(in1.real())]) << 0) |
+            (item32_t(_table[size_t(in1.imag())]) << 8) ;
+        }
+        return
+            (item32_t(_table[size_t(in0.real())]) << 8) |
+            (item32_t(_table[size_t(in0.imag())]) << 0) |
+            (item32_t(_table[size_t(in1.real())]) << 24) |
+            (item32_t(_table[size_t(in1.imag())]) << 16) ;
+    }
+
+private:
+    std::vector<boost::uint8_t> _table;
+};
+
 /***********************************************************************
  * Implementation for sc16 lookup table
  *  - Lookup the real and imaginary parts individually
@@ -121,9 +170,13 @@ private:
 #ifdef BOOST_BIG_ENDIAN
 #  define SHIFT_PAIR0 16, 0
 #  define SHIFT_PAIR1 0, 16
+#  define BE_SWAP false
+#  define LE_SWAP true
 #else
 #  define SHIFT_PAIR0 0, 16
 #  define SHIFT_PAIR1 16, 0
+#  define BE_SWAP true
+#  define LE_SWAP false
 #endif
 
 static converter::sptr make_convert_sc16_item32_be_1_to_fc32_1(void){
@@ -166,6 +219,14 @@ static converter::sptr make_convert_sc8_item32_le_1_to_sc16_1(void){
     return converter::sptr(new convert_sc8_item32_1_to_fcxx_1<s16_t, uhd::wtohx, SHIFT_PAIR0>());
 }
 
+static converter::sptr make_convert_sc16_1_to_sc8_item32_be_1(void){
+    return converter::sptr(new convert_sc16_1_to_sc8_item32_1<BE_SWAP>());
+}
+
+static converter::sptr make_convert_sc16_1_to_sc8_item32_le_1(void){
+    return converter::sptr(new convert_sc16_1_to_sc8_item32_1<LE_SWAP>());
+}
+
 UHD_STATIC_BLOCK(register_convert_sc16_item32_1_to_fcxx_1){
     uhd::convert::id_type id;
     id.num_inputs = 1;
@@ -210,4 +271,12 @@ UHD_STATIC_BLOCK(register_convert_sc16_item32_1_to_fcxx_1){
     id.output_format = "sc16";
     id.input_format = "sc8_item32_le";
     uhd::convert::register_converter(id, &make_convert_sc8_item32_le_1_to_sc16_1, PRIORITY_TABLE);
+
+    id.output_format = "sc16";
+    id.input_format = "sc8_item32_be";
+    uhd::convert::register_converter(id, &make_convert_sc16_1_to_sc8_item32_be_1, PRIORITY_TABLE);
+
+    id.output_format = "sc16";
+    id.input_format = "sc8_item32_le";
+    uhd::convert::register_converter(id, &make_convert_sc16_1_to_sc8_item32_le_1, PRIORITY_TABLE);
 }
diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py
index a6ae3f810..24729d0d5 100644
--- a/host/lib/convert/gen_convert_general.py
+++ b/host/lib/convert/gen_convert_general.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright 2011 Ettus Research LLC
+# Copyright 2011-2012 Ettus Research LLC
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp
index 1a5d30080..519b7b711 100644
--- a/host/tests/convert_test.cpp
+++ b/host/tests/convert_test.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright 2011-2011 Ettus Research LLC
+// Copyright 2011-2012 Ettus Research LLC
 //
 // This program is free software: you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -67,13 +67,13 @@ template <typename Range> static void loopback(
  * Test short conversion
  **********************************************************************/
 static void test_convert_types_sc16(
-    size_t nsamps, convert::id_type &id
+    size_t nsamps, convert::id_type &id, const int extra_div = 1
 ){
     //fill the input samples
     std::vector<sc16_t> input(nsamps), output(nsamps);
     BOOST_FOREACH(sc16_t &in, input) in = sc16_t(
-        std::rand()-(RAND_MAX/2),
-        std::rand()-(RAND_MAX/2)
+        short(((std::rand()/double(RAND_MAX/2)) - 1)*32767/extra_div),
+        short(((std::rand()/double(RAND_MAX/2)) - 1)*32767/extra_div)
     );
 
     //run the loopback and test
@@ -116,15 +116,15 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){
  **********************************************************************/
 template <typename data_type>
 static void test_convert_types_for_floats(
-    size_t nsamps, convert::id_type &id
+    size_t nsamps, convert::id_type &id, const double extra_scale = 1.0
 ){
     typedef typename data_type::value_type value_type;
 
     //fill the input samples
     std::vector<data_type> input(nsamps), output(nsamps);
     BOOST_FOREACH(data_type &in, input) in = data_type(
-        (std::rand()/value_type(RAND_MAX/2)) - 1,
-        (std::rand()/value_type(RAND_MAX/2)) - 1
+        ((std::rand()/value_type(RAND_MAX/2)) - 1)*extra_scale,
+        ((std::rand()/value_type(RAND_MAX/2)) - 1)*extra_scale
     );
 
     //run the loopback and test
@@ -280,3 +280,63 @@ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){
         MY_CHECK_CLOSE(input[i].imag()/float(32767), output[i].imag(), float(0.01));
     }
 }
+
+/***********************************************************************
+ * Test sc8 conversions
+ **********************************************************************/
+BOOST_AUTO_TEST_CASE(test_convert_types_fc64_and_sc8){
+    convert::id_type id;
+    id.input_format = "fc64";
+    id.num_inputs = 1;
+    id.num_outputs = 1;
+
+    //try various lengths to test edge cases
+    id.output_format = "sc8_item32_le";
+    for (size_t nsamps = 1; nsamps < 16; nsamps++){
+        test_convert_types_for_floats<fc64_t>(nsamps, id, 1./256);
+    }
+
+    //try various lengths to test edge cases
+    id.output_format = "sc8_item32_be";
+    for (size_t nsamps = 1; nsamps < 16; nsamps++){
+        test_convert_types_for_floats<fc64_t>(nsamps, id, 1./256);
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_sc8){
+    convert::id_type id;
+    id.input_format = "fc32";
+    id.num_inputs = 1;
+    id.num_outputs = 1;
+
+    //try various lengths to test edge cases
+    id.output_format = "sc8_item32_le";
+    for (size_t nsamps = 1; nsamps < 16; nsamps++){
+        test_convert_types_for_floats<fc32_t>(nsamps, id, 1./256);
+    }
+
+    //try various lengths to test edge cases
+    id.output_format = "sc8_item32_be";
+    for (size_t nsamps = 1; nsamps < 16; nsamps++){
+        test_convert_types_for_floats<fc32_t>(nsamps, id, 1./256);
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_sc16_and_sc8){
+    convert::id_type id;
+    id.input_format = "sc16";
+    id.num_inputs = 1;
+    id.num_outputs = 1;
+
+    //try various lengths to test edge cases
+    id.output_format = "sc8_item32_le";
+    for (size_t nsamps = 1; nsamps < 16; nsamps++){
+        test_convert_types_sc16(nsamps, id, 256);
+    }
+
+    //try various lengths to test edge cases
+    id.output_format = "sc8_item32_be";
+    for (size_t nsamps = 1; nsamps < 16; nsamps++){
+        test_convert_types_sc16(nsamps, id, 256);
+    }
+}
-- 
cgit v1.2.3