summaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-03-11 18:37:34 -0800
committerJosh Blum <josh@joshknows.com>2010-03-11 18:37:34 -0800
commitdaed43a8a873ad5cc16ac8a3eb6db5a8fe126fa5 (patch)
tree72286b6649af0bf99e84edca08b584cb2e6af6ae /host/lib
parent9c0fb5e15da3c8ccbc1c8537671703411b210fcf (diff)
downloaduhd-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')
-rw-r--r--host/lib/device.cpp15
-rw-r--r--host/lib/gain_handler.cpp264
-rw-r--r--host/lib/usrp/dboard/basic.cpp4
-rw-r--r--host/lib/usrp/dboard_manager.cpp83
-rw-r--r--host/lib/wax.cpp10
5 files changed, 221 insertions, 155 deletions
diff --git a/host/lib/device.cpp b/host/lib/device.cpp
index 82052708a..4b64e4a15 100644
--- a/host/lib/device.cpp
+++ b/host/lib/device.cpp
@@ -32,9 +32,16 @@ using namespace uhd;
* Create a new device from a device address.
* Based on the address, call the appropriate make functions.
* \param dev_addr the device address
+ * \param hint the device address that was used to find the device
* \return a smart pointer to a device
*/
-static device::sptr make_device(const device_addr_t &dev_addr){
+static device::sptr make_device(const device_addr_t &dev_addr_, const device_addr_t &hint){
+ //copy keys that were in hint but not in dev_addr
+ //this way, we can pass additional transport arguments
+ device_addr_t dev_addr = dev_addr_;
+ BOOST_FOREACH(std::string key, hint.get_keys()){
+ if (not dev_addr.has_key(key)) dev_addr[key] = hint[key];
+ }
//create a usrp1e
if (dev_addr["type"] == "usrp1e"){
@@ -46,7 +53,9 @@ static device::sptr make_device(const device_addr_t &dev_addr){
return usrp::usrp2::make(dev_addr);
}
- throw std::runtime_error("cant make a device");
+ throw std::runtime_error(str(
+ boost::format("Cant make a device for %s") % device_addr::to_string(dev_addr)
+ ));
}
/*!
@@ -126,7 +135,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
}
//create and register a new device
catch(const std::assert_error &e){
- device::sptr dev = make_device(dev_addr);
+ device::sptr dev = make_device(dev_addr, hint);
hash_to_device[dev_hash] = dev;
return dev;
}
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;
}
diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp
index 5e245a8cf..4b74e4a47 100644
--- a/host/lib/usrp/dboard/basic.cpp
+++ b/host/lib/usrp/dboard/basic.cpp
@@ -73,12 +73,12 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){
return dboard_base::sptr(new basic_tx(args, 32e6));
}
-STATIC_BLOCK(reg_dboards, {
+STATIC_BLOCK(reg_dboards){
dboard_manager::register_subdevs(0x0000, &make_basic_tx, "Basic TX", list_of(""));
dboard_manager::register_subdevs(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab"));
dboard_manager::register_subdevs(0x000e, &make_lf_tx, "LF TX", list_of(""));
dboard_manager::register_subdevs(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab"));
-});
+}
/***********************************************************************
* Basic and LF RX dboard
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index 57b449175..08b92e62a 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -16,10 +16,12 @@
//
#include <uhd/usrp/dboard_manager.hpp>
+#include <uhd/gain_handler.hpp>
#include <uhd/utils.hpp>
#include <uhd/dict.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/format.hpp>
+#include <boost/bind.hpp>
#include <boost/foreach.hpp>
using namespace uhd;
@@ -42,6 +44,7 @@ void dboard_manager::register_subdevs(
const std::string &name,
const prop_names_t &subdev_names
){
+ //std::cout << "registering: " << name << std::endl;
id_to_str[dboard_id] = name;
id_to_args_map[dboard_id] = args_t(dboard_ctor, subdev_names);
}
@@ -52,36 +55,7 @@ std::string dboard_id::to_string(const dboard_id_t &id){
}
/***********************************************************************
- * dboard manager implementation class
- **********************************************************************/
-class dboard_manager_impl : public dboard_manager{
-
-public:
- dboard_manager_impl(
- dboard_id_t rx_dboard_id,
- dboard_id_t tx_dboard_id,
- dboard_interface::sptr interface
- );
- ~dboard_manager_impl(void);
-
- //dboard_interface
- prop_names_t get_rx_subdev_names(void);
- prop_names_t get_tx_subdev_names(void);
- wax::obj get_rx_subdev(const std::string &subdev_name);
- wax::obj get_tx_subdev(const std::string &subdev_name);
-
-private:
- //list of rx and tx dboards in this dboard_manager
- //each dboard here is actually a subdevice proxy
- //the subdevice proxy is internal to the cpp file
- uhd::dict<std::string, wax::obj> _rx_dboards;
- uhd::dict<std::string, wax::obj> _tx_dboards;
- dboard_interface::sptr _interface;
- void set_nice_gpio_pins(void);
-};
-
-/***********************************************************************
- * internal helper classes
+ * internal helper classe
**********************************************************************/
/*!
* A special wax proxy object that forwards calls to a subdev.
@@ -95,7 +69,18 @@ public:
//structors
subdev_proxy(dboard_base::sptr subdev, type_t type)
: _subdev(subdev), _type(type){
- /* NOP */
+ //initialize gain props struct
+ gain_handler::gain_props_t gain_props;
+ gain_props.gain_val_prop = SUBDEV_PROP_GAIN;
+ gain_props.gain_min_prop = SUBDEV_PROP_GAIN_MIN;
+ gain_props.gain_max_prop = SUBDEV_PROP_GAIN_MAX;
+ gain_props.gain_step_prop = SUBDEV_PROP_GAIN_STEP;
+ gain_props.gain_names_prop = SUBDEV_PROP_GAIN_NAMES;
+
+ //make a new gain handler
+ _gain_handler = gain_handler::make(
+ this->get_link(), gain_props, boost::bind(&gain_handler::is_equal<subdev_prop_t>, _1, _2)
+ );
}
~subdev_proxy(void){
@@ -103,11 +88,13 @@ public:
}
private:
+ gain_handler::sptr _gain_handler;
dboard_base::sptr _subdev;
type_t _type;
//forward the get calls to the rx or tx
void get(const wax::obj &key, wax::obj &val){
+ if (_gain_handler->intercept_get(key, val)) return;
switch(_type){
case RX_TYPE: return _subdev->rx_get(key, val);
case TX_TYPE: return _subdev->tx_get(key, val);
@@ -116,6 +103,7 @@ private:
//forward the set calls to the rx or tx
void set(const wax::obj &key, const wax::obj &val){
+ if (_gain_handler->intercept_set(key, val)) return;
switch(_type){
case RX_TYPE: return _subdev->rx_set(key, val);
case TX_TYPE: return _subdev->tx_set(key, val);
@@ -124,6 +112,35 @@ private:
};
/***********************************************************************
+ * dboard manager implementation class
+ **********************************************************************/
+class dboard_manager_impl : public dboard_manager{
+
+public:
+ dboard_manager_impl(
+ dboard_id_t rx_dboard_id,
+ dboard_id_t tx_dboard_id,
+ dboard_interface::sptr interface
+ );
+ ~dboard_manager_impl(void);
+
+ //dboard_interface
+ prop_names_t get_rx_subdev_names(void);
+ prop_names_t get_tx_subdev_names(void);
+ wax::obj get_rx_subdev(const std::string &subdev_name);
+ wax::obj get_tx_subdev(const std::string &subdev_name);
+
+private:
+ //list of rx and tx dboards in this dboard_manager
+ //each dboard here is actually a subdevice proxy
+ //the subdevice proxy is internal to the cpp file
+ uhd::dict<std::string, subdev_proxy::sptr> _rx_dboards;
+ uhd::dict<std::string, subdev_proxy::sptr> _tx_dboards;
+ dboard_interface::sptr _interface;
+ void set_nice_gpio_pins(void);
+};
+
+/***********************************************************************
* make routine for dboard manager
**********************************************************************/
dboard_manager::sptr dboard_manager::make(
@@ -241,7 +258,7 @@ wax::obj dboard_manager_impl::get_rx_subdev(const std::string &subdev_name){
str(boost::format("Unknown rx subdev name %s") % subdev_name)
);
//get a link to the rx subdev proxy
- return wax::cast<subdev_proxy::sptr>(_rx_dboards[subdev_name])->get_link();
+ return _rx_dboards[subdev_name]->get_link();
}
wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){
@@ -249,7 +266,7 @@ wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){
str(boost::format("Unknown tx subdev name %s") % subdev_name)
);
//get a link to the tx subdev proxy
- return wax::cast<subdev_proxy::sptr>(_tx_dboards[subdev_name])->get_link();
+ return _tx_dboards[subdev_name]->get_link();
}
void dboard_manager_impl::set_nice_gpio_pins(void){
diff --git a/host/lib/wax.cpp b/host/lib/wax.cpp
index c08398c50..0348d9a66 100644
--- a/host/lib/wax.cpp
+++ b/host/lib/wax.cpp
@@ -36,7 +36,11 @@ public:
link_args_t(const wax::obj *obj_ptr) : _obj_ptr(obj_ptr){
/* NOP */
}
- wax::obj & operator()(void){
+ wax::obj & operator()(void) const{
+ //recursively resolve link args to get at original pointer
+ if (_obj_ptr->type() == typeid(link_args_t)){
+ return wax::cast<link_args_t>(*_obj_ptr)();
+ }
return *const_cast<wax::obj *>(_obj_ptr);
}
private:
@@ -56,10 +60,10 @@ public:
proxy_args_t(const wax::obj *obj_ptr, const wax::obj &key) : _key(key){
_obj_link = obj_ptr->get_link();
}
- wax::obj & operator()(void){
+ wax::obj & operator()(void) const{
return wax::cast<link_args_t>(_obj_link)();
}
- const wax::obj & key(void){
+ const wax::obj & key(void) const{
return _key;
}
private: