From 72359ea15846ab87c781ab4d072f694e97cc3cd1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 17 Jan 2012 13:42:37 -0800 Subject: uhd: implement convert_sc8to_sc16 table w/ scalar --- host/lib/convert/convert_with_tables.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'host/lib/convert/convert_with_tables.cpp') diff --git a/host/lib/convert/convert_with_tables.cpp b/host/lib/convert/convert_with_tables.cpp index c45415d5d..c033a2959 100644 --- a/host/lib/convert/convert_with_tables.cpp +++ b/host/lib/convert/convert_with_tables.cpp @@ -17,6 +17,7 @@ #include "convert_common.hpp" #include +#include #include using namespace uhd::convert; @@ -68,6 +69,19 @@ public: convert_sc8_item32_1_to_fcxx_1(void): _table(sc16_table_len){} void set_scalar(const double scalar){ + + //special case, this is converts sc8 to sc16, + //use the scale-factor but no normalization + if (sizeof(type) == sizeof(s16_t)){ + for (size_t i = 0; i < sc16_table_len; i++){ + const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff)); + const type real = type(boost::math::iround(boost::int8_t(val >> 8)*scalar*32767)); + const type imag = type(boost::math::iround(boost::int8_t(val >> 0)*scalar*32767)); + _table[i] = std::complex(real, imag); + } + return; + } + for (size_t i = 0; i < sc16_table_len; i++){ const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff)); const type real = type(boost::int8_t(val >> 8)*scalar); @@ -149,6 +163,14 @@ static converter::sptr make_convert_sc8_item32_le_1_to_fc64_1(void){ return converter::sptr(new convert_sc8_item32_1_to_fcxx_1()); } +static converter::sptr make_convert_sc8_item32_be_1_to_sc16_1(void){ + return converter::sptr(new convert_sc8_item32_1_to_fcxx_1()); +} + +static converter::sptr make_convert_sc8_item32_le_1_to_sc16_1(void){ + return converter::sptr(new convert_sc8_item32_1_to_fcxx_1()); +} + UHD_STATIC_BLOCK(register_convert_sc16_item32_1_to_fcxx_1){ uhd::convert::id_type id; id.num_inputs = 1; @@ -185,4 +207,12 @@ UHD_STATIC_BLOCK(register_convert_sc16_item32_1_to_fcxx_1){ id.output_format = "fc64"; id.input_format = "sc8_item32_le"; uhd::convert::register_converter(id, &make_convert_sc8_item32_le_1_to_fc64_1, PRIORITY_TABLE); + + id.output_format = "sc16"; + id.input_format = "sc8_item32_be"; + uhd::convert::register_converter(id, &make_convert_sc8_item32_be_1_to_sc16_1, PRIORITY_TABLE); + + 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); } -- cgit v1.2.3 From d46c176af34b728fd43b3dd46485b38623a7335e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 30 Jan 2012 22:23:38 -0800 Subject: dsp rework: tx trailer, scaling work (peak) --- host/include/uhd/stream.hpp | 9 +++-- host/lib/convert/convert_common.hpp | 48 ++++++++++++++++++++++++ host/lib/convert/convert_with_tables.cpp | 21 ++++------- host/lib/convert/gen_convert_general.py | 16 ++++++++ host/lib/transport/gen_vrt_if_packet.py | 0 host/lib/transport/super_send_packet_handler.hpp | 2 +- host/lib/usrp/b100/io_impl.cpp | 1 + host/lib/usrp/cores/rx_dsp_core_200.cpp | 17 +++++---- host/lib/usrp/cores/tx_dsp_core_200.cpp | 25 +++++++++--- host/lib/usrp/e100/io_impl.cpp | 1 + host/lib/usrp/usrp2/io_impl.cpp | 1 + 11 files changed, 110 insertions(+), 31 deletions(-) mode change 100755 => 100644 host/lib/transport/gen_vrt_if_packet.py (limited to 'host/lib/convert/convert_with_tables.cpp') diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp index 0c9282545..cec2eee79 100644 --- a/host/include/uhd/stream.hpp +++ b/host/include/uhd/stream.hpp @@ -79,10 +79,11 @@ struct UHD_API stream_args_t{ * The args parameter is used to pass arbitrary key/value pairs. * Possible keys used by args (depends on implementation): * - * - scalar: an integer scaling factor used with the sc8 wire format. - * Use scalar=1 to harvest the lower 8-bits. - * Use scalar=256 to harvest the upper 8-bits. - * Any scalar in-between is also a possibility. + * - peak: specifies a fractional sample level to calculate scaling with the sc8 wire format. + * When using sc8 samples over the wire, the device must scale samples + * (both on the host and in the device) to satisfy the dynamic range needs. + * The peak value specifies a fraction of the maximum sample level (1.0 = 100%). + * Set peak to max_sample_level/full_scale_level to ensure optimum dynamic range. * * - underflow_policy: how the TX DSP should recover from underflow. * Possible options are "next_burst" or "next_packet". diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 699d6301b..aab59de4b 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -190,4 +190,52 @@ static UHD_INLINE void item32_sc8_to_fc64(item32_t item, fc64_t &out0, fc64_t &o ); } +/*********************************************************************** + * Convert complex char to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t sc8_to_item32_sc8(sc8_t in0, sc8_t in1, double){ + return + (item32_t(boost::uint8_t(in0.real())) << 8) | + (item32_t(boost::uint8_t(in0.imag())) << 0) | + (item32_t(boost::uint8_t(in1.real())) << 24) | + (item32_t(boost::uint8_t(in1.imag())) << 16) + ; +} + +/*********************************************************************** + * Convert complex short to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t sc16_to_item32_sc8(sc16_t in0, sc16_t in1, double){ + return + (item32_t(boost::uint8_t(in0.real())) << 8) | + (item32_t(boost::uint8_t(in0.imag())) << 0) | + (item32_t(boost::uint8_t(in1.real())) << 24) | + (item32_t(boost::uint8_t(in1.imag())) << 16) + ; +} + +/*********************************************************************** + * Convert complex float to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t fc32_to_item32_sc8(fc32_t in0, fc32_t in1, double scale_factor){ + return + (item32_t(boost::uint8_t(in0.real()*float(scale_factor))) << 8) | + (item32_t(boost::uint8_t(in0.imag()*float(scale_factor))) << 0) | + (item32_t(boost::uint8_t(in1.real()*float(scale_factor))) << 24) | + (item32_t(boost::uint8_t(in1.imag()*float(scale_factor))) << 16) + ; +} + +/*********************************************************************** + * Convert complex double to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t fc64_to_item32_sc8(fc64_t in0, fc64_t in1, double scale_factor){ + return + (item32_t(boost::uint8_t(in0.real()*(scale_factor))) << 8) | + (item32_t(boost::uint8_t(in0.imag()*(scale_factor))) << 0) | + (item32_t(boost::uint8_t(in1.real()*(scale_factor))) << 24) | + (item32_t(boost::uint8_t(in1.imag()*(scale_factor))) << 16) + ; +} + #endif /* INCLUDED_LIBUHD_CONVERT_COMMON_HPP */ diff --git a/host/lib/convert/convert_with_tables.cpp b/host/lib/convert/convert_with_tables.cpp index c033a2959..2379739a7 100644 --- a/host/lib/convert/convert_with_tables.cpp +++ b/host/lib/convert/convert_with_tables.cpp @@ -68,24 +68,19 @@ class convert_sc8_item32_1_to_fcxx_1 : public converter{ public: convert_sc8_item32_1_to_fcxx_1(void): _table(sc16_table_len){} - void set_scalar(const double scalar){ - - //special case, this is converts sc8 to sc16, - //use the scale-factor but no normalization + //special case for sc16 type, 32767 undoes float normalization + static type conv(const boost::int8_t &num, const double scalar){ if (sizeof(type) == sizeof(s16_t)){ - for (size_t i = 0; i < sc16_table_len; i++){ - const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff)); - const type real = type(boost::math::iround(boost::int8_t(val >> 8)*scalar*32767)); - const type imag = type(boost::math::iround(boost::int8_t(val >> 0)*scalar*32767)); - _table[i] = std::complex(real, imag); - } - return; + return type(boost::math::iround(num*scalar*32767)); } + return type(num*scalar); + } + void set_scalar(const double scalar){ for (size_t i = 0; i < sc16_table_len; i++){ const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff)); - const type real = type(boost::int8_t(val >> 8)*scalar); - const type imag = type(boost::int8_t(val >> 0)*scalar); + const type real = conv(boost::int8_t(val >> 8), scalar); + const type imag = conv(boost::int8_t(val >> 0), scalar); _table[i] = std::complex(real, imag); } } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index b8d64aa4b..a6ae3f810 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -92,6 +92,22 @@ DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ item32_sc8_to_$(cpu_type)(item_n, output[num_samps-1], dummy, scale_factor); } } + +DECLARE_CONVERTER($(cpu_type), 1, sc8_item32_$(end), 1, PRIORITY_GENERAL){ + const $(cpu_type)_t *input = reinterpret_cast(inputs[0]); + item32_t *output = reinterpret_cast(outputs[0]); + + const size_t num_pairs = nsamps/2; + for (size_t i = 0, j = 0; i < num_pairs; i++, j+=2){ + const item32_t item = $(cpu_type)_to_item32_sc8(input[j], input[j+1], scale_factor); + output[i] = $(to_wire)(item); + } + + if (nsamps != num_pairs*2){ + const item32_t item = $(cpu_type)_to_item32_sc8(input[nsamps-1], 0, scale_factor); + output[num_pairs] = $(to_wire)(item); + } +} """ TMPL_CONV_USRP1_COMPLEX = """ diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py old mode 100755 new mode 100644 diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 5ed8e0143..57304a7d4 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -134,7 +134,7 @@ public: vrt::if_packet_info_t if_packet_info; if_packet_info.has_sid = false; if_packet_info.has_cid = false; - if_packet_info.has_tlr = false; + if_packet_info.has_tlr = true; if_packet_info.has_tsi = metadata.has_time_spec; if_packet_info.has_tsf = metadata.has_time_spec; if_packet_info.tsi = boost::uint32_t(metadata.time_spec.get_full_secs()); diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 6e9e017aa..9474268ef 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -263,6 +263,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; static const size_t bpp = 2048 - hdr_size; diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index b2bf934bc..7b35daa42 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -63,8 +63,7 @@ public: { //init to something so update method has reasonable defaults _scaling_adjustment = 1.0; - _extra_scaling = 1.0; - _fxpt_scalar_correction = 1.0; + _dsp_extra_scaling = 1.0; //This is a hack/fix for the lingering packet problem. //The caller should also flush the recv transports @@ -187,14 +186,14 @@ public: } void update_scalar(void){ - const double target_scalar = (1 << 16)*_scaling_adjustment/_extra_scaling; + const double target_scalar = (1 << 16)*_scaling_adjustment/_dsp_extra_scaling; const boost::int32_t actual_scalar = boost::math::iround(target_scalar); _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small _iface->poke32(REG_DSP_RX_SCALE_IQ, actual_scalar); } double get_scaling_adjustment(void){ - return _fxpt_scalar_correction*_extra_scaling/32767.; + return _fxpt_scalar_correction*_host_extra_scaling/32767.; } double set_freq(const double freq_){ @@ -230,11 +229,15 @@ public: unsigned format_word = 0; if (stream_args.otw_format == "sc16"){ format_word = 0; - _extra_scaling = 1.0; + _dsp_extra_scaling = 1.0; + _host_extra_scaling = 1.0; } else if (stream_args.otw_format == "sc8"){ format_word = (1 << 0); - _extra_scaling = stream_args.args.cast("scalar", 1.0); + double peak = stream_args.args.cast("peak", 1.0); + peak = std::max(peak, 1.0/256); + _host_extra_scaling = peak*256; + _dsp_extra_scaling = peak*256; } else throw uhd::value_error("USRP RX cannot handle requested wire format: " + stream_args.otw_format); @@ -248,7 +251,7 @@ private: const size_t _dsp_base, _ctrl_base; double _tick_rate, _link_rate; bool _continuous_streaming; - double _scaling_adjustment, _extra_scaling, _fxpt_scalar_correction; + double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction; const boost::uint32_t _sid; }; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index 2c5b86bfc..15358e184 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -18,6 +18,7 @@ #include "tx_dsp_core_200.hpp" #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #define REG_TX_CTRL_POLICY _ctrl_base + 12 #define REG_TX_CTRL_CYCLES_PER_UP _ctrl_base + 16 #define REG_TX_CTRL_PACKETS_PER_UP _ctrl_base + 20 +#define REG_TX_CTRL_FORMAT _ctrl_base + 24 #define FLAG_TX_CTRL_POLICY_WAIT (0x1 << 0) #define FLAG_TX_CTRL_POLICY_NEXT_PACKET (0x1 << 1) @@ -60,8 +62,7 @@ public: { //init to something so update method has reasonable defaults _scaling_adjustment = 1.0; - _extra_scaling = 1.0; - _fxpt_scalar_correction = 1.0; + _dsp_extra_scaling = 1.0; //init the tx control registers this->clear(); @@ -134,14 +135,14 @@ public: } void update_scalar(void){ - const double target_scalar = (1 << 17)*_scaling_adjustment/_extra_scaling; + const double target_scalar = (1 << 17)*_scaling_adjustment/_dsp_extra_scaling; const boost::int32_t actual_scalar = boost::math::iround(target_scalar); _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small _iface->poke32(REG_DSP_TX_SCALE_IQ, actual_scalar); } double get_scaling_adjustment(void){ - return _fxpt_scalar_correction*_extra_scaling*32767.; + return _fxpt_scalar_correction*_host_extra_scaling*32767.; } double set_freq(const double freq_){ @@ -175,13 +176,25 @@ public: void setup(const uhd::stream_args_t &stream_args){ if (not stream_args.args.has_key("noclear")) this->clear(); + unsigned format_word = 0; if (stream_args.otw_format == "sc16"){ - _extra_scaling = 1.0; + format_word = 0; + _dsp_extra_scaling = 1.0; + _host_extra_scaling = 1.0; + } + else if (stream_args.otw_format == "sc8"){ + format_word = (1 << 0); + double peak = stream_args.args.cast("peak", 1.0); + peak = std::max(peak, 1.0/256); + _host_extra_scaling = 1.0/peak/256; + _dsp_extra_scaling = 1.0/peak; } else throw uhd::value_error("USRP TX cannot handle requested wire format: " + stream_args.otw_format); this->update_scalar(); + _iface->poke32(REG_TX_CTRL_FORMAT, format_word); + if (stream_args.args.has_key("underflow_policy")){ this->set_underflow_policy(stream_args.args["underflow_policy"]); } @@ -191,7 +204,7 @@ private: wb_iface::sptr _iface; const size_t _dsp_base, _ctrl_base; double _tick_rate, _link_rate; - double _scaling_adjustment, _extra_scaling, _fxpt_scalar_correction; + double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction; const boost::uint32_t _sid; }; diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 89a4ed00b..53f783a3f 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -339,6 +339,7 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 58a5df2a5..6dcec6f1f 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -450,6 +450,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + vrt_send_header_offset_words32*sizeof(boost::uint32_t) - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; -- cgit v1.2.3 From 893af3dc280a5d85be2a5beb266dba9bb538292c Mon Sep 17 00:00:00 2001 From: Josh Blum 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/lib/convert/convert_with_tables.cpp') 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 +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(inputs[0]); + item32_t *output = reinterpret_cast(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 _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()); } +static converter::sptr make_convert_sc16_1_to_sc8_item32_be_1(void){ + return converter::sptr(new convert_sc16_1_to_sc8_item32_1()); +} + +static converter::sptr make_convert_sc16_1_to_sc8_item32_le_1(void){ + return converter::sptr(new convert_sc16_1_to_sc8_item32_1()); +} + 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 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 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 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 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(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(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(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(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