aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/gain_handler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/gain_handler.cpp')
-rw-r--r--host/lib/gain_handler.cpp177
1 files changed, 177 insertions, 0 deletions
diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp
new file mode 100644
index 000000000..36e2e8ed3
--- /dev/null
+++ b/host/lib/gain_handler.cpp
@@ -0,0 +1,177 @@
+//
+// Copyright 2010 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/gain_handler.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/utils/props.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <cmath>
+#include <vector>
+
+using namespace uhd;
+
+/***********************************************************************
+ * gain handler implementation interface
+ **********************************************************************/
+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);
+ float 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));
+}
+
+/***********************************************************************
+ * gain handler implementation methods
+ **********************************************************************/
+gain_handler::props_t::props_t(void){
+ /* NOP */
+}
+
+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;
+}
+
+gain_handler_impl::~gain_handler_impl(void){
+ /* NOP */
+}
+
+prop_names_t gain_handler_impl::get_gain_names(void){
+ return _link[_props.names].as<prop_names_t>();
+}
+
+float gain_handler_impl::get_overall_gain_val(void){
+ float gain_val = 0;
+ BOOST_FOREACH(std::string name, get_gain_names()){
+ gain_val += get_named_prop<float>(_props.value, name);
+ }
+ return gain_val;
+}
+
+gain_range_t gain_handler_impl::get_overall_gain_range(void){
+ float gain_min = 0, gain_max = 0, gain_step = 0;
+ BOOST_FOREACH(std::string name, get_gain_names()){
+ gain_range_t floatmp = get_named_prop<gain_range_t>(_props.range, name);
+ gain_min += floatmp.min;
+ gain_max += floatmp.max;
+ gain_step = std::max(gain_step, floatmp.step);
+ }
+ return gain_range_t(gain_min, gain_max, gain_step);
+}
+
+/***********************************************************************
+ * 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_);
+
+ //not a gain value key... dont handle
+ if (not _is_equal(key, _props.value)) return false;
+
+ float gain_val = val.as<float>();
+
+ //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;
+ }
+
+ //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
+ float 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 true;
+}