diff options
-rw-r--r-- | host/include/uhd/convert.hpp | 8 | ||||
-rw-r--r-- | host/lib/convert/convert_impl.cpp | 43 | ||||
-rw-r--r-- | host/tests/convert_test.cpp | 28 |
3 files changed, 50 insertions, 29 deletions
diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp index f906ff0e9..c6b005867 100644 --- a/host/include/uhd/convert.hpp +++ b/host/include/uhd/convert.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 @@ -80,9 +80,13 @@ namespace uhd{ namespace convert{ /*! * Get a converter factory function. * \param id identify the conversion + * \param prio the desired prio or -1 for best * \return the converter factory function */ - UHD_API function_type get_converter(const id_type &id); + UHD_API function_type get_converter( + const id_type &id, + const priority_type prio = -1 + ); /*! * Register the size of a particular item. diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 12ad54486..dc7f8f9dc 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -22,6 +22,7 @@ #include <uhd/exception.hpp> #include <boost/cstdint.hpp> #include <boost/format.hpp> +#include <boost/foreach.hpp> #include <complex> using namespace uhd; @@ -51,17 +52,9 @@ std::string convert::id_type::to_pp_string(void) const{ } /*********************************************************************** - * Define types for the function tables - **********************************************************************/ -struct fcn_table_entry_type{ - convert::priority_type prio; - convert::function_type fcn; -}; - -/*********************************************************************** * Setup the table registry **********************************************************************/ -typedef uhd::dict<convert::id_type, fcn_table_entry_type> fcn_table_type; +typedef uhd::dict<convert::id_type, uhd::dict<convert::priority_type, convert::function_type> > fcn_table_type; UHD_SINGLETON_FCN(fcn_table_type, get_table); /*********************************************************************** @@ -72,14 +65,7 @@ void uhd::convert::register_converter( const function_type &fcn, const priority_type prio ){ - //get a reference to the function table - fcn_table_type &table = get_table(); - - //register the function if higher priority - if (not table.has_key(id) or table[id].prio < prio){ - table[id].fcn = fcn; - table[id].prio = prio; - } + get_table()[id][prio] = fcn; //----------------------------------------------------------------// UHD_LOGV(always) << "register_converter: " << id.to_pp_string() << std::endl @@ -92,9 +78,26 @@ void uhd::convert::register_converter( /*********************************************************************** * The converter functions **********************************************************************/ -convert::function_type convert::get_converter(const id_type &id){ - if (get_table().has_key(id)) return get_table()[id].fcn; - throw uhd::key_error("Cannot find a conversion routine for " + id.to_pp_string()); +convert::function_type convert::get_converter( + const id_type &id, + const priority_type prio +){ + if (not get_table().has_key(id)) throw uhd::key_error( + "Cannot find a conversion routine for " + id.to_pp_string()); + + //find a matching priority + priority_type best_prio = -1; + BOOST_FOREACH(priority_type prio_i, get_table()[id].keys()){ + if (prio_i == prio) return get_table()[id][prio]; + best_prio = std::max(best_prio, prio_i); + } + + //wanted a specific prio, didnt find + if (prio != -1) throw uhd::key_error( + "Cannot find a conversion routine [with prio] for " + id.to_pp_string()); + + //otherwise, return best prio + return get_table()[id][best_prio]; } /*********************************************************************** diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp index 6b0ae53a9..4b0226e3d 100644 --- a/host/tests/convert_test.cpp +++ b/host/tests/convert_test.cpp @@ -19,6 +19,7 @@ #include <boost/test/unit_test.hpp> #include <boost/foreach.hpp> #include <boost/cstdint.hpp> +#include <boost/assign/list_of.hpp> #include <complex> #include <vector> #include <cstdlib> @@ -45,7 +46,9 @@ template <typename Range> static void loopback( convert::id_type &in_id, convert::id_type &out_id, const Range &input, - Range &output + Range &output, + const int prio_in = -1, + const int prio_out = -1 ){ //item32 is largest device type std::vector<boost::uint32_t> interm(nsamps); @@ -54,12 +57,12 @@ template <typename Range> static void loopback( std::vector<void *> output0(1, &interm[0]), output1(1, &output[0]); //convert to intermediate type - convert::converter::sptr c0 = convert::get_converter(in_id)(); + convert::converter::sptr c0 = convert::get_converter(in_id, prio_in)(); c0->set_scalar(32767.); c0->conv(input0, output0, nsamps); //convert back to host type - convert::converter::sptr c1 = convert::get_converter(out_id)(); + convert::converter::sptr c1 = convert::get_converter(out_id, prio_out)(); c1->set_scalar(1/32767.); c1->conv(input1, output1, nsamps); } @@ -133,10 +136,21 @@ static void test_convert_types_for_floats( convert::id_type out_id = id; std::swap(out_id.input_format, out_id.output_format); std::swap(out_id.num_inputs, out_id.num_outputs); - loopback(nsamps, in_id, out_id, input, output); - for (size_t i = 0; i < nsamps; i++){ - MY_CHECK_CLOSE(input[i].real(), output[i].real(), value_type(1./32767)); - MY_CHECK_CLOSE(input[i].imag(), output[i].imag(), value_type(1./32767)); + + //make a list of all prio: best/generic combos + typedef std::pair<int, int> int_pair_t; + std::vector<int_pair_t> prios = boost::assign::list_of + (int_pair_t(0, 0)) (int_pair_t(-1, 0)) + (int_pair_t(0, -1)) (int_pair_t(-1, -1)) + ; + + //loopback foreach prio combo (generic vs best) + BOOST_FOREACH(const int_pair_t &prio, prios){ + loopback(nsamps, in_id, out_id, input, output, prio.first, prio.second); + for (size_t i = 0; i < nsamps; i++){ + MY_CHECK_CLOSE(input[i].real(), output[i].real(), value_type(1./32767)); + MY_CHECK_CLOSE(input[i].imag(), output[i].imag(), value_type(1./32767)); + } } } |