diff options
-rw-r--r-- | host/lib/convert/convert_common.hpp | 2 | ||||
-rw-r--r-- | host/lib/convert/convert_with_tables.cpp | 71 | ||||
-rw-r--r-- | host/lib/convert/gen_convert_general.py | 2 | ||||
-rw-r--r-- | host/tests/convert_test.cpp | 74 |
4 files changed, 139 insertions, 10 deletions
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 @@ -27,6 +27,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); + } +} |