diff options
Diffstat (limited to 'host/lib/gain_handler.cpp')
-rw-r--r-- | host/lib/gain_handler.cpp | 238 |
1 files changed, 124 insertions, 114 deletions
diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index b03d5bda2..7dd1547cb 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -17,151 +17,161 @@ #include <uhd/gain_handler.hpp> #include <uhd/utils.hpp> +#include <uhd/types.hpp> +#include <uhd/props.hpp> #include <boost/assign/list_of.hpp> #include <boost/foreach.hpp> #include <boost/format.hpp> +#include <cmath> #include <vector> using namespace uhd; /*********************************************************************** - * Helper functions and macros + * gain handler implementation interface **********************************************************************/ -#define GET_PROP_NAMES() \ - wax::cast<prop_names_t>((*_wax_obj_ptr)[_gain_names_prop]) - -/*! - * Helper function to simplify getting a named gain (also min, max, step). - */ -static gain_t get_named_gain(wax::obj *wax_obj_ptr, wax::obj prop, std::string name){ - return wax::cast<gain_t>((*wax_obj_ptr)[named_prop_t(prop, name)]); +class gain_handler_impl : public gain_handler{ +public: + gain_handler_impl( + const wax::obj &link, + const props_t &props, + is_equal_t is_equal + ); + ~gain_handler_impl(void); + bool intercept_get(const wax::obj &key, wax::obj &val); + bool intercept_set(const wax::obj &key, const wax::obj &val); + +private: + wax::obj _link; + props_t _props; + is_equal_t _is_equal; + + prop_names_t get_gain_names(void); + gain_t get_overall_gain_val(void); + gain_range_t get_overall_gain_range(void); + template <class T> T get_named_prop(const wax::obj &prop, const std::string &name){ + return _link[named_prop_t(prop, name)].as<T>(); + } +}; + +/*********************************************************************** + * the make function + **********************************************************************/ +gain_handler::sptr gain_handler::make( + const wax::obj &link, + const props_t &props, + is_equal_t is_equal +){ + return sptr(new gain_handler_impl(link, props, is_equal)); } /*********************************************************************** - * Class methods of gain handler + * gain handler implementation methods **********************************************************************/ -gain_handler::~gain_handler(void){ +gain_handler::props_t::props_t(void){ /* NOP */ } -void gain_handler::_check_key(const wax::obj &key_){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); - - try{ - //only handle non wildcard names - ASSERT_THROW(name != ""); - - //only handle these gain props - ASSERT_THROW( - _is_equal(key, _gain_prop) or - _is_equal(key, _gain_min_prop) or - _is_equal(key, _gain_max_prop) or - _is_equal(key, _gain_step_prop) - ); - - //check that the name is allowed - prop_names_t prop_names = GET_PROP_NAMES(); - ASSERT_THROW(not std::has(prop_names.begin(), prop_names.end(), name)); - - //if we get here, throw an exception - throw std::invalid_argument(str( - boost::format("Unknown gain name %s") % name - )); - } - catch(const std::assert_error &){} +gain_handler_impl::gain_handler_impl( + const wax::obj &link, + const props_t &props, + is_equal_t is_equal +){ + _link = link; + _props = props; + _is_equal = is_equal; } -static gain_t gain_max(gain_t a, gain_t b){ - return std::max(a, b); +gain_handler_impl::~gain_handler_impl(void){ + /* NOP */ } -static gain_t gain_sum(gain_t a, gain_t b){ - return std::sum(a, b); + +prop_names_t gain_handler_impl::get_gain_names(void){ + return _link[_props.names].as<prop_names_t>(); } -bool gain_handler::intercept_get(const wax::obj &key, wax::obj &val){ - _check_key(key); //verify the key - - std::vector<wax::obj> gain_props = boost::assign::list_of - (_gain_prop)(_gain_min_prop)(_gain_max_prop)(_gain_step_prop); - - /*! - * Handle getting overall gains when a name is not specified. - * For the gain props below, set the overall value and return true. - */ - BOOST_FOREACH(wax::obj prop_key, gain_props){ - if (_is_equal(key, prop_key)){ - //form the gains vector from the props vector - prop_names_t prop_names = GET_PROP_NAMES(); - std::vector<gain_t> gains(prop_names.size()); - std::transform( - prop_names.begin(), prop_names.end(), gains.begin(), - boost::bind(get_named_gain, _wax_obj_ptr, key, _1) - ); - - //reduce across the gain vector - if (_is_equal(key, _gain_step_prop)){ - val = std::reduce<gain_t>(gains.begin(), gains.end(), gain_max); - } - else{ - val = std::reduce<gain_t>(gains.begin(), gains.end(), gain_sum); - } - return true; - } +gain_t gain_handler_impl::get_overall_gain_val(void){ + gain_t gain_val = 0; + BOOST_FOREACH(std::string name, get_gain_names()){ + gain_val += get_named_prop<gain_t>(_props.value, name); } + return gain_val; +} - return false; +gain_range_t gain_handler_impl::get_overall_gain_range(void){ + gain_t gain_min = 0, gain_max = 0, gain_step = 0; + BOOST_FOREACH(std::string name, get_gain_names()){ + gain_range_t gain_tmp = get_named_prop<gain_range_t>(_props.range, name); + gain_min += gain_tmp.min; + gain_max += gain_tmp.max; + gain_step = std::max(gain_step, gain_tmp.step); + } + return gain_range_t(gain_min, gain_max, gain_step); } -bool gain_handler::intercept_set(const wax::obj &key_, const wax::obj &val){ - _check_key(key_); //verify the key +/*********************************************************************** + * gain handler implementation get method + **********************************************************************/ +bool gain_handler_impl::intercept_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //not a wildcard... dont handle (but check name) + if (name != ""){ + assert_has(get_gain_names(), name, "gain name"); + return false; + } + + if (_is_equal(key, _props.value)){ + val = get_overall_gain_val(); + return true; + } + + if (_is_equal(key, _props.range)){ + val = get_overall_gain_range(); + return true; + } + + return false; //not handled +} +/*********************************************************************** + * gain handler implementation set method + **********************************************************************/ +bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val){ wax::obj key; std::string name; boost::tie(key, name) = extract_named_prop(key_); - /*! - * Verify that a named gain component is in range. - */ - try{ - //only handle the gain props - ASSERT_THROW(_is_equal(key, _gain_prop)); - - //check that the gain is in range - gain_t gain = wax::cast<gain_t>(val); - gain_t gain_min = get_named_gain(_wax_obj_ptr, _gain_min_prop, name); - gain_t gain_max = get_named_gain(_wax_obj_ptr, _gain_max_prop, name); - ASSERT_THROW(gain > gain_max or gain < gain_min); - - //if we get here, throw an exception - throw std::range_error(str( - boost::format("gain %s is out of range of (%f, %f)") % name % gain_min % gain_max + //not a gain value key... dont handle + if (not _is_equal(key, _props.value)) return false; + + gain_t gain_val = val.as<gain_t>(); + + //not a wildcard... dont handle (but check name and range) + if (name != ""){ + assert_has(get_gain_names(), name, "gain name"); + gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name); + if (gain_val > gain.max or gain_val < gain.min) throw std::range_error(str( + boost::format("A value of %f for gain %s is out of range of (%f, %f)") + % gain_val % name % gain.min % gain.max )); + return false; } - catch(const std::assert_error &){} - - /*! - * Handle setting the overall gain. - */ - if (_is_equal(key, _gain_prop) and name == ""){ - gain_t gain = wax::cast<gain_t>(val); - prop_names_t prop_names = GET_PROP_NAMES(); - BOOST_FOREACH(std::string name, prop_names){ - //get the min, max, step for this gain name - gain_t gain_min = get_named_gain(_wax_obj_ptr, _gain_min_prop, name); - gain_t gain_max = get_named_gain(_wax_obj_ptr, _gain_max_prop, name); - gain_t gain_step = get_named_gain(_wax_obj_ptr, _gain_step_prop, name); - - //clip g to be within the allowed range - gain_t g = std::min(std::max(gain, gain_min), gain_max); - //set g to be a multiple of the step size - g -= fmod(g, gain_step); - //set g to be the new gain - (*_wax_obj_ptr)[named_prop_t(_gain_prop, name)] = g; - //subtract g out of the total gain left to apply - gain -= g; - } - return true; + + //set the overall gain + BOOST_FOREACH(std::string name, get_gain_names()){ + //get the min, max, step for this gain name + gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name); + + //clip g to be within the allowed range + gain_t g = std::min(std::max(gain_val, gain.min), gain.max); + //set g to be a multiple of the step size + g -= std::fmod(g, gain.step); + //set g to be the new gain + _link[named_prop_t(_props.value, name)] = g; + //subtract g out of the total gain left to apply + gain_val -= g; } - return false; + return true; } |