diff options
| author | Josh Blum <josh@joshknows.com> | 2010-01-28 19:54:55 -0800 | 
|---|---|---|
| committer | Josh Blum <josh@joshknows.com> | 2010-01-28 19:54:55 -0800 | 
| commit | d5d9da3114bf069c05a8dcb7fca32ccd70405512 (patch) | |
| tree | 5c2c63efe9175ebd2b22c6b4899b997e9fed5b11 /lib/gain_handler.cpp | |
| parent | fc1bffcfd9761c1f60cf322bb58e7f9c8096a5c0 (diff) | |
| download | uhd-d5d9da3114bf069c05a8dcb7fca32ccd70405512.tar.gz uhd-d5d9da3114bf069c05a8dcb7fca32ccd70405512.tar.bz2 uhd-d5d9da3114bf069c05a8dcb7fca32ccd70405512.zip | |
Added gain handler class to manage wildcard gain settings.
Gets overall gains and sets overall gains when used.
Wild card gain will be a gain with an empty string name.
Diffstat (limited to 'lib/gain_handler.cpp')
| -rw-r--r-- | lib/gain_handler.cpp | 149 | 
1 files changed, 149 insertions, 0 deletions
| diff --git a/lib/gain_handler.cpp b/lib/gain_handler.cpp new file mode 100644 index 000000000..72343c1a4 --- /dev/null +++ b/lib/gain_handler.cpp @@ -0,0 +1,149 @@ +// +// Copyright 2010 Ettus Research LLC +// + +#include <usrp_uhd/gain_handler.hpp> +#include <usrp_uhd/utils.hpp> +#include <boost/assign/list_of.hpp> +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <vector> + +using namespace usrp_uhd; + +/*********************************************************************** + * Helper functions and macros + **********************************************************************/ +#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::ptr wax_obj_ptr, wax::type prop, std::string name){ +    return wax::cast<gain_t>((*wax_obj_ptr)[named_prop_t(prop, name)]); +} + +/*********************************************************************** + * Class methods of gain handler + **********************************************************************/ +gain_handler::~gain_handler(void){ +    /* NOP */ +} + +void gain_handler::_check_key(const wax::type &key_){ +    wax::type key; std::string name; +    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 &){} +} + +bool gain_handler::intercept_get(const wax::type &key, wax::type &val){ +    _check_key(key); //verify the key + +    // use a vector of tuples to map properties to a reducer function +    // we cant use a map because the wax::type cant be sorted +    typedef boost::function<gain_t(gain_t, gain_t)> reducer_t; +    typedef boost::tuple<wax::type, reducer_t> tuple_t; +    reducer_t reducer_sum = boost::bind(std::sum<gain_t>, _1, _2); +    reducer_t reducer_max = boost::bind(std::max<gain_t>, _1, _2); +    std::vector<tuple_t> prop_to_reducer = boost::assign::tuple_list_of +        (_gain_prop,      reducer_sum)(_gain_min_prop,  reducer_sum) +        (_gain_max_prop,  reducer_sum)(_gain_step_prop, reducer_max); + +    /*! +     * Handle getting overall gains when a name is not specified. +     * For the gain props below, set the overall value and return true.  +     */ +    BOOST_FOREACH(tuple_t p2r, prop_to_reducer){ +        if (_is_equal(key, p2r.get<0>())){ +            //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, p2r.get<0>(), _1) +            ); + +            //reduce across the gain vector +            val = std::reduce<gain_t>(gains.begin(), gains.end(), p2r.get<1>()); +            return true; +        } +    } + +    return false; +} + +bool gain_handler::intercept_set(const wax::type &key_, const wax::type &val){ +    _check_key(key_); //verify the key + +    wax::type key; std::string name; +    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 +        )); +    } +    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; +    } + +    return false; +} | 
