2010-01-13 00:59:03 +00:00
|
|
|
//
|
|
|
|
|
// Copyright 2010 Ettus Research LLC
|
|
|
|
|
//
|
2010-01-30 00:40:23 +00:00
|
|
|
// 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/>.
|
|
|
|
|
//
|
2010-01-13 00:59:03 +00:00
|
|
|
|
|
|
|
|
#include <usrp_uhd/usrp/dboard/manager.hpp>
|
2010-01-26 19:29:14 +00:00
|
|
|
#include <usrp_uhd/utils.hpp>
|
|
|
|
|
#include <boost/assign/list_of.hpp>
|
2010-01-15 03:02:55 +00:00
|
|
|
#include <boost/format.hpp>
|
2010-01-26 19:29:14 +00:00
|
|
|
#include <boost/foreach.hpp>
|
2010-01-15 03:02:55 +00:00
|
|
|
#include "dboards.hpp"
|
2010-01-13 00:59:03 +00:00
|
|
|
|
2010-01-26 19:29:14 +00:00
|
|
|
using namespace usrp_uhd;
|
2010-01-13 00:59:03 +00:00
|
|
|
using namespace usrp_uhd::usrp::dboard;
|
2010-01-29 08:24:15 +00:00
|
|
|
using namespace boost::assign;
|
2010-01-13 00:59:03 +00:00
|
|
|
|
2010-01-15 03:02:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
|
* register internal dboards
|
|
|
|
|
*
|
|
|
|
|
* Register internal/known dboards located in this build tree.
|
|
|
|
|
* Each board should have entries below mapping an id to a constructor.
|
|
|
|
|
* The xcvr type boards should register both rx and tx sides.
|
|
|
|
|
*
|
|
|
|
|
* This function will be called before new boards are registered.
|
|
|
|
|
* This allows for internal boards to be externally overridden.
|
|
|
|
|
* This function will also be called when creating a new manager
|
|
|
|
|
* to ensure that the maps are filled with the entries below.
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
static void register_internal_dboards(void){
|
|
|
|
|
//ensure that this function can only be called once per instance
|
|
|
|
|
static bool called = false;
|
|
|
|
|
if (called) return; called = true;
|
2010-01-29 08:24:15 +00:00
|
|
|
//register the known dboards (dboard id, constructor, subdev names)
|
|
|
|
|
manager::register_subdevs(ID_BASIC_TX, &basic_tx::make, list_of(""));
|
|
|
|
|
manager::register_subdevs(ID_BASIC_RX, &basic_rx::make, list_of("a")("b")("ab"));
|
2010-01-15 03:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
|
* storage and registering for dboards
|
|
|
|
|
**********************************************************************/
|
2010-01-15 23:45:33 +00:00
|
|
|
//map a dboard id to a dboard constructor
|
2010-01-29 08:24:15 +00:00
|
|
|
static std::map<dboard_id_t, manager::dboard_ctor_t> id_to_ctor_map;
|
2010-01-15 03:02:55 +00:00
|
|
|
|
2010-01-26 19:29:14 +00:00
|
|
|
//map a dboard constructor to subdevice names
|
|
|
|
|
static std::map<manager::dboard_ctor_t, prop_names_t> ctor_to_names_map;
|
2010-01-15 03:02:55 +00:00
|
|
|
|
2010-01-15 23:45:33 +00:00
|
|
|
void manager::register_subdevs(
|
|
|
|
|
dboard_id_t dboard_id,
|
|
|
|
|
dboard_ctor_t dboard_ctor,
|
2010-01-26 19:29:14 +00:00
|
|
|
const prop_names_t &subdev_names
|
2010-01-15 03:02:55 +00:00
|
|
|
){
|
|
|
|
|
register_internal_dboards(); //always call first
|
2010-01-15 23:45:33 +00:00
|
|
|
id_to_ctor_map[dboard_id] = dboard_ctor;
|
2010-01-26 19:29:14 +00:00
|
|
|
ctor_to_names_map[dboard_ctor] = subdev_names;
|
2010-01-15 03:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-13 00:59:03 +00:00
|
|
|
/***********************************************************************
|
|
|
|
|
* internal helper classes
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
/*!
|
|
|
|
|
* A special wax proxy object that forwards calls to a subdev.
|
|
|
|
|
* A sptr to an instance will be used in the properties structure.
|
|
|
|
|
*/
|
|
|
|
|
class subdev_proxy : boost::noncopyable, public wax::obj{
|
|
|
|
|
public:
|
|
|
|
|
typedef boost::shared_ptr<subdev_proxy> sptr;
|
|
|
|
|
enum type_t{RX_TYPE, TX_TYPE};
|
|
|
|
|
|
|
|
|
|
//structors
|
2010-01-15 23:45:33 +00:00
|
|
|
subdev_proxy(base::sptr subdev, type_t type)
|
2010-01-13 01:31:25 +00:00
|
|
|
: _subdev(subdev), _type(type){
|
2010-01-13 00:59:03 +00:00
|
|
|
/* NOP */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~subdev_proxy(void){
|
|
|
|
|
/* NOP */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2010-01-15 23:45:33 +00:00
|
|
|
base::sptr _subdev;
|
|
|
|
|
type_t _type;
|
2010-01-13 00:59:03 +00:00
|
|
|
|
|
|
|
|
//forward the get calls to the rx or tx
|
2010-02-01 20:35:34 +00:00
|
|
|
void get(const wax::obj &key, wax::obj &val){
|
2010-01-13 00:59:03 +00:00
|
|
|
switch(_type){
|
2010-01-13 01:31:25 +00:00
|
|
|
case RX_TYPE: return _subdev->rx_get(key, val);
|
|
|
|
|
case TX_TYPE: return _subdev->tx_get(key, val);
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//forward the set calls to the rx or tx
|
2010-02-01 20:35:34 +00:00
|
|
|
void set(const wax::obj &key, const wax::obj &val){
|
2010-01-13 00:59:03 +00:00
|
|
|
switch(_type){
|
2010-01-13 01:31:25 +00:00
|
|
|
case RX_TYPE: return _subdev->rx_set(key, val);
|
|
|
|
|
case TX_TYPE: return _subdev->tx_set(key, val);
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
|
* dboard manager methods
|
|
|
|
|
**********************************************************************/
|
2010-01-15 23:45:33 +00:00
|
|
|
static manager::dboard_ctor_t const& get_dboard_ctor(
|
2010-01-29 08:24:15 +00:00
|
|
|
dboard_id_t dboard_id,
|
2010-01-15 03:02:55 +00:00
|
|
|
std::string const& xx_type
|
|
|
|
|
){
|
|
|
|
|
//verify that there is a registered constructor for this id
|
2010-01-15 23:45:33 +00:00
|
|
|
if (id_to_ctor_map.count(dboard_id) == 0){
|
2010-01-15 03:02:55 +00:00
|
|
|
throw std::runtime_error(str(
|
|
|
|
|
boost::format("Unknown %s dboard id: 0x%04x") % xx_type % dboard_id
|
|
|
|
|
));
|
|
|
|
|
}
|
2010-01-15 23:45:33 +00:00
|
|
|
//return the dboard constructor for this id
|
|
|
|
|
return id_to_ctor_map[dboard_id];
|
2010-01-15 03:02:55 +00:00
|
|
|
}
|
2010-01-13 00:59:03 +00:00
|
|
|
|
|
|
|
|
manager::manager(
|
2010-01-15 03:02:55 +00:00
|
|
|
dboard_id_t rx_dboard_id,
|
|
|
|
|
dboard_id_t tx_dboard_id,
|
2010-01-13 00:59:03 +00:00
|
|
|
interface::sptr dboard_interface
|
|
|
|
|
){
|
2010-01-15 03:02:55 +00:00
|
|
|
register_internal_dboards(); //always call first
|
2010-01-15 23:45:33 +00:00
|
|
|
const dboard_ctor_t rx_dboard_ctor = get_dboard_ctor(rx_dboard_id, "rx");
|
|
|
|
|
const dboard_ctor_t tx_dboard_ctor = get_dboard_ctor(tx_dboard_id, "tx");
|
|
|
|
|
//make xcvr subdevs (make one subdev for both rx and tx dboards)
|
|
|
|
|
if (rx_dboard_ctor == tx_dboard_ctor){
|
2010-01-26 19:29:14 +00:00
|
|
|
BOOST_FOREACH(std::string name, ctor_to_names_map[rx_dboard_ctor]){
|
2010-01-15 23:45:33 +00:00
|
|
|
base::sptr xcvr_dboard = rx_dboard_ctor(
|
2010-01-26 19:29:14 +00:00
|
|
|
base::ctor_args_t(name, dboard_interface)
|
2010-01-15 23:45:33 +00:00
|
|
|
);
|
2010-02-05 19:36:17 +00:00
|
|
|
//create a rx proxy for this xcvr board
|
|
|
|
|
_rx_dboards[name] = 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(
|
|
|
|
|
new subdev_proxy(xcvr_dboard, subdev_proxy::TX_TYPE)
|
|
|
|
|
);
|
2010-01-15 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//make tx and rx subdevs (separate subdevs for rx and tx dboards)
|
|
|
|
|
else{
|
|
|
|
|
//make the rx subdevs
|
2010-01-26 19:29:14 +00:00
|
|
|
BOOST_FOREACH(std::string name, ctor_to_names_map[rx_dboard_ctor]){
|
2010-02-05 19:36:17 +00:00
|
|
|
base::sptr rx_dboard = rx_dboard_ctor(
|
2010-01-26 19:29:14 +00:00
|
|
|
base::ctor_args_t(name, dboard_interface)
|
|
|
|
|
);
|
2010-02-05 19:36:17 +00:00
|
|
|
//create a rx proxy for this rx board
|
|
|
|
|
_rx_dboards[name] = subdev_proxy::sptr(
|
|
|
|
|
new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE)
|
|
|
|
|
);
|
2010-01-15 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
//make the tx subdevs
|
2010-01-26 19:29:14 +00:00
|
|
|
BOOST_FOREACH(std::string name, ctor_to_names_map[tx_dboard_ctor]){
|
2010-02-05 19:36:17 +00:00
|
|
|
base::sptr tx_dboard = tx_dboard_ctor(
|
2010-01-26 19:29:14 +00:00
|
|
|
base::ctor_args_t(name, dboard_interface)
|
|
|
|
|
);
|
2010-02-05 19:36:17 +00:00
|
|
|
//create a tx proxy for this tx board
|
|
|
|
|
_tx_dboards[name] = subdev_proxy::sptr(
|
|
|
|
|
new subdev_proxy(tx_dboard, subdev_proxy::TX_TYPE)
|
|
|
|
|
);
|
2010-01-15 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
manager::~manager(void){
|
|
|
|
|
/* NOP */
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-26 19:29:14 +00:00
|
|
|
prop_names_t manager::get_rx_subdev_names(void){
|
|
|
|
|
return get_map_keys(_rx_dboards);
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-26 19:29:14 +00:00
|
|
|
prop_names_t manager::get_tx_subdev_names(void){
|
|
|
|
|
return get_map_keys(_tx_dboards);
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2010-02-05 19:36:17 +00:00
|
|
|
wax::obj manager::get_rx_subdev(const std::string &subdev_name){
|
2010-01-26 19:29:14 +00:00
|
|
|
if (_rx_dboards.count(subdev_name) == 0) throw std::invalid_argument(
|
|
|
|
|
str(boost::format("Unknown rx subdev name %s") % subdev_name)
|
|
|
|
|
);
|
2010-02-05 19:36:17 +00:00
|
|
|
//get a link to the rx subdev proxy
|
|
|
|
|
return wax::cast<subdev_proxy::sptr>(_rx_dboards[subdev_name])->get_link();
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2010-02-05 19:36:17 +00:00
|
|
|
wax::obj manager::get_tx_subdev(const std::string &subdev_name){
|
2010-01-26 19:29:14 +00:00
|
|
|
if (_tx_dboards.count(subdev_name) == 0) throw std::invalid_argument(
|
|
|
|
|
str(boost::format("Unknown tx subdev name %s") % subdev_name)
|
|
|
|
|
);
|
2010-02-05 19:36:17 +00:00
|
|
|
//get a link to the tx subdev proxy
|
|
|
|
|
return wax::cast<subdev_proxy::sptr>(_tx_dboards[subdev_name])->get_link();
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|