From daed43a8a873ad5cc16ac8a3eb6db5a8fe126fa5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 11 Mar 2010 18:37:34 -0800 Subject: 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. --- host/lib/device.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'host/lib/device.cpp') 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; } -- cgit v1.2.3 From 7590f187d0414fd05e23828488166bc4bc88df26 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 15 Mar 2010 12:15:33 -0700 Subject: Device sub classes can register themselves. Simplifies device.cpp internals. Added static instance macro for lazy instantiation of static variables. --- host/include/uhd/device.hpp | 13 +++++ host/include/uhd/dict.hpp | 8 +++ host/include/uhd/usrp/dboard_manager.hpp | 4 +- host/include/uhd/utils.hpp | 13 ++++- host/lib/device.cpp | 92 ++++++++++++++++---------------- host/lib/usrp/dboard/basic.cpp | 8 +-- host/lib/usrp/dboard_manager.cpp | 53 +++++++++--------- host/lib/usrp/usrp2/usrp2_impl.cpp | 5 +- 8 files changed, 117 insertions(+), 79 deletions(-) (limited to 'host/lib/device.cpp') diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 47dfa4328..c9d608bcf 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -37,6 +37,19 @@ class device : boost::noncopyable, public wax::obj{ public: typedef boost::shared_ptr sptr; + typedef boost::function discover_t; + typedef boost::function make_t; + + /*! + * Register a device into the discovery and factory system. + * + * \param discover a function that discovers devices + * \param make a factory function that makes a device + */ + static void register_device( + const discover_t &discover, + const make_t &make + ); /*! * \brief Discover usrp devices attached to the host. diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/dict.hpp index 1ed28551a..2224a0063 100644 --- a/host/include/uhd/dict.hpp +++ b/host/include/uhd/dict.hpp @@ -56,6 +56,14 @@ namespace uhd{ /* NOP */ } + /*! + * Get the number of elements in this dict. + * \param the number of elements + */ + std::size_t size(void) const{ + return _map.size(); + } + /*! * Get a list of the keys in this dict. * \return vector of keys diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index cf69675fc..0c32c6dba 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -40,14 +40,14 @@ public: typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t const&); /*! - * Register subdevices for a given dboard id. + * Register a dboard into the system. * * \param dboard_id the dboard id (rx or tx) * \param dboard_ctor the dboard constructor function pointer * \param name the canonical name for the dboard represented * \param subdev_names the names of the subdevs on this dboard */ - static void register_subdevs( + static void register_dboard( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 2f6e4fd87..995cb9926 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -23,10 +23,19 @@ #include #include +/*! + * Defines a function that implements the "construct on first use" idiom + * \param _t the type definition for the instance + * \param _x the name of the defined function + * \return a reference to the lazy instance + */ +#define STATIC_INSTANCE(_t, _x) static _t &_x(){static _t _x; return _x;} + /*! * Defines a static code block that will be called before main() + * \param _x the name of the defined struct (must be unique in file) */ -#define STATIC_BLOCK(_x) struct _x{_x();}_x;_x::_x() +#define STATIC_BLOCK(_x) static struct _x{_x();}_x;_x::_x() /*! * Useful templated functions and classes that I like to pretend are part of stl @@ -42,7 +51,7 @@ namespace std{ #define ASSERT_THROW(_x) if (not (_x)) { \ throw std::assert_error(str(boost::format( \ - "Assertion Failed:\n %s:%d\n %s\n __/ %s __/" \ + "Assertion Failed:\n %s:%d\n %s\n ---> %s <---" \ ) % __FILE__ % __LINE__ % BOOST_CURRENT_FUNCTION % std::string(#_x))); \ } diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 4b64e4a15..a87ba83eb 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -15,49 +15,22 @@ // asize_t with this program. If not, see . // -#include -#include +#include #include #include #include #include #include #include +#include #include #include 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_, 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"){ - return usrp::usrp1e::make(dev_addr); - } - - //create a usrp2 - if (dev_addr["type"] == "usrp2"){ - return usrp::usrp2::make(dev_addr); - } - - throw std::runtime_error(str( - boost::format("Cant make a device for %s") % device_addr::to_string(dev_addr) - )); -} - +/*********************************************************************** + * Helper Functions + **********************************************************************/ /*! * Make a device hash that maps 1 to 1 with a device address. * The hash will be used to identify created devices. @@ -80,20 +53,35 @@ static size_t hash_device_addr( return hash; } +/*********************************************************************** + * Registration + **********************************************************************/ +typedef boost::tuple dev_fcn_reg_t; + +// instantiate the device function registry container +STATIC_INSTANCE(std::vector, get_dev_fcn_regs) + +void device::register_device( + const discover_t &discover, + const make_t &make +){ + //std::cout << "registering device" << std::endl; + get_dev_fcn_regs().push_back(dev_fcn_reg_t(discover, make)); +} + /*********************************************************************** * Discover **********************************************************************/ device_addrs_t device::discover(const device_addr_t &hint){ device_addrs_t device_addrs; - //discover the usrp1es - std::vector usrp2_addrs = usrp::usrp1e::discover(hint); - device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); - - //discover the usrp2s - if (hint.has_key("addr")){ - std::vector usrp2_addrs = usrp::usrp2::discover(hint); - device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); + BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){ + device_addrs_t discovered_addrs = fcn.get<0>()(hint); + device_addrs.insert( + device_addrs.begin(), + discovered_addrs.begin(), + discovered_addrs.end() + ); } return device_addrs; @@ -103,24 +91,38 @@ device_addrs_t device::discover(const device_addr_t &hint){ * Make **********************************************************************/ device::sptr device::make(const device_addr_t &hint, size_t which){ - std::vector device_addrs = discover(hint); + typedef boost::tuple dev_addr_make_t; + std::vector dev_addr_makers; + + BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){ + BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){ + //copy keys that were in hint but not in dev_addr + //this way, we can pass additional transport arguments + BOOST_FOREACH(std::string key, hint.get_keys()){ + if (not dev_addr.has_key(key)) dev_addr[key] = hint[key]; + } + //append the discovered address and its factory function + dev_addr_makers.push_back(dev_addr_make_t(dev_addr, fcn.get<1>())); + } + } //check that we found any devices - if (device_addrs.size() == 0){ + if (dev_addr_makers.size() == 0){ throw std::runtime_error(str( boost::format("No devices found for %s") % device_addr::to_string(hint) )); } //check that the which index is valid - if (device_addrs.size() <= which){ + if (dev_addr_makers.size() <= which){ throw std::runtime_error(str( boost::format("No device at index %d for %s") % which % device_addr::to_string(hint) )); } //create a unique hash for the device address - device_addr_t dev_addr = device_addrs.at(which); + device_addr_t dev_addr; make_t maker; + boost::tie(dev_addr, maker) = dev_addr_makers.at(which); size_t dev_hash = hash_device_addr(dev_addr); //std::cout << boost::format("Hash: %u") % dev_hash << std::endl; @@ -135,7 +137,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, hint); + device::sptr dev = maker(dev_addr); hash_to_device[dev_hash] = dev; return dev; } diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 1059feb19..e719950e8 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -74,10 +74,10 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){ } 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")); + dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX", list_of("")); + dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab")); + dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX", list_of("")); + dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab")); } /*********************************************************************** diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 23c2921d2..eeabbda99 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -30,27 +30,30 @@ using namespace uhd::usrp; /*********************************************************************** * storage and registering for dboards **********************************************************************/ -typedef boost::tuple args_t; +//dboard registry tuple: dboard constructor, canonical name, subdev names +typedef boost::tuple args_t; //map a dboard id to a dboard constructor -static uhd::dict id_to_args_map; +typedef uhd::dict id_to_args_map_t; +STATIC_INSTANCE(id_to_args_map_t, get_id_to_args_map) -//map a dboard id to a canonical name -static uhd::dict id_to_str; - -void dboard_manager::register_subdevs( +void dboard_manager::register_dboard( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, 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); + if (get_id_to_args_map().has_key(dboard_id)){ + throw std::runtime_error(str(boost::format( + "The dboard id 0x%.4x is already registered to %s." + ) % dboard_id % dboard_id::to_string(dboard_id))); + } + get_id_to_args_map()[dboard_id] = args_t(dboard_ctor, name, subdev_names); } std::string dboard_id::to_string(const dboard_id_t &id){ - std::string name = (id_to_str.has_key(id))? id_to_str[id] : "unknown"; + std::string name = (get_id_to_args_map().has_key(id))? get_id_to_args_map()[id].get<1>() : "unknown"; return str(boost::format("%s (0x%.4x)") % name % id); } @@ -170,7 +173,7 @@ static args_t get_dboard_args( } //verify that there is a registered constructor for this id - if (not id_to_args_map.has_key(dboard_id)){ + if (not get_id_to_args_map().has_key(dboard_id)){ throw std::runtime_error(str( boost::format("Unregistered %s dboard id: %s") % xx_type % dboard_id::to_string(dboard_id) @@ -178,7 +181,7 @@ static args_t get_dboard_args( } //return the dboard args for this id - return id_to_args_map[dboard_id]; + return get_id_to_args_map()[dboard_id]; } dboard_manager_impl::dboard_manager_impl( @@ -188,11 +191,11 @@ dboard_manager_impl::dboard_manager_impl( ){ _interface = interface; - dboard_ctor_t rx_dboard_ctor; prop_names_t rx_subdevs; - boost::tie(rx_dboard_ctor, rx_subdevs) = get_dboard_args(rx_dboard_id, "rx"); + dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; + boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(rx_dboard_id, "rx"); - dboard_ctor_t tx_dboard_ctor; prop_names_t tx_subdevs; - boost::tie(tx_dboard_ctor, tx_subdevs) = get_dboard_args(tx_dboard_id, "tx"); + dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; + boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(tx_dboard_id, "tx"); //initialize the gpio pins before creating subdevs set_nice_gpio_pins(); @@ -200,16 +203,16 @@ dboard_manager_impl::dboard_manager_impl( //make xcvr subdevs (make one subdev for both rx and tx dboards) if (rx_dboard_ctor == tx_dboard_ctor){ ASSERT_THROW(rx_subdevs == tx_subdevs); - BOOST_FOREACH(std::string name, rx_subdevs){ + BOOST_FOREACH(std::string subdev, rx_subdevs){ dboard_base::sptr xcvr_dboard = rx_dboard_ctor( - dboard_base::ctor_args_t(name, interface, rx_dboard_id, tx_dboard_id) + dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, tx_dboard_id) ); //create a rx proxy for this xcvr board - _rx_dboards[name] = subdev_proxy::sptr( + _rx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(xcvr_dboard, subdev_proxy::RX_TYPE) ); //create a tx proxy for this xcvr board - _tx_dboards[name] = subdev_proxy::sptr( + _tx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(xcvr_dboard, subdev_proxy::TX_TYPE) ); } @@ -218,22 +221,22 @@ dboard_manager_impl::dboard_manager_impl( //make tx and rx subdevs (separate subdevs for rx and tx dboards) else{ //make the rx subdevs - BOOST_FOREACH(std::string name, rx_subdevs){ + BOOST_FOREACH(std::string subdev, rx_subdevs){ dboard_base::sptr rx_dboard = rx_dboard_ctor( - dboard_base::ctor_args_t(name, interface, rx_dboard_id, ID_NONE) + dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, ID_NONE) ); //create a rx proxy for this rx board - _rx_dboards[name] = subdev_proxy::sptr( + _rx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE) ); } //make the tx subdevs - BOOST_FOREACH(std::string name, tx_subdevs){ + BOOST_FOREACH(std::string subdev, tx_subdevs){ dboard_base::sptr tx_dboard = tx_dboard_ctor( - dboard_base::ctor_args_t(name, interface, ID_NONE, tx_dboard_id) + dboard_base::ctor_args_t(subdev, interface, ID_NONE, tx_dboard_id) ); //create a tx proxy for this tx board - _tx_dboards[name] = subdev_proxy::sptr( + _tx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(tx_dboard, subdev_proxy::TX_TYPE) ); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 58c82303f..850a738d4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -26,6 +26,10 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; +STATIC_BLOCK(register_device){ + device::register_device(&usrp2::discover, &usrp2::make); +} + /*********************************************************************** * Discovery over the udp transport **********************************************************************/ @@ -57,7 +61,6 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr)); device_addr_t new_addr; new_addr["name"] = "USRP2"; - new_addr["type"] = "usrp2"; new_addr["transport"] = "udp"; new_addr["addr"] = ip_addr.to_string(); usrp2_addrs.push_back(new_addr); -- cgit v1.2.3