2010-01-13 00:59:03 +00:00
|
|
|
//
|
2011-02-22 19:55:54 +00:00
|
|
|
// Copyright 2010-2011 Ettus Research LLC
|
2010-01-13 00:59:03 +00:00
|
|
|
//
|
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
|
|
|
|
2010-05-02 23:03:46 +00:00
|
|
|
#include "dboard_ctor_args.hpp"
|
2010-02-21 20:59:41 +00:00
|
|
|
#include <uhd/usrp/dboard_manager.hpp>
|
2011-05-05 01:36:10 +00:00
|
|
|
#include <uhd/utils/msg.hpp>
|
2011-05-04 22:27:11 +00:00
|
|
|
#include <uhd/utils/log.hpp>
|
2011-06-10 20:11:22 +00:00
|
|
|
#include <uhd/utils/safe_call.hpp>
|
2010-03-27 08:02:58 +00:00
|
|
|
#include <uhd/utils/static.hpp>
|
2011-02-24 22:54:24 +00:00
|
|
|
#include <uhd/exception.hpp>
|
2010-03-27 21:27:55 +00:00
|
|
|
#include <uhd/types/dict.hpp>
|
2010-02-19 01:48:14 +00:00
|
|
|
#include <boost/tuple/tuple.hpp>
|
2010-01-15 03:02:55 +00:00
|
|
|
#include <boost/format.hpp>
|
2010-03-12 02:37:34 +00:00
|
|
|
#include <boost/bind.hpp>
|
2010-01-26 19:29:14 +00:00
|
|
|
#include <boost/foreach.hpp>
|
2010-04-13 02:37:38 +00:00
|
|
|
#include <boost/assign/list_of.hpp>
|
2010-01-13 00:59:03 +00:00
|
|
|
|
2010-02-10 00:28:16 +00:00
|
|
|
using namespace uhd;
|
2010-02-21 20:59:41 +00:00
|
|
|
using namespace uhd::usrp;
|
2010-01-15 03:02:55 +00:00
|
|
|
|
2011-04-24 03:03:57 +00:00
|
|
|
/***********************************************************************
|
|
|
|
|
* dboard key class to use for look-up
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
class dboard_key_t{
|
|
|
|
|
public:
|
|
|
|
|
dboard_key_t(const dboard_id_t &id = dboard_id_t::none()):
|
|
|
|
|
_rx_id(id), _tx_id(id), _xcvr(false){}
|
|
|
|
|
|
|
|
|
|
dboard_key_t(const dboard_id_t &rx_id, const dboard_id_t &tx_id):
|
|
|
|
|
_rx_id(rx_id), _tx_id(tx_id), _xcvr(true){}
|
|
|
|
|
|
|
|
|
|
dboard_id_t xx_id(void) const{
|
|
|
|
|
UHD_ASSERT_THROW(not this->is_xcvr());
|
|
|
|
|
return this->_rx_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dboard_id_t rx_id(void) const{
|
|
|
|
|
UHD_ASSERT_THROW(this->is_xcvr());
|
|
|
|
|
return this->_rx_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dboard_id_t tx_id(void) const{
|
|
|
|
|
UHD_ASSERT_THROW(this->is_xcvr());
|
|
|
|
|
return this->_tx_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool is_xcvr(void) const{
|
|
|
|
|
return this->_xcvr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
dboard_id_t _rx_id, _tx_id;
|
|
|
|
|
bool _xcvr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool operator==(const dboard_key_t &lhs, const dboard_key_t &rhs){
|
|
|
|
|
if (lhs.is_xcvr() and rhs.is_xcvr())
|
|
|
|
|
return lhs.rx_id() == rhs.rx_id() and lhs.tx_id() == rhs.tx_id();
|
|
|
|
|
if (not lhs.is_xcvr() and not rhs.is_xcvr())
|
|
|
|
|
return lhs.xx_id() == rhs.xx_id();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-15 03:02:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
|
* storage and registering for dboards
|
|
|
|
|
**********************************************************************/
|
2010-03-15 19:15:33 +00:00
|
|
|
//dboard registry tuple: dboard constructor, canonical name, subdev names
|
|
|
|
|
typedef boost::tuple<dboard_manager::dboard_ctor_t, std::string, prop_names_t> args_t;
|
2010-01-15 03:02:55 +00:00
|
|
|
|
2010-02-19 01:48:14 +00:00
|
|
|
//map a dboard id to a dboard constructor
|
2011-04-24 03:03:57 +00:00
|
|
|
typedef uhd::dict<dboard_key_t, args_t> id_to_args_map_t;
|
2010-03-27 08:02:58 +00:00
|
|
|
UHD_SINGLETON_FCN(id_to_args_map_t, get_id_to_args_map)
|
2010-01-15 03:02:55 +00:00
|
|
|
|
2011-04-24 03:03:57 +00:00
|
|
|
static void register_dboard_key(
|
|
|
|
|
const dboard_key_t &dboard_key,
|
|
|
|
|
dboard_manager::dboard_ctor_t dboard_ctor,
|
2010-03-11 03:33:38 +00:00
|
|
|
const std::string &name,
|
2010-01-26 19:29:14 +00:00
|
|
|
const prop_names_t &subdev_names
|
2010-01-15 03:02:55 +00:00
|
|
|
){
|
2011-05-04 22:27:11 +00:00
|
|
|
UHD_LOGV(always) << "registering: " << name << std::endl;
|
2011-04-24 03:03:57 +00:00
|
|
|
if (get_id_to_args_map().has_key(dboard_key)){
|
|
|
|
|
|
|
|
|
|
if (dboard_key.is_xcvr()) throw uhd::key_error(str(boost::format(
|
|
|
|
|
"The dboard id pair [%s, %s] is already registered to %s."
|
|
|
|
|
) % dboard_key.rx_id().to_string() % dboard_key.tx_id().to_string() % get_id_to_args_map()[dboard_key].get<1>()));
|
|
|
|
|
|
|
|
|
|
else throw uhd::key_error(str(boost::format(
|
2010-05-03 08:20:11 +00:00
|
|
|
"The dboard id %s is already registered to %s."
|
2011-04-24 03:03:57 +00:00
|
|
|
) % dboard_key.xx_id().to_string() % get_id_to_args_map()[dboard_key].get<1>()));
|
|
|
|
|
|
2010-03-15 19:15:33 +00:00
|
|
|
}
|
2011-04-24 03:03:57 +00:00
|
|
|
get_id_to_args_map()[dboard_key] = args_t(dboard_ctor, name, subdev_names);
|
2010-01-15 03:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-24 03:03:57 +00:00
|
|
|
void dboard_manager::register_dboard(
|
|
|
|
|
const dboard_id_t &dboard_id,
|
|
|
|
|
dboard_ctor_t dboard_ctor,
|
|
|
|
|
const std::string &name,
|
|
|
|
|
const prop_names_t &subdev_names
|
|
|
|
|
){
|
|
|
|
|
register_dboard_key(dboard_key_t(dboard_id), dboard_ctor, name, subdev_names);
|
|
|
|
|
}
|
2010-06-19 00:20:46 +00:00
|
|
|
|
2010-06-18 23:39:45 +00:00
|
|
|
void dboard_manager::register_dboard(
|
|
|
|
|
const dboard_id_t &rx_dboard_id,
|
|
|
|
|
const dboard_id_t &tx_dboard_id,
|
|
|
|
|
dboard_ctor_t dboard_ctor,
|
|
|
|
|
const std::string &name,
|
|
|
|
|
const prop_names_t &subdev_names
|
|
|
|
|
){
|
2011-04-24 03:03:57 +00:00
|
|
|
register_dboard_key(dboard_key_t(rx_dboard_id, tx_dboard_id), dboard_ctor, name, subdev_names);
|
2010-06-18 23:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
2010-10-21 00:41:59 +00:00
|
|
|
std::string dboard_id_t::to_cname(void) const{
|
2011-04-24 03:03:57 +00:00
|
|
|
std::string cname;
|
|
|
|
|
BOOST_FOREACH(const dboard_key_t &key, get_id_to_args_map().keys()){
|
|
|
|
|
if (
|
|
|
|
|
(not key.is_xcvr() and *this == key.xx_id()) or
|
|
|
|
|
(key.is_xcvr() and (*this == key.rx_id() or *this == key.tx_id()))
|
|
|
|
|
){
|
|
|
|
|
if (not cname.empty()) cname += ", ";
|
|
|
|
|
cname += get_id_to_args_map()[key].get<1>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (cname.empty())? "Unknown" : cname;
|
2010-10-21 00:41:59 +00:00
|
|
|
}
|
|
|
|
|
|
2010-05-03 08:20:11 +00:00
|
|
|
std::string dboard_id_t::to_pp_string(void) const{
|
2010-10-21 00:41:59 +00:00
|
|
|
return str(boost::format("%s (%s)") % this->to_cname() % this->to_string());
|
2010-03-11 03:33:38 +00:00
|
|
|
}
|
|
|
|
|
|
2010-02-22 08:37:53 +00:00
|
|
|
/***********************************************************************
|
2010-09-30 18:05:33 +00:00
|
|
|
* internal helper classes
|
2010-01-13 00:59:03 +00:00
|
|
|
**********************************************************************/
|
|
|
|
|
/*!
|
|
|
|
|
* 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-07-24 07:11:44 +00:00
|
|
|
subdev_proxy(dboard_base::sptr subdev, type_t type):
|
|
|
|
|
_subdev(subdev), _type(type)
|
|
|
|
|
{
|
2010-01-13 00:59:03 +00:00
|
|
|
/* NOP */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2010-02-21 20:59:41 +00:00
|
|
|
dboard_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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2010-03-12 02:37:34 +00:00
|
|
|
/***********************************************************************
|
|
|
|
|
* 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,
|
2010-04-14 15:41:13 +00:00
|
|
|
dboard_iface::sptr iface
|
2010-03-12 02:37:34 +00:00
|
|
|
);
|
|
|
|
|
~dboard_manager_impl(void);
|
|
|
|
|
|
2010-04-14 15:41:13 +00:00
|
|
|
//dboard_iface
|
2010-03-12 02:37:34 +00:00
|
|
|
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:
|
2011-02-22 19:55:54 +00:00
|
|
|
void init(dboard_id_t, dboard_id_t);
|
2010-03-12 02:37:34 +00:00
|
|
|
//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;
|
2010-04-14 15:41:13 +00:00
|
|
|
dboard_iface::sptr _iface;
|
2010-04-13 02:37:38 +00:00
|
|
|
void set_nice_dboard_if(void);
|
2010-03-12 02:37:34 +00:00
|
|
|
};
|
|
|
|
|
|
2010-01-13 00:59:03 +00:00
|
|
|
/***********************************************************************
|
2010-02-22 08:37:53 +00:00
|
|
|
* make routine for dboard manager
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
dboard_manager::sptr dboard_manager::make(
|
|
|
|
|
dboard_id_t rx_dboard_id,
|
|
|
|
|
dboard_id_t tx_dboard_id,
|
2010-04-14 15:41:13 +00:00
|
|
|
dboard_iface::sptr iface
|
2010-02-22 08:37:53 +00:00
|
|
|
){
|
|
|
|
|
return dboard_manager::sptr(
|
2010-04-14 15:41:13 +00:00
|
|
|
new dboard_manager_impl(rx_dboard_id, tx_dboard_id, iface)
|
2010-02-22 08:37:53 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
|
* implementation class methods
|
2010-01-13 00:59:03 +00:00
|
|
|
**********************************************************************/
|
2010-02-22 08:37:53 +00:00
|
|
|
dboard_manager_impl::dboard_manager_impl(
|
2010-01-15 03:02:55 +00:00
|
|
|
dboard_id_t rx_dboard_id,
|
|
|
|
|
dboard_id_t tx_dboard_id,
|
2010-04-14 15:41:13 +00:00
|
|
|
dboard_iface::sptr iface
|
2011-02-22 19:55:54 +00:00
|
|
|
):
|
|
|
|
|
_iface(iface)
|
|
|
|
|
{
|
|
|
|
|
try{
|
|
|
|
|
this->init(rx_dboard_id, tx_dboard_id);
|
|
|
|
|
}
|
|
|
|
|
catch(const std::exception &e){
|
2011-05-05 01:36:10 +00:00
|
|
|
UHD_MSG(error) << "The daughterboard manager encountered a recoverable error in init" << std::endl << e.what();
|
2011-02-22 19:55:54 +00:00
|
|
|
this->init(dboard_id_t::none(), dboard_id_t::none());
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-19 01:48:14 +00:00
|
|
|
|
2011-02-22 19:55:54 +00:00
|
|
|
void dboard_manager_impl::init(
|
|
|
|
|
dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id
|
|
|
|
|
){
|
2011-04-24 03:03:57 +00:00
|
|
|
//find the dboard key matches for the dboard ids
|
|
|
|
|
dboard_key_t rx_dboard_key, tx_dboard_key, xcvr_dboard_key;
|
|
|
|
|
BOOST_FOREACH(const dboard_key_t &key, get_id_to_args_map().keys()){
|
|
|
|
|
if (key.is_xcvr()){
|
|
|
|
|
if (rx_dboard_id == key.rx_id() and tx_dboard_id == key.tx_id()) xcvr_dboard_key = key;
|
|
|
|
|
if (rx_dboard_id == key.rx_id()) rx_dboard_key = key; //kept to handle warning
|
|
|
|
|
if (tx_dboard_id == key.tx_id()) tx_dboard_key = key; //kept to handle warning
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
if (rx_dboard_id == key.xx_id()) rx_dboard_key = key;
|
|
|
|
|
if (tx_dboard_id == key.xx_id()) tx_dboard_key = key;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-19 00:20:46 +00:00
|
|
|
|
2010-09-28 17:21:11 +00:00
|
|
|
//warn for invalid dboard id xcvr combinations
|
2011-04-24 03:03:57 +00:00
|
|
|
if (not xcvr_dboard_key.is_xcvr() and (rx_dboard_key.is_xcvr() or tx_dboard_key.is_xcvr())){
|
2011-05-05 01:36:10 +00:00
|
|
|
UHD_MSG(warning) << boost::format(
|
2011-04-24 03:03:57 +00:00
|
|
|
"Unknown transceiver board ID combination.\n"
|
|
|
|
|
"Is your daughter-board mounted properly?\n"
|
2010-09-28 17:21:11 +00:00
|
|
|
"RX dboard ID: %s\n"
|
|
|
|
|
"TX dboard ID: %s\n"
|
2011-05-05 01:36:10 +00:00
|
|
|
) % rx_dboard_id.to_pp_string() % tx_dboard_id.to_pp_string();
|
2010-09-28 17:21:11 +00:00
|
|
|
}
|
|
|
|
|
|
2010-02-18 00:23:12 +00:00
|
|
|
//initialize the gpio pins before creating subdevs
|
2010-04-13 02:37:38 +00:00
|
|
|
set_nice_dboard_if();
|
2010-02-18 00:23:12 +00:00
|
|
|
|
2010-05-02 23:03:46 +00:00
|
|
|
//dboard constructor args
|
2010-07-22 17:26:48 +00:00
|
|
|
dboard_ctor_args_t db_ctor_args;
|
2011-02-22 19:55:54 +00:00
|
|
|
db_ctor_args.db_iface = _iface;
|
2010-05-02 23:03:46 +00:00
|
|
|
|
2011-04-24 03:03:57 +00:00
|
|
|
//make xcvr subdevs
|
|
|
|
|
if (xcvr_dboard_key.is_xcvr()){
|
|
|
|
|
|
|
|
|
|
//extract data for the xcvr dboard key
|
|
|
|
|
dboard_ctor_t dboard_ctor; std::string name; prop_names_t subdevs;
|
|
|
|
|
boost::tie(dboard_ctor, name, subdevs) = get_id_to_args_map()[xcvr_dboard_key];
|
|
|
|
|
|
|
|
|
|
//create the xcvr object for each subdevice
|
|
|
|
|
BOOST_FOREACH(const std::string &subdev, subdevs){
|
2010-05-02 23:03:46 +00:00
|
|
|
db_ctor_args.sd_name = subdev;
|
2010-05-03 18:03:59 +00:00
|
|
|
db_ctor_args.rx_id = rx_dboard_id;
|
|
|
|
|
db_ctor_args.tx_id = tx_dboard_id;
|
2011-04-24 03:03:57 +00:00
|
|
|
dboard_base::sptr xcvr_dboard = dboard_ctor(&db_ctor_args);
|
2010-02-05 19:36:17 +00:00
|
|
|
//create a rx proxy for this xcvr board
|
2010-03-15 19:15:33 +00:00
|
|
|
_rx_dboards[subdev] = subdev_proxy::sptr(
|
2010-02-05 19:36:17 +00:00
|
|
|
new subdev_proxy(xcvr_dboard, subdev_proxy::RX_TYPE)
|
|
|
|
|
);
|
|
|
|
|
//create a tx proxy for this xcvr board
|
2010-03-15 19:15:33 +00:00
|
|
|
_tx_dboards[subdev] = subdev_proxy::sptr(
|
2010-02-05 19:36:17 +00:00
|
|
|
new subdev_proxy(xcvr_dboard, subdev_proxy::TX_TYPE)
|
|
|
|
|
);
|
2010-01-15 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-02-18 00:23:12 +00:00
|
|
|
|
2010-01-15 23:45:33 +00:00
|
|
|
//make tx and rx subdevs (separate subdevs for rx and tx dboards)
|
|
|
|
|
else{
|
2011-04-24 03:03:57 +00:00
|
|
|
|
|
|
|
|
//force the rx key to the unknown board for bad combinations
|
|
|
|
|
if (rx_dboard_key.is_xcvr() or rx_dboard_key.xx_id() == dboard_id_t::none()){
|
|
|
|
|
rx_dboard_key = dboard_key_t(0xfff1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//extract data for the rx dboard key
|
|
|
|
|
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_id_to_args_map()[rx_dboard_key];
|
|
|
|
|
|
2010-01-15 23:45:33 +00:00
|
|
|
//make the rx subdevs
|
2010-03-29 19:58:06 +00:00
|
|
|
BOOST_FOREACH(const std::string &subdev, rx_subdevs){
|
2010-05-02 23:03:46 +00:00
|
|
|
db_ctor_args.sd_name = subdev;
|
2010-05-03 18:03:59 +00:00
|
|
|
db_ctor_args.rx_id = rx_dboard_id;
|
2010-05-03 08:20:11 +00:00
|
|
|
db_ctor_args.tx_id = dboard_id_t::none();
|
2010-05-02 23:03:46 +00:00
|
|
|
dboard_base::sptr rx_dboard = rx_dboard_ctor(&db_ctor_args);
|
2010-02-05 19:36:17 +00:00
|
|
|
//create a rx proxy for this rx board
|
2010-03-15 19:15:33 +00:00
|
|
|
_rx_dboards[subdev] = subdev_proxy::sptr(
|
2010-02-05 19:36:17 +00:00
|
|
|
new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE)
|
|
|
|
|
);
|
2010-01-15 23:45:33 +00:00
|
|
|
}
|
2011-04-24 03:03:57 +00:00
|
|
|
|
|
|
|
|
//force the tx key to the unknown board for bad combinations
|
|
|
|
|
if (tx_dboard_key.is_xcvr() or tx_dboard_key.xx_id() == dboard_id_t::none()){
|
|
|
|
|
tx_dboard_key = dboard_key_t(0xfff0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//extract data for the tx dboard key
|
|
|
|
|
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_id_to_args_map()[tx_dboard_key];
|
|
|
|
|
|
2010-01-15 23:45:33 +00:00
|
|
|
//make the tx subdevs
|
2010-03-29 19:58:06 +00:00
|
|
|
BOOST_FOREACH(const std::string &subdev, tx_subdevs){
|
2010-05-02 23:03:46 +00:00
|
|
|
db_ctor_args.sd_name = subdev;
|
2010-05-03 08:20:11 +00:00
|
|
|
db_ctor_args.rx_id = dboard_id_t::none();
|
2010-05-03 18:03:59 +00:00
|
|
|
db_ctor_args.tx_id = tx_dboard_id;
|
2010-05-02 23:03:46 +00:00
|
|
|
dboard_base::sptr tx_dboard = tx_dboard_ctor(&db_ctor_args);
|
2010-02-05 19:36:17 +00:00
|
|
|
//create a tx proxy for this tx board
|
2010-03-15 19:15:33 +00:00
|
|
|
_tx_dboards[subdev] = subdev_proxy::sptr(
|
2010-02-05 19:36:17 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2011-06-10 22:23:24 +00:00
|
|
|
dboard_manager_impl::~dboard_manager_impl(void){UHD_SAFE_CALL(
|
|
|
|
|
set_nice_dboard_if();
|
|
|
|
|
)}
|
2010-01-13 00:59:03 +00:00
|
|
|
|
2010-02-22 08:37:53 +00:00
|
|
|
prop_names_t dboard_manager_impl::get_rx_subdev_names(void){
|
2010-04-06 01:11:32 +00:00
|
|
|
return _rx_dboards.keys();
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2010-02-22 08:37:53 +00:00
|
|
|
prop_names_t dboard_manager_impl::get_tx_subdev_names(void){
|
2010-04-06 01:11:32 +00:00
|
|
|
return _tx_dboards.keys();
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2010-02-22 08:37:53 +00:00
|
|
|
wax::obj dboard_manager_impl::get_rx_subdev(const std::string &subdev_name){
|
2011-02-25 00:35:29 +00:00
|
|
|
if (not _rx_dboards.has_key(subdev_name)) throw uhd::key_error(
|
2010-01-26 19:29:14 +00:00
|
|
|
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
|
2010-03-12 02:37:34 +00:00
|
|
|
return _rx_dboards[subdev_name]->get_link();
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2010-02-22 08:37:53 +00:00
|
|
|
wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){
|
2011-02-25 00:35:29 +00:00
|
|
|
if (not _tx_dboards.has_key(subdev_name)) throw uhd::key_error(
|
2010-01-26 19:29:14 +00:00
|
|
|
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
|
2010-03-12 02:37:34 +00:00
|
|
|
return _tx_dboards[subdev_name]->get_link();
|
2010-01-13 00:59:03 +00:00
|
|
|
}
|
2010-02-22 22:36:48 +00:00
|
|
|
|
2010-04-13 02:37:38 +00:00
|
|
|
void dboard_manager_impl::set_nice_dboard_if(void){
|
|
|
|
|
//make a list of possible unit types
|
2010-04-14 15:41:13 +00:00
|
|
|
std::vector<dboard_iface::unit_t> units = boost::assign::list_of
|
|
|
|
|
(dboard_iface::UNIT_RX)
|
|
|
|
|
(dboard_iface::UNIT_TX)
|
2010-04-13 02:37:38 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
//set nice settings on each unit
|
2010-04-14 15:41:13 +00:00
|
|
|
BOOST_FOREACH(dboard_iface::unit_t unit, units){
|
|
|
|
|
_iface->set_gpio_ddr(unit, 0x0000); //all inputs
|
2010-11-27 04:27:53 +00:00
|
|
|
_iface->set_gpio_out(unit, 0x0000); //all low
|
2010-05-24 23:31:23 +00:00
|
|
|
_iface->set_pin_ctrl(unit, 0x0000); //all gpio
|
2010-04-14 15:41:13 +00:00
|
|
|
_iface->set_clock_enabled(unit, false); //clock off
|
2010-04-13 02:37:38 +00:00
|
|
|
}
|
2010-09-30 18:05:33 +00:00
|
|
|
|
|
|
|
|
//disable all rx subdevices
|
|
|
|
|
BOOST_FOREACH(const std::string &sd_name, this->get_rx_subdev_names()){
|
|
|
|
|
this->get_rx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//disable all tx subdevices
|
|
|
|
|
BOOST_FOREACH(const std::string &sd_name, this->get_tx_subdev_names()){
|
|
|
|
|
this->get_tx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false;
|
|
|
|
|
}
|
2010-02-22 22:36:48 +00:00
|
|
|
}
|
2011-06-28 03:26:52 +00:00
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
|
* Populate a properties tree from a subdev waxy object
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
#include <uhd/types/ranges.hpp>
|
|
|
|
|
#include <uhd/types/sensors.hpp>
|
|
|
|
|
|
|
|
|
|
static sensor_value_t get_sensor(wax::obj subdev, const std::string &name){
|
|
|
|
|
return subdev[named_prop_t(SUBDEV_PROP_SENSOR, name)].as<sensor_value_t>();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-29 19:20:19 +00:00
|
|
|
static void set_gain(wax::obj subdev, const std::string &name, const double gain){
|
2011-06-28 03:26:52 +00:00
|
|
|
subdev[named_prop_t(SUBDEV_PROP_GAIN, name)] = gain;
|
2011-06-29 19:20:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double get_gain(wax::obj subdev, const std::string &name){
|
2011-06-28 03:26:52 +00:00
|
|
|
return subdev[named_prop_t(SUBDEV_PROP_GAIN, name)].as<double>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static meta_range_t get_gain_range(wax::obj subdev, const std::string &name){
|
|
|
|
|
return subdev[named_prop_t(SUBDEV_PROP_GAIN_RANGE, name)].as<meta_range_t>();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-29 19:20:19 +00:00
|
|
|
static void set_freq(wax::obj subdev, const double freq){
|
2011-06-28 03:26:52 +00:00
|
|
|
subdev[SUBDEV_PROP_FREQ] = freq;
|
2011-06-29 19:20:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double get_freq(wax::obj subdev){
|
2011-06-28 03:26:52 +00:00
|
|
|
return subdev[SUBDEV_PROP_FREQ].as<double>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static meta_range_t get_freq_range(wax::obj subdev){
|
|
|
|
|
return subdev[SUBDEV_PROP_FREQ_RANGE].as<meta_range_t>();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-29 19:20:19 +00:00
|
|
|
static void set_ant(wax::obj subdev, const std::string &ant){
|
2011-06-28 03:26:52 +00:00
|
|
|
subdev[SUBDEV_PROP_ANTENNA] = ant;
|
2011-06-29 19:20:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static std::string get_ant(wax::obj subdev){
|
2011-06-28 03:26:52 +00:00
|
|
|
return subdev[SUBDEV_PROP_ANTENNA].as<std::string>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static std::vector<std::string> get_ants(wax::obj subdev){
|
|
|
|
|
return subdev[SUBDEV_PROP_ANTENNA_NAMES].as<std::vector<std::string> >();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static std::string get_conn(wax::obj subdev){
|
|
|
|
|
switch(subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()){
|
2011-06-28 23:05:08 +00:00
|
|
|
case SUBDEV_CONN_COMPLEX_IQ: return "IQ";
|
|
|
|
|
case SUBDEV_CONN_COMPLEX_QI: return "QI";
|
|
|
|
|
case SUBDEV_CONN_REAL_I: return "I";
|
|
|
|
|
case SUBDEV_CONN_REAL_Q: return "Q";
|
2011-06-28 03:26:52 +00:00
|
|
|
}
|
|
|
|
|
UHD_THROW_INVALID_CODE_PATH();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool get_use_lo_off(wax::obj subdev){
|
|
|
|
|
return subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool get_set_enb(wax::obj subdev, const bool enb){
|
|
|
|
|
subdev[SUBDEV_PROP_ENABLED] = enb;
|
|
|
|
|
return subdev[SUBDEV_PROP_ENABLED].as<bool>();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-29 19:20:19 +00:00
|
|
|
static void set_bw(wax::obj subdev, const double freq){
|
2011-06-28 03:26:52 +00:00
|
|
|
subdev[SUBDEV_PROP_BANDWIDTH] = freq;
|
2011-06-29 19:20:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double get_bw(wax::obj subdev){
|
2011-06-28 03:26:52 +00:00
|
|
|
return subdev[SUBDEV_PROP_BANDWIDTH].as<double>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dboard_manager::populate_prop_tree_from_subdev(
|
|
|
|
|
property_tree::sptr tree,
|
|
|
|
|
const property_tree::path_type &root,
|
|
|
|
|
wax::obj subdev
|
|
|
|
|
){
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<std::string>(root / "name").set(subdev[SUBDEV_PROP_NAME].as<std::string>());
|
2011-06-28 03:26:52 +00:00
|
|
|
|
|
|
|
|
const prop_names_t sensor_names = subdev[SUBDEV_PROP_SENSOR_NAMES].as<prop_names_t>();
|
|
|
|
|
BOOST_FOREACH(const std::string &name, sensor_names){
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<sensor_value_t>(root / "sensors" / name)
|
|
|
|
|
.publish(boost::bind(&get_sensor, subdev, name));
|
2011-06-28 03:26:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const prop_names_t gain_names = subdev[SUBDEV_PROP_GAIN_NAMES].as<prop_names_t>();
|
2011-06-28 23:05:08 +00:00
|
|
|
tree->create<int>(root / "gains"); //phony property so this dir exists
|
2011-06-28 03:26:52 +00:00
|
|
|
BOOST_FOREACH(const std::string &name, gain_names){
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<double>(root / "gains" / name / "value")
|
2011-06-29 19:20:19 +00:00
|
|
|
.publish(boost::bind(&get_gain, subdev, name))
|
|
|
|
|
.subscribe(boost::bind(&set_gain, subdev, name, _1));
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<meta_range_t>(root / "gains" / name / "range")
|
|
|
|
|
.publish(boost::bind(&get_gain_range, subdev, name));
|
2011-06-28 03:26:52 +00:00
|
|
|
}
|
|
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<double>(root / "freq/value")
|
2011-06-29 19:20:19 +00:00
|
|
|
.publish(boost::bind(&get_freq, subdev))
|
|
|
|
|
.subscribe(boost::bind(&set_freq, subdev, _1));
|
2011-06-28 03:26:52 +00:00
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<meta_range_t>(root / "freq/range")
|
|
|
|
|
.publish(boost::bind(&get_freq_range, subdev));
|
2011-06-28 03:26:52 +00:00
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<std::string>(root / "antenna/value")
|
2011-06-29 19:20:19 +00:00
|
|
|
.publish(boost::bind(&get_ant, subdev))
|
|
|
|
|
.subscribe(boost::bind(&set_ant, subdev, _1));
|
2011-06-28 03:26:52 +00:00
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<std::vector<std::string> >(root / "antenna/options")
|
|
|
|
|
.publish(boost::bind(&get_ants, subdev));
|
2011-06-28 03:26:52 +00:00
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<std::string>(root / "connection")
|
|
|
|
|
.publish(boost::bind(&get_conn, subdev));
|
2011-06-28 03:26:52 +00:00
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<bool>(root / "enabled")
|
2011-06-29 18:26:33 +00:00
|
|
|
.coerce(boost::bind(&get_set_enb, subdev, _1));
|
2011-06-28 03:26:52 +00:00
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<bool>(root / "use_lo_offset")
|
|
|
|
|
.publish(boost::bind(&get_use_lo_off, subdev));
|
2011-06-28 03:26:52 +00:00
|
|
|
|
2011-06-28 18:11:04 +00:00
|
|
|
tree->create<double>(root / "bandwidth/value")
|
2011-06-29 19:20:19 +00:00
|
|
|
.publish(boost::bind(&get_bw, subdev))
|
|
|
|
|
.subscribe(boost::bind(&set_bw, subdev, _1));
|
2011-06-28 03:26:52 +00:00
|
|
|
}
|