From f21874e68a413ad8088bef69e3e8c1ef9c352eca Mon Sep 17 00:00:00 2001 From: Tom Tsou Date: Thu, 6 Jul 2017 17:25:55 -0700 Subject: convert: Add sc12-sc16 converters Create missing sc12-sc16 and sc16-sc12 type converters. To avoid replicating the full sc12 converter class object, overload the converter calls with C++11 std::enable_if metafunctions. When used with std::is_floating and std::is_integral templates, this allow a single template interface with compile time function selection and static type checking. Note the below std::enable_if interface is confusing, but quite effective in this case. typename enable_if::value>::type* = NULL Fixes: #966 Related: #967, #1721 --- host/lib/convert/convert_pack_sc12.cpp | 91 +++++++++++++++++++++++++------- host/lib/convert/convert_unpack_sc12.cpp | 50 ++++++++++++++++-- 2 files changed, 117 insertions(+), 24 deletions(-) (limited to 'host/lib/convert') diff --git a/host/lib/convert/convert_pack_sc12.cpp b/host/lib/convert/convert_pack_sc12.cpp index aaa6f2632..2e45e19f5 100644 --- a/host/lib/convert/convert_pack_sc12.cpp +++ b/host/lib/convert/convert_pack_sc12.cpp @@ -20,6 +20,7 @@ #include #include #include +#include using namespace uhd::convert; @@ -59,6 +60,17 @@ enum item32_sc12_3x_enable { * |_ _|_ _ _4_ _ _| 2 * 31 0 */ +template +inline void pack(item32_sc12_3x &output, int enable, const int32_t i[4], const int32_t q[4]) +{ + if (enable & CONVERT12_LINE0) + output.line0 = towire(i[0] << 20 | q[0] << 8 | i[1] >> 4); + if (enable & CONVERT12_LINE1) + output.line1 = towire(i[1] << 28 | q[1] << 16 | i[2] << 4 | q[2] >> 8); + if (enable & CONVERT12_LINE2) + output.line2 = towire(q[2] << 24 | i[3] << 12 | q[3]); +} + template void convert_star_4_to_sc12_item32_3 ( @@ -68,31 +80,55 @@ void convert_star_4_to_sc12_item32_3 const std::complex &in3, const int enable, item32_sc12_3x &output, - const double scalar + const double scalar, + typename std::enable_if::value>::type* = NULL ) { - const item32_t i0 = int32_t(type(in0.real()*scalar)) & 0xfff; - const item32_t q0 = int32_t(type(in0.imag()*scalar)) & 0xfff; + int32_t i[4] { + int32_t(in0.real()*scalar) & 0xfff, + int32_t(in1.real()*scalar) & 0xfff, + int32_t(in2.real()*scalar) & 0xfff, + int32_t(in3.real()*scalar) & 0xfff, + }; - const item32_t i1 = int32_t(type(in1.real()*scalar)) & 0xfff; - const item32_t q1 = int32_t(type(in1.imag()*scalar)) & 0xfff; + int32_t q[4] { + int32_t(in0.imag()*scalar) & 0xfff, + int32_t(in1.imag()*scalar) & 0xfff, + int32_t(in2.imag()*scalar) & 0xfff, + int32_t(in3.imag()*scalar) & 0xfff, + }; - const item32_t i2 = int32_t(type(in2.real()*scalar)) & 0xfff; - const item32_t q2 = int32_t(type(in2.imag()*scalar)) & 0xfff; + pack(output, enable, i, q); +} - const item32_t i3 = int32_t(type(in3.real()*scalar)) & 0xfff; - const item32_t q3 = int32_t(type(in3.imag()*scalar)) & 0xfff; +template +void convert_star_4_to_sc12_item32_3 +( + const std::complex &in0, + const std::complex &in1, + const std::complex &in2, + const std::complex &in3, + const int enable, + item32_sc12_3x &output, + const double, + typename std::enable_if::value>::type* = NULL +) +{ + int32_t i[4] { + int32_t(in0.real() >> 4) & 0xfff, + int32_t(in1.real() >> 4) & 0xfff, + int32_t(in2.real() >> 4) & 0xfff, + int32_t(in3.real() >> 4) & 0xfff, + }; - const item32_t line0 = (i0 << 20) | (q0 << 8) | (i1 >> 4); - const item32_t line1 = (i1 << 28) | (q1 << 16) | (i2 << 4) | (q2 >> 8); - const item32_t line2 = (q2 << 24) | (i3 << 12) | (q3); + int32_t q[4] { + int32_t(in0.imag() >> 4) & 0xfff, + int32_t(in1.imag() >> 4) & 0xfff, + int32_t(in2.imag() >> 4) & 0xfff, + int32_t(in3.imag() >> 4) & 0xfff, + }; - if (enable & CONVERT12_LINE0) - output.line0 = towire(line0); - if (enable & CONVERT12_LINE1) - output.line1 = towire(line1); - if (enable & CONVERT12_LINE2) - output.line2 = towire(line2); + pack(output, enable, i, q); } template @@ -192,6 +228,16 @@ static converter::sptr make_convert_fc32_1_to_sc12_item32_be_1(void) return converter::sptr(new convert_star_1_to_sc12_item32_1()); } +static converter::sptr make_convert_sc16_1_to_sc12_item32_le_1(void) +{ + return converter::sptr(new convert_star_1_to_sc12_item32_1()); +} + +static converter::sptr make_convert_sc16_1_to_sc12_item32_be_1(void) +{ + return converter::sptr(new convert_star_1_to_sc12_item32_1()); +} + UHD_STATIC_BLOCK(register_convert_pack_sc12) { //uhd::convert::register_bytes_per_item("sc12", 3/*bytes*/); //registered in unpack @@ -199,11 +245,16 @@ UHD_STATIC_BLOCK(register_convert_pack_sc12) uhd::convert::id_type id; id.num_inputs = 1; id.num_outputs = 1; - id.input_format = "fc32"; + id.input_format = "fc32"; id.output_format = "sc12_item32_le"; uhd::convert::register_converter(id, &make_convert_fc32_1_to_sc12_item32_le_1, PRIORITY_GENERAL); - id.output_format = "sc12_item32_be"; uhd::convert::register_converter(id, &make_convert_fc32_1_to_sc12_item32_be_1, PRIORITY_GENERAL); + + id.input_format = "sc16"; + id.output_format = "sc12_item32_le"; + uhd::convert::register_converter(id, &make_convert_sc16_1_to_sc12_item32_le_1, PRIORITY_GENERAL); + id.output_format = "sc12_item32_be"; + uhd::convert::register_converter(id, &make_convert_sc16_1_to_sc12_item32_be_1, PRIORITY_GENERAL); } diff --git a/host/lib/convert/convert_unpack_sc12.cpp b/host/lib/convert/convert_unpack_sc12.cpp index f42e51c00..07f9cffa0 100644 --- a/host/lib/convert/convert_unpack_sc12.cpp +++ b/host/lib/convert/convert_unpack_sc12.cpp @@ -20,6 +20,7 @@ #include #include #include +#include using namespace uhd::convert; @@ -56,7 +57,8 @@ void convert_sc12_item32_3_to_star_4 std::complex &out1, std::complex &out2, std::complex &out3, - const double scalar + const double scalar, + typename std::enable_if::value>::type* = NULL ) { //step 0: extract the lines from the input buffer @@ -86,6 +88,32 @@ void convert_sc12_item32_3_to_star_4 out3 = std::complex(i3, q3); } +template +void convert_sc12_item32_3_to_star_4 +( + const item32_sc12_3x &input, + std::complex &out0, + std::complex &out1, + std::complex &out2, + std::complex &out3, + const double, + typename std::enable_if::value>::type* = NULL +) +{ + //step 0: extract the lines from the input buffer + const item32_t line0 = tohost(input.line0); + const item32_t line1 = tohost(input.line1); + const item32_t line2 = tohost(input.line2); + const uint64_t line01 = (uint64_t(line0) << 32) | line1; + const uint64_t line12 = (uint64_t(line1) << 32) | line2; + + //step 1: extract and load the outputs + out0 = std::complex(line0 >> 16 & 0xfff0, line0 >> 4 & 0xfff0); + out1 = std::complex(line01 >> 24 & 0xfff0, line1 >> 12 & 0xfff0); + out2 = std::complex(line1 >> 0 & 0xfff0, line12 >> 20 & 0xfff0); + out3 = std::complex(line2 >> 8 & 0xfff0, line2 << 4 & 0xfff0); +} + template struct convert_sc12_item32_1_to_star_1 : public converter { @@ -193,18 +221,32 @@ static converter::sptr make_convert_sc12_item32_be_1_to_fc32_1(void) return converter::sptr(new convert_sc12_item32_1_to_star_1()); } +static converter::sptr make_convert_sc12_item32_le_1_to_sc16_1(void) +{ + return converter::sptr(new convert_sc12_item32_1_to_star_1()); +} + +static converter::sptr make_convert_sc12_item32_be_1_to_sc16_1(void) +{ + return converter::sptr(new convert_sc12_item32_1_to_star_1()); +} + UHD_STATIC_BLOCK(register_convert_unpack_sc12) { uhd::convert::register_bytes_per_item("sc12", 3/*bytes*/); - uhd::convert::id_type id; id.num_inputs = 1; id.num_outputs = 1; - id.output_format = "fc32"; + id.output_format = "fc32"; id.input_format = "sc12_item32_le"; uhd::convert::register_converter(id, &make_convert_sc12_item32_le_1_to_fc32_1, PRIORITY_GENERAL); - id.input_format = "sc12_item32_be"; uhd::convert::register_converter(id, &make_convert_sc12_item32_be_1_to_fc32_1, PRIORITY_GENERAL); + + id.output_format = "sc16"; + id.input_format = "sc12_item32_le"; + uhd::convert::register_converter(id, &make_convert_sc12_item32_le_1_to_sc16_1, PRIORITY_GENERAL); + id.input_format = "sc12_item32_be"; + uhd::convert::register_converter(id, &make_convert_sc12_item32_be_1_to_sc16_1, PRIORITY_GENERAL); } -- cgit v1.2.3