diff options
author | Josh Blum <josh@joshknows.com> | 2010-03-11 18:37:34 -0800 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2010-03-11 18:37:34 -0800 |
commit | daed43a8a873ad5cc16ac8a3eb6db5a8fe126fa5 (patch) | |
tree | 72286b6649af0bf99e84edca08b584cb2e6af6ae /host/lib/gain_handler.cpp | |
parent | 9c0fb5e15da3c8ccbc1c8537671703411b210fcf (diff) | |
download | uhd-daed43a8a873ad5cc16ac8a3eb6db5a8fe126fa5.tar.gz uhd-daed43a8a873ad5cc16ac8a3eb6db5a8fe126fa5.tar.bz2 uhd-daed43a8a873ad5cc16ac8a3eb6db5a8fe126fa5.zip |
Cleaned up the gain handler (thing that gets and sets wildcard gains)
and made use of it in the dboard manager so it intercepts the sets and gets.
While doing this, fixed something with nested links in wax obj.
Added some useful macros and templates to the utils.
Diffstat (limited to 'host/lib/gain_handler.cpp')
-rw-r--r-- | host/lib/gain_handler.cpp | 264 |
1 files changed, 150 insertions, 114 deletions
diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index b03d5bda2..8f840ae7f 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -17,6 +17,7 @@ #include <uhd/gain_handler.hpp> #include <uhd/utils.hpp> +#include <uhd/props.hpp> #include <boost/assign/list_of.hpp> #include <boost/foreach.hpp> #include <boost/format.hpp> @@ -25,143 +26,178 @@ using namespace uhd; /*********************************************************************** - * Helper functions and macros + * helper functions **********************************************************************/ -#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)]); +static gain_t gain_max(gain_t a, gain_t b){ + return std::max(a, b); +} +static gain_t gain_sum(gain_t a, gain_t b){ + return std::sum(a, b); +} + +/*********************************************************************** + * gain handler implementation interface + **********************************************************************/ +class gain_handler_impl : public gain_handler{ +public: + gain_handler_impl( + const wax::obj &link, + const gain_props_t &gain_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; + gain_props_t _gain_props; + is_equal_t _is_equal; + + prop_names_t get_gain_names(void); + std::vector<gain_t> get_gains(const wax::obj &prop_key); + gain_t get_overall_gain_val(void); + gain_t get_overall_gain_min(void); + gain_t get_overall_gain_max(void); + gain_t get_overall_gain_step(void); +}; + +/*********************************************************************** + * the make function + **********************************************************************/ +gain_handler::sptr gain_handler::make( + const wax::obj &link, + const gain_props_t &gain_props, + is_equal_t is_equal +){ + return sptr(new gain_handler_impl(link, gain_props, is_equal)); } /*********************************************************************** - * Class methods of gain handler + * gain handler implementation methods **********************************************************************/ -gain_handler::~gain_handler(void){ +gain_handler::gain_props_t::gain_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 gain_props_t &gain_props, + is_equal_t is_equal +){ + _link = link; + _gain_props = gain_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 wax::cast<prop_names_t>(_link[_gain_props.gain_names_prop]); } -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; - } +std::vector<gain_t> gain_handler_impl::get_gains(const wax::obj &prop_key){ + std::vector<gain_t> gains; + BOOST_FOREACH(std::string name, get_gain_names()){ + gains.push_back(wax::cast<gain_t>(_link[named_prop_t(prop_key, name)])); } + return gains; +} + +gain_t gain_handler_impl::get_overall_gain_val(void){ + return std::reduce<gain_t>(get_gains(_gain_props.gain_val_prop), gain_sum); +} - return false; +gain_t gain_handler_impl::get_overall_gain_min(void){ + return std::reduce<gain_t>(get_gains(_gain_props.gain_min_prop), gain_sum); } -bool gain_handler::intercept_set(const wax::obj &key_, const wax::obj &val){ - _check_key(key_); //verify the key +gain_t gain_handler_impl::get_overall_gain_max(void){ + return std::reduce<gain_t>(get_gains(_gain_props.gain_max_prop), gain_sum); +} + +gain_t gain_handler_impl::get_overall_gain_step(void){ + return std::reduce<gain_t>(get_gains(_gain_props.gain_step_prop), gain_max); +} +/*********************************************************************** + * 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_); - /*! - * 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 wildcard... dont handle (but check name) + if (name != ""){ + assert_has(get_gain_names(), name, "gain name"); + return false; + } + + if (_is_equal(key, _gain_props.gain_val_prop)){ + val = get_overall_gain_val(); + return true; + } + + if (_is_equal(key, _gain_props.gain_min_prop)){ + val = get_overall_gain_min(); + return true; } - 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; - } + + if (_is_equal(key, _gain_props.gain_max_prop)){ + val = get_overall_gain_max(); return true; } - return false; + if (_is_equal(key, _gain_props.gain_step_prop)){ + val = get_overall_gain_step(); + 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_); + + //not a gain value key... dont handle + if (not _is_equal(key, _gain_props.gain_val_prop)) return false; + + gain_t gain_val = wax::cast<gain_t>(val); + + //not a wildcard... dont handle (but check name and range) + if (name != ""){ + assert_has(get_gain_names(), name, "gain name"); + gain_t gain_min = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_min_prop, name)]); + gain_t gain_max = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_max_prop, 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; + } + + //set the overall gain + BOOST_FOREACH(std::string name, get_gain_names()){ + //get the min, max, step for this gain name + gain_t gain_min = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_min_prop, name)]); + gain_t gain_max = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_max_prop, name)]); + gain_t gain_step = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_step_prop, 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 -= fmod(g, gain_step); + //set g to be the new gain + _link[named_prop_t(_gain_props.gain_val_prop, name)] = g; + //subtract g out of the total gain left to apply + gain_val -= g; + } + + return true; } |