Merge branch 'codec_gains'

Conflicts:
	host/lib/usrp/mimo_usrp.cpp
	host/lib/usrp/simple_usrp.cpp
	host/test/CMakeLists.txt
This commit is contained in:
Josh Blum 2010-08-06 15:18:02 -07:00
commit 03ccbeb641
26 changed files with 738 additions and 446 deletions

View file

@ -18,6 +18,7 @@
INSTALL(FILES
#### props headers ###
codec_props.hpp
dboard_props.hpp
device_props.hpp
dsp_props.hpp

View file

@ -0,0 +1,42 @@
//
// 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/>.
//
#ifndef INCLUDED_UHD_USRP_CODEC_PROPS_HPP
#define INCLUDED_UHD_USRP_CODEC_PROPS_HPP
#include <uhd/utils/props.hpp>
namespace uhd{ namespace usrp{
/*!
* Possible device codec properties:
* A codec is expected to have a rate and gain elements.
* Other properties can be discovered through the others prop.
*/
enum codec_prop_t{
CODEC_PROP_NAME = 'n', //ro, std::string
CODEC_PROP_OTHERS = 'o', //ro, prop_names_t
CODEC_PROP_GAIN_I = 'i', //rw, float
CODEC_PROP_GAIN_Q = 'q', //rw, float
CODEC_PROP_GAIN_RANGE = 'r', //ro, gain_range_t
CODEC_PROP_GAIN_NAMES = 'G' //ro, prop_names_t
};
}} //namespace
#endif /* INCLUDED_UHD_USRP_CODEC_PROPS_HPP */

View file

@ -23,15 +23,18 @@
namespace uhd{ namespace usrp{
/*!
* Possible device dboard properties
* Possible device dboard properties:
* A dboard has an id, one or more subdevices, and a codec.
* A dboard is considered to be unidirectional (RX or TX).
*/
enum dboard_prop_t{
DBOARD_PROP_NAME = 'n', //ro, std::string
DBOARD_PROP_SUBDEV = 's', //ro, wax::obj
DBOARD_PROP_SUBDEV_NAMES = 'S', //ro, prop_names_t
DBOARD_PROP_DBOARD_ID = 'i', //rw, dboard_id_t
DBOARD_PROP_DBOARD_IFACE = 'f' //ro, dboard_iface::sptr
//DBOARD_PROP_CODEC //ro, wax::obj //----> not sure, dont have to deal with yet
DBOARD_PROP_DBOARD_IFACE = 'f', //ro, dboard_iface::sptr
DBOARD_PROP_CODEC = 'c', //ro, wax::obj
DBOARD_PROP_GAIN_GROUP = 'g' //ro, gain_group
};
}} //namespace

View file

@ -34,22 +34,6 @@ namespace uhd{ namespace usrp{
DEVICE_PROP_MBOARD_NAMES = 'M' //ro, prop_names_t
};
////////////////////////////////////////////////////////////////////////
/*! ------ not dealing with yet, commented out ------------
* Possible device codec properties:
* A codec is expected to have a rate and gain elements.
* Other properties can be discovered through the others prop.
*/
/*enum codec_prop_t{
CODEC_PROP_NAME, //ro, std::string
CODEC_PROP_OTHERS, //ro, prop_names_t
CODEC_PROP_GAIN, //rw, gain_t
CODEC_PROP_GAIN_RANGE, //ro, gain_range_t
CODEC_PROP_GAIN_NAMES, //ro, prop_names_t
//CODEC_PROP_CLOCK_RATE //ro, freq_t //----> not sure we care to know
};*/
}} //namespace
#endif /* INCLUDED_UHD_USRP_DEVICE_PROPS_HPP */

View file

@ -53,8 +53,6 @@ namespace uhd{ namespace usrp{
SUBDEV_PROP_ANTENNA_NAMES = 'A', //ro, prop_names_t
SUBDEV_PROP_LO_LOCKED = 'L', //ro, bool
SUBDEV_PROP_CONNECTION = 'c', //ro, subdev_conn_t
//SUBDEV_PROP_QUADRATURE = 'q', //ro, bool
//SUBDEV_PROP_IQ_SWAPPED = 'i', //ro, bool
SUBDEV_PROP_USE_LO_OFFSET = 'l', //ro, bool
SUBDEV_PROP_RSSI = 'R', //ro, float
SUBDEV_PROP_BANDWIDTH = 'B' //rw, double

View file

@ -22,7 +22,7 @@ INSTALL(FILES
byteswap.hpp
byteswap.ipp
exception.hpp
gain_handler.hpp
gain_group.hpp
pimpl.hpp
props.hpp
safe_main.hpp

View file

@ -0,0 +1,85 @@
//
// 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/>.
//
#ifndef INCLUDED_UHD_UTILS_GAIN_GROUP_HPP
#define INCLUDED_UHD_UTILS_GAIN_GROUP_HPP
#include <uhd/config.hpp>
#include <uhd/types/ranges.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/utility.hpp>
namespace uhd{
/*!
* A set of function to control a gain element.
*/
struct UHD_API gain_fcns_t{
boost::function<gain_range_t(void)> get_range;
boost::function<float(void)> get_value;
boost::function<void(float)> set_value;
};
class UHD_API gain_group : boost::noncopyable{
public:
typedef boost::shared_ptr<gain_group> sptr;
/*!
* Get the overall gain range for this group.
* Overall step is defined as the minimum step size.
* \return a gain range with overall min, max, step
*/
virtual gain_range_t get_range(void) = 0;
/*!
* Get the overall gain value for this group.
* \return a summation of all the gain values
*/
virtual float get_value(void) = 0;
/*!
* Set the overall gain value for this group.
* The power will be distributed across individual gain elements.
* The semantics of how to do this are determined by the priority.
* \param gain the gain to set across the group
*/
virtual void set_value(float gain) = 0;
/*!
* Register a set of gain functions into this group.
* Priority determines how power will be distributed
* with higher priorities getting the power first,
* and lower priorities getting the remainder power.
* \param gain_fcns the set of gain functions
* \param priority the priority of the gain element
*/
virtual void register_fcns(
const gain_fcns_t &gain_fcns, size_t priority = 0
) = 0;
/*!
* Make a new empty gain group.
* \return a gain group object.
*/
static sptr make(void);
};
} //namespace uhd
#endif /* INCLUDED_UHD_UTILS_GAIN_GROUP_HPP */

View file

@ -1,90 +0,0 @@
//
// 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/>.
//
#ifndef INCLUDED_UHD_UTILS_GAIN_HANDLER_HPP
#define INCLUDED_UHD_UTILS_GAIN_HANDLER_HPP
#include <uhd/config.hpp>
#include <uhd/wax.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
namespace uhd{
class UHD_API gain_handler{
public:
typedef boost::shared_ptr<gain_handler> sptr;
typedef boost::function<bool(const wax::obj &, const wax::obj &)> is_equal_t;
/*!
* A set of properties for dealing with gains.
*/
struct UHD_API props_t{
wax::obj value, range, names;
props_t(void); //default constructor
};
/*!
* Make a new gain handler.
* The construction arguments are agnostic to the property type.
* It is up to the caller to provide an "is_equal" function that
* can tell weather two properties (in a wax obj) are equal.
* \param link a link to the wax obj with properties
* \param props a struct of properties keys
* \param is_equal the function that tests for equal properties
*/
static sptr make(
const wax::obj &link,
const props_t &props,
is_equal_t is_equal
);
/*!
* Intercept gets for overall gain, min, max, step.
* Ensures that the gain name is valid.
* \return true for handled, false to pass on
*/
virtual bool intercept_get(const wax::obj &key, wax::obj &val) = 0;
/*!
* Intercept sets for overall gain.
* Ensures that the gain name is valid.
* Ensures that the new gain is within range.
* \return true for handled, false to pass on
*/
virtual bool intercept_set(const wax::obj &key, const wax::obj &val) = 0;
/*!
* Function template to test if two wax types are equal:
* The constructor will bind an instance of this for a specific type.
* This bound equals functions allows the intercept methods to be non-templated.
*/
template <class T> static bool is_equal(const wax::obj &a, const wax::obj &b){
try{
return a.as<T>() == b.as<T>();
}
catch(const wax::bad_cast &){
return false;
}
}
};
} //namespace uhd
#endif /* INCLUDED_UHD_UTILS_GAIN_HANDLER_HPP */

View file

@ -24,6 +24,8 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp

View file

@ -18,7 +18,6 @@
#include "dboard_ctor_args.hpp"
#include <uhd/usrp/dboard_manager.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/utils/gain_handler.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/types/dict.hpp>
@ -98,33 +97,18 @@ public:
enum type_t{RX_TYPE, TX_TYPE};
//structors
subdev_proxy(dboard_base::sptr subdev, type_t type)
: _subdev(subdev), _type(type){
//initialize gain props struct
gain_handler::props_t gain_props;
gain_props.value = SUBDEV_PROP_GAIN;
gain_props.range = SUBDEV_PROP_GAIN_RANGE;
gain_props.names = 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){
subdev_proxy(dboard_base::sptr subdev, type_t type):
_subdev(subdev), _type(type)
{
/* NOP */
}
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);
@ -133,7 +117,6 @@ 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);

View file

@ -18,6 +18,7 @@
#include <uhd/usrp/mimo_usrp.hpp>
#include <uhd/usrp/tune_helper.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/gain_group.hpp>
#include <uhd/utils/algorithm.hpp>
#include <uhd/utils/warning.hpp>
#include <uhd/usrp/subdev_props.hpp>
@ -190,15 +191,15 @@ public:
}
void set_rx_gain(size_t chan, float gain){
_rx_subdev(chan)[SUBDEV_PROP_GAIN] = gain;
return _rx_gain_group(chan)->set_value(gain);
}
float get_rx_gain(size_t chan){
return _rx_subdev(chan)[SUBDEV_PROP_GAIN].as<float>();
return _rx_gain_group(chan)->get_value();
}
gain_range_t get_rx_gain_range(size_t chan){
return _rx_subdev(chan)[SUBDEV_PROP_GAIN_RANGE].as<gain_range_t>();
return _rx_gain_group(chan)->get_range();
}
void set_rx_antenna(size_t chan, const std::string &ant){
@ -262,15 +263,15 @@ public:
}
void set_tx_gain(size_t chan, float gain){
_tx_subdev(chan)[SUBDEV_PROP_GAIN] = gain;
return _tx_gain_group(chan)->set_value(gain);
}
float get_tx_gain(size_t chan){
return _tx_subdev(chan)[SUBDEV_PROP_GAIN].as<float>();
return _tx_gain_group(chan)->get_value();
}
gain_range_t get_tx_gain_range(size_t chan){
return _tx_subdev(chan)[SUBDEV_PROP_GAIN_RANGE].as<gain_range_t>();
return _tx_gain_group(chan)->get_range();
}
void set_tx_antenna(size_t chan, const std::string &ant){
@ -317,6 +318,14 @@ private:
std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name;
return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)];
}
gain_group::sptr _rx_gain_group(size_t chan){
std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name;
return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();
}
gain_group::sptr _tx_gain_group(size_t chan){
std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name;
return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();
}
//shadows
double _rx_rate, _tx_rate;

View file

@ -0,0 +1,114 @@
//
// 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 "misc_utils.hpp"
#include <uhd/utils/gain_group.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/codec_props.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
using namespace uhd;
using namespace uhd::usrp;
static const size_t subdev_gain_priority = 1; //higher, closer to the antenna
static const size_t codec_gain_priority = 0;
/***********************************************************************
* codec gain group helper functions:
* do this so we dont have to bind a templated function
**********************************************************************/
static gain_range_t get_codec_gain_range(wax::obj codec, const std::string &name){
return codec[named_prop_t(CODEC_PROP_GAIN_RANGE, name)].as<gain_range_t>();
}
static float get_codec_gain_i(wax::obj codec, const std::string &name){
return codec[named_prop_t(CODEC_PROP_GAIN_I, name)].as<float>();
}
static float get_codec_gain_q(wax::obj codec, const std::string &name){
return codec[named_prop_t(CODEC_PROP_GAIN_Q, name)].as<float>();
}
static void set_codec_gain_both(wax::obj codec, const std::string &name, float gain){
codec[named_prop_t(CODEC_PROP_GAIN_I, name)] = gain;
codec[named_prop_t(CODEC_PROP_GAIN_Q, name)] = gain;
}
static void set_codec_gain_i(wax::obj codec, const std::string &name, float gain){
codec[named_prop_t(CODEC_PROP_GAIN_I, name)] = gain;
}
static void set_codec_gain_q(wax::obj codec, const std::string &name, float gain){
codec[named_prop_t(CODEC_PROP_GAIN_Q, name)] = gain;
}
/***********************************************************************
* subdev gain group helper functions:
* do this so we dont have to bind a templated function
**********************************************************************/
static float get_subdev_gain(wax::obj subdev, const std::string &name){
return subdev[named_prop_t(SUBDEV_PROP_GAIN, name)].as<float>();
}
static gain_range_t get_subdev_gain_range(wax::obj subdev, const std::string &name){
return subdev[named_prop_t(SUBDEV_PROP_GAIN_RANGE, name)].as<gain_range_t>();
}
static void set_subdev_gain(wax::obj subdev, const std::string &name, float gain){
subdev[named_prop_t(SUBDEV_PROP_GAIN, name)] = gain;
}
/***********************************************************************
* gain group factory function for usrp
**********************************************************************/
gain_group::sptr usrp::make_gain_group(wax::obj subdev, wax::obj codec){
gain_group::sptr gg = gain_group::make();
gain_fcns_t fcns;
//add all the subdev gains first (antenna to dsp order)
BOOST_FOREACH(const std::string &name, subdev[SUBDEV_PROP_GAIN_NAMES].as<prop_names_t>()){
fcns.get_range = boost::bind(&get_subdev_gain_range, subdev, name);
fcns.get_value = boost::bind(&get_subdev_gain, subdev, name);
fcns.set_value = boost::bind(&set_subdev_gain, subdev, name, _1);
gg->register_fcns(fcns, subdev_gain_priority);
}
//add all the codec gains last (antenna to dsp order)
BOOST_FOREACH(const std::string &name, codec[CODEC_PROP_GAIN_NAMES].as<prop_names_t>()){
fcns.get_range = boost::bind(&get_codec_gain_range, codec, name);
//register the value functions depending upon the connection type
switch(subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()){
case SUBDEV_CONN_COMPLEX_IQ:
case SUBDEV_CONN_COMPLEX_QI:
fcns.get_value = boost::bind(&get_codec_gain_i, codec, name); //same as Q
fcns.set_value = boost::bind(&set_codec_gain_both, codec, name, _1); //sets both
break;
case SUBDEV_CONN_REAL_I:
fcns.get_value = boost::bind(&get_codec_gain_i, codec, name);
fcns.set_value = boost::bind(&set_codec_gain_i, codec, name, _1);
break;
case SUBDEV_CONN_REAL_Q:
fcns.get_value = boost::bind(&get_codec_gain_q, codec, name);
fcns.set_value = boost::bind(&set_codec_gain_q, codec, name, _1);
break;
}
gg->register_fcns(fcns, codec_gain_priority);
}
return gg;
}

View file

@ -0,0 +1,35 @@
//
// 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/>.
//
#ifndef INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP
#define INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP
#include <uhd/config.hpp>
#include <uhd/wax.hpp>
#include <uhd/utils/gain_group.hpp>
namespace uhd{ namespace usrp{
/*!
* Create a gain group that represents the subdevice and its codec.
*/
gain_group::sptr make_gain_group(wax::obj subdev, wax::obj codec);
}} //namespace
#endif /* INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP */

View file

@ -18,6 +18,7 @@
#include <uhd/usrp/simple_usrp.hpp>
#include <uhd/usrp/tune_helper.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/gain_group.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/usrp/device_props.hpp>
@ -132,15 +133,15 @@ public:
}
void set_rx_gain(float gain){
_rx_subdev()[SUBDEV_PROP_GAIN] = gain;
return _rx_gain_group()->set_value(gain);
}
float get_rx_gain(void){
return _rx_subdev()[SUBDEV_PROP_GAIN].as<float>();
return _rx_gain_group()->get_value();
}
gain_range_t get_rx_gain_range(void){
return _rx_subdev()[SUBDEV_PROP_GAIN_RANGE].as<gain_range_t>();
return _rx_gain_group()->get_range();
}
void set_rx_antenna(const std::string &ant){
@ -196,15 +197,15 @@ public:
}
void set_tx_gain(float gain){
_tx_subdev()[SUBDEV_PROP_GAIN] = gain;
return _tx_gain_group()->set_value(gain);
}
float get_tx_gain(void){
return _tx_subdev()[SUBDEV_PROP_GAIN].as<float>();
return _tx_gain_group()->get_value();
}
gain_range_t get_tx_gain_range(void){
return _tx_subdev()[SUBDEV_PROP_GAIN_RANGE].as<gain_range_t>();
return _tx_gain_group()->get_range();
}
void set_tx_antenna(const std::string &ant){
@ -250,6 +251,14 @@ private:
std::string sd_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name;
return _tx_dboard()[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)];
}
gain_group::sptr _rx_gain_group(void){
std::string sd_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name;
return _rx_dboard()[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();
}
gain_group::sptr _tx_gain_group(void){
std::string sd_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name;
return _tx_dboard()[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();
}
};
/***********************************************************************

View file

@ -22,6 +22,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_impl.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp

View file

@ -0,0 +1,96 @@
//
// 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 "usrp2_impl.hpp"
#include <uhd/usrp/codec_props.hpp>
#include <boost/bind.hpp>
using namespace uhd;
using namespace uhd::usrp;
/***********************************************************************
* Helper Methods
**********************************************************************/
void usrp2_mboard_impl::codec_init(void){
//make proxies
_rx_codec_proxy = wax_obj_proxy::make(
boost::bind(&usrp2_mboard_impl::rx_codec_get, this, _1, _2),
boost::bind(&usrp2_mboard_impl::rx_codec_set, this, _1, _2)
);
_tx_codec_proxy = wax_obj_proxy::make(
boost::bind(&usrp2_mboard_impl::tx_codec_get, this, _1, _2),
boost::bind(&usrp2_mboard_impl::tx_codec_set, this, _1, _2)
);
}
/***********************************************************************
* RX Codec Properties
**********************************************************************/
void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
//handle the get request conditioned on the key
switch(key.as<codec_prop_t>()){
case CODEC_PROP_NAME:
val = std::string("usrp2 adc");
return;
case CODEC_PROP_OTHERS:
val = prop_names_t();
return;
case CODEC_PROP_GAIN_NAMES:
val = prop_names_t(); //no gain elements to be controlled
return;
default: UHD_THROW_PROP_GET_ERROR();
}
}
void usrp2_mboard_impl::rx_codec_set(const wax::obj &, const wax::obj &){
UHD_THROW_PROP_SET_ERROR();
}
/***********************************************************************
* TX Codec Properties
**********************************************************************/
void usrp2_mboard_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
//handle the get request conditioned on the key
switch(key.as<codec_prop_t>()){
case CODEC_PROP_NAME:
val = std::string("usrp2 dac - ad9777");
return;
case CODEC_PROP_OTHERS:
val = prop_names_t();
return;
case CODEC_PROP_GAIN_NAMES:
val = prop_names_t(); //no gain elements to be controlled
return;
default: UHD_THROW_PROP_GET_ERROR();
}
}
void usrp2_mboard_impl::tx_codec_set(const wax::obj &, const wax::obj &){
UHD_THROW_PROP_SET_ERROR();
}

View file

@ -15,10 +15,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
#include "../dsp_utils.hpp"
#include "../misc_utils.hpp"
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dboard_props.hpp>
#include <uhd/utils/assert.hpp>
@ -84,6 +84,16 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
val = _dboard_iface;
return;
case DBOARD_PROP_CODEC:
val = _rx_codec_proxy->get_link();
return;
case DBOARD_PROP_GAIN_GROUP:
val = make_gain_group(
_dboard_manager->get_rx_subdev(name), _rx_codec_proxy->get_link()
);
return;
default: UHD_THROW_PROP_GET_ERROR();
}
}
@ -129,6 +139,16 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
val = _dboard_iface;
return;
case DBOARD_PROP_CODEC:
val = _tx_codec_proxy->get_link();
return;
case DBOARD_PROP_GAIN_GROUP:
val = make_gain_group(
_dboard_manager->get_tx_subdev(name), _tx_codec_proxy->get_link()
);
return;
default: UHD_THROW_PROP_GET_ERROR();
}
}

View file

@ -96,6 +96,9 @@ usrp2_mboard_impl::usrp2_mboard_impl(
//initialize the clock configuration
init_clock_config();
//init the codec before the dboard
codec_init();
//init the tx and rx dboards (do last)
dboard_init();

View file

@ -163,6 +163,15 @@ private:
void update_clock_config(void);
void set_time_spec(const uhd::time_spec_t &time_spec, bool now);
//properties interface for the codec
void codec_init(void);
void rx_codec_get(const wax::obj &, wax::obj &);
void rx_codec_set(const wax::obj &, const wax::obj &);
void tx_codec_get(const wax::obj &, wax::obj &);
void tx_codec_set(const wax::obj &, const wax::obj &);
wax_obj_proxy::sptr _rx_codec_proxy;
wax_obj_proxy::sptr _tx_codec_proxy;
//properties interface for rx dboard
void rx_dboard_get(const wax::obj &, wax::obj &);
void rx_dboard_set(const wax::obj &, const wax::obj &);

View file

@ -19,7 +19,7 @@
LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/utils/assert.cpp
${CMAKE_SOURCE_DIR}/lib/utils/gain_handler.cpp
${CMAKE_SOURCE_DIR}/lib/utils/gain_group.cpp
${CMAKE_SOURCE_DIR}/lib/utils/load_modules.cpp
${CMAKE_SOURCE_DIR}/lib/utils/props.cpp
${CMAKE_SOURCE_DIR}/lib/utils/thread_priority.cpp

View file

@ -0,0 +1,149 @@
//
// 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_group.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/utils/algorithm.hpp>
#include <uhd/utils/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace uhd;
static const bool verbose = false;
static bool compare_by_step_size(
const size_t &rhs, const size_t &lhs, std::vector<gain_fcns_t> &fcns
){
return fcns.at(rhs).get_range().step > fcns.at(lhs).get_range().step;
}
/***********************************************************************
* gain group implementation
**********************************************************************/
class gain_group_impl : public gain_group{
public:
gain_group_impl(void){
/*NOP*/
}
gain_range_t get_range(void){
float overall_min = 0, overall_max = 0, overall_step = 0;
BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){
const gain_range_t range = fcns.get_range();
overall_min += range.min;
overall_max += range.max;
//the overall step is the min (zero is invalid, first run)
if (overall_step == 0) overall_step = range.step;
overall_step = std::min(overall_step, range.step);
}
return gain_range_t(overall_min, overall_max, overall_step);
}
float get_value(void){
float overall_gain = 0;
BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){
overall_gain += fcns.get_value();
}
return overall_gain;
}
void set_value(float gain){
std::vector<gain_fcns_t> all_fcns = get_all_fcns();
if (all_fcns.size() == 0) return; //nothing to set!
//get the max step size among the gains
float max_step = 0;
BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){
max_step = std::max(max_step, fcns.get_range().step);
}
//create gain bucket to distribute power
std::vector<float> gain_bucket;
//distribute power according to priority (round to max step)
float gain_left_to_distribute = gain;
BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){
const gain_range_t range = fcns.get_range();
gain_bucket.push_back(
max_step*int(std::clip(gain_left_to_distribute, range.min, range.max)/max_step)
);
gain_left_to_distribute -= gain_bucket.back();
}
//get a list of indexes sorted by step size large to small
std::vector<size_t> indexes_step_size_dec;
for (size_t i = 0; i < all_fcns.size(); i++){
indexes_step_size_dec.push_back(i);
}
std::sort(
indexes_step_size_dec.begin(), indexes_step_size_dec.end(),
boost::bind(&compare_by_step_size, _1, _2, all_fcns)
);
UHD_ASSERT_THROW(
all_fcns.at(indexes_step_size_dec.front()).get_range().step >=
all_fcns.at(indexes_step_size_dec.back()).get_range().step
);
//distribute the remainder (less than max step)
//fill in the largest step sizes first that are less than the remainder
BOOST_FOREACH(size_t i, indexes_step_size_dec){
const gain_range_t range = all_fcns.at(i).get_range();
float additional_gain = range.step*int(
std::clip(gain_bucket.at(i) + gain_left_to_distribute, range.min, range.max
)/range.step) - gain_bucket.at(i);
gain_bucket.at(i) += additional_gain;
gain_left_to_distribute -= additional_gain;
}
if (verbose) std::cout << "gain_left_to_distribute " << gain_left_to_distribute << std::endl;
//now write the bucket out to the individual gain values
for (size_t i = 0; i < gain_bucket.size(); i++){
if (verbose) std::cout << gain_bucket.at(i) << std::endl;
all_fcns.at(i).set_value(gain_bucket.at(i));
}
}
void register_fcns(
const gain_fcns_t &gain_fcns, size_t priority
){
_registry[priority].push_back(gain_fcns);
}
private:
//! get the gain function sets in order (highest priority first)
std::vector<gain_fcns_t> get_all_fcns(void){
std::vector<gain_fcns_t> all_fcns;
BOOST_FOREACH(ssize_t key, std::sorted(_registry.keys())){
const std::vector<gain_fcns_t> &fcns = _registry[key];
all_fcns.insert(all_fcns.begin(), fcns.begin(), fcns.end());
}
return all_fcns;
}
uhd::dict<size_t, std::vector<gain_fcns_t> > _registry;
};
/***********************************************************************
* gain group factory function
**********************************************************************/
gain_group::sptr gain_group::make(void){
return sptr(new gain_group_impl());
}

View file

@ -1,177 +0,0 @@
//
// 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;
}

View file

@ -26,7 +26,7 @@ ADD_EXECUTABLE(main_test
convert_types_test.cpp
dict_test.cpp
error_test.cpp
gain_handler_test.cpp
gain_group_test.cpp
subdev_spec_test.cpp
tune_helper_test.cpp
vrt_test.cpp

View file

@ -0,0 +1,122 @@
//
// 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 <boost/test/unit_test.hpp>
#include <uhd/utils/gain_group.hpp>
#include <boost/bind.hpp>
#include <boost/math/special_functions/round.hpp>
#include <iostream>
#define rint(x) boost::math::iround(x)
using namespace uhd;
/***********************************************************************
* Define gain element classes with needed functions
**********************************************************************/
class gain_element1{
public:
gain_range_t get_range(void){
return gain_range_t(0, 90, 1);
}
float get_value(void){
return _gain;
}
void set_value(float gain){
float step = get_range().step;
_gain = step*rint(gain/step);
}
private:
float _gain;
};
class gain_element2{
public:
gain_range_t get_range(void){
return gain_range_t(-20, 10, 0.1);
}
float get_value(void){
return _gain;
}
void set_value(float gain){
float step = get_range().step;
_gain = step*rint(gain/step);
}
private:
float _gain;
};
//create static instances of gain elements to be shared by the tests
static gain_element1 g1;
static gain_element2 g2;
static gain_group::sptr get_gain_group(size_t pri1 = 0, size_t pri2 = 0){
//create instance of gain group
gain_fcns_t gain_fcns;
gain_group::sptr gg(gain_group::make());
//load gain group with function sets
gain_fcns.get_range = boost::bind(&gain_element1::get_range, &g1);
gain_fcns.get_value = boost::bind(&gain_element1::get_value, &g1);
gain_fcns.set_value = boost::bind(&gain_element1::set_value, &g1, _1);
gg->register_fcns(gain_fcns, pri1);
gain_fcns.get_range = boost::bind(&gain_element2::get_range, &g2);
gain_fcns.get_value = boost::bind(&gain_element2::get_value, &g2);
gain_fcns.set_value = boost::bind(&gain_element2::set_value, &g2, _1);
gg->register_fcns(gain_fcns, pri2);
return gg;
}
/***********************************************************************
* Test cases
**********************************************************************/
static const double tolerance = 0.001;
BOOST_AUTO_TEST_CASE(test_gain_group_overall){
gain_group::sptr gg = get_gain_group();
//test the overall stuff
gg->set_value(80);
BOOST_CHECK_CLOSE(gg->get_value(), float(80), tolerance);
BOOST_CHECK_CLOSE(gg->get_range().min, float(-20), tolerance);
BOOST_CHECK_CLOSE(gg->get_range().max, float(100), tolerance);
BOOST_CHECK_CLOSE(gg->get_range().step, float(0.1), tolerance);
}
BOOST_AUTO_TEST_CASE(test_gain_group_priority){
gain_group::sptr gg = get_gain_group(0, 1);
//test the overall stuff
gg->set_value(80);
BOOST_CHECK_CLOSE(gg->get_value(), float(80), tolerance);
BOOST_CHECK_CLOSE(gg->get_range().min, float(-20), tolerance);
BOOST_CHECK_CLOSE(gg->get_range().max, float(100), tolerance);
BOOST_CHECK_CLOSE(gg->get_range().step, float(0.1), tolerance);
//test the the higher priority gain got filled first (gain 2)
BOOST_CHECK_CLOSE(g2.get_value(), g2.get_range().max, tolerance);
}

View file

@ -1,121 +0,0 @@
//
// 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 <boost/test/unit_test.hpp>
#include <uhd/utils/gain_handler.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/utils/props.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace uhd;
enum prop_t{
PROP_GAIN_VALUE,
PROP_GAIN_RANGE,
PROP_GAIN_NAMES
};
class gainful_obj : public wax::obj{
public:
gainful_obj(void){
//initialize gain props struct
gain_handler::props_t gain_props;
gain_props.value = PROP_GAIN_VALUE;
gain_props.range = PROP_GAIN_RANGE;
gain_props.names = PROP_GAIN_NAMES;
//make a new gain handler
_gain_handler = gain_handler::make(
this->get_link(), gain_props,
boost::bind(&gain_handler::is_equal<prop_t>, _1, _2)
);
_gain_values["g0"] = 0;
_gain_values["g1"] = 0;
_gain_ranges["g0"] = gain_range_t(-10, 0, float(.1));
_gain_ranges["g1"] = gain_range_t(0, 100, float(1.5));
}
~gainful_obj(void){}
private:
void get(const wax::obj &key_, wax::obj &val){
if (_gain_handler->intercept_get(key_, val)) return;
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
//handle the get request conditioned on the key
switch(key.as<prop_t>()){
case PROP_GAIN_VALUE:
val = _gain_values[name];
return;
case PROP_GAIN_RANGE:
val = _gain_ranges[name];
return;
case PROP_GAIN_NAMES:
val = _gain_values.keys();
return;
default: UHD_THROW_PROP_GET_ERROR();
}
}
void set(const wax::obj &key_, const wax::obj &val){
if (_gain_handler->intercept_set(key_, val)) return;
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
//handle the get request conditioned on the key
switch(key.as<prop_t>()){
case PROP_GAIN_VALUE:
_gain_values[name] = val.as<float>();
return;
default: UHD_THROW_PROP_SET_ERROR();
}
}
gain_handler::sptr _gain_handler;
uhd::dict<std::string, float> _gain_values;
uhd::dict<std::string, gain_range_t> _gain_ranges;
};
BOOST_AUTO_TEST_CASE(test_gain_handler){
std::cout << "Testing the gain handler..." << std::endl;
gainful_obj go0;
BOOST_CHECK_THROW(
go0[named_prop_t(PROP_GAIN_VALUE, "fail")].as<float>(),
std::exception
);
std::cout << "verifying the overall min, max, step" << std::endl;
gain_range_t gain = go0[PROP_GAIN_RANGE].as<gain_range_t>();
BOOST_CHECK_EQUAL(gain.min, float(-10));
BOOST_CHECK_EQUAL(gain.max, float(100));
BOOST_CHECK_EQUAL(gain.step, float(1.5));
std::cout << "verifying the overall gain" << std::endl;
go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = float(-5);
go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = float(30);
BOOST_CHECK_EQUAL(go0[PROP_GAIN_VALUE].as<float>(), float(25));
}

View file

@ -21,6 +21,7 @@
#include <uhd/usrp/device_props.hpp>
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/usrp/dboard_props.hpp>
#include <uhd/usrp/codec_props.hpp>
#include <uhd/usrp/dsp_props.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dboard_id.hpp>
@ -88,12 +89,25 @@ static std::string get_subdev_pp_string(const std::string &type, wax::obj subdev
ss << boost::format("Gain range %s: %.1f to %.1f step %.1f dB") % gain_name % gain_range.min % gain_range.max % gain_range.step << std::endl;
}
ss << boost::format("Connection Type: %c") % (subdev[usrp::SUBDEV_PROP_CONNECTION].as<usrp::subdev_conn_t>()) << std::endl;
ss << boost::format("Connection Type: %c") % char(subdev[usrp::SUBDEV_PROP_CONNECTION].as<usrp::subdev_conn_t>()) << std::endl;
ss << boost::format("Uses LO offset: %s") % (subdev[usrp::SUBDEV_PROP_USE_LO_OFFSET].as<bool>()? "Yes" : "No") << std::endl;
return ss.str();
}
static std::string get_codec_pp_string(const std::string &type, wax::obj codec){
std::stringstream ss;
ss << boost::format("%s Codec: %s") % type % codec[usrp::CODEC_PROP_NAME].as<std::string>() << std::endl;
//ss << std::endl;
prop_names_t gain_names(codec[usrp::CODEC_PROP_GAIN_NAMES].as<prop_names_t>());
if (gain_names.size() == 0) ss << "Gain Elements: None" << std::endl;
BOOST_FOREACH(const std::string &gain_name, gain_names){
gain_range_t gain_range(codec[named_prop_t(usrp::CODEC_PROP_GAIN_RANGE, gain_name)].as<gain_range_t>());
ss << boost::format("Gain range %s: %.1f to %.1f step %.1f dB") % gain_name % gain_range.min % gain_range.max % gain_range.step << std::endl;
}
return ss.str();
}
static std::string get_dboard_pp_string(const std::string &type, wax::obj dboard){
std::stringstream ss;
ss << boost::format("%s Dboard: %s") % type % dboard[usrp::DBOARD_PROP_NAME].as<std::string>() << std::endl;
@ -101,6 +115,7 @@ static std::string get_dboard_pp_string(const std::string &type, wax::obj dboard
BOOST_FOREACH(const std::string &subdev_name, dboard[usrp::DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>()){
ss << make_border(get_subdev_pp_string(type, dboard[named_prop_t(usrp::DBOARD_PROP_SUBDEV, subdev_name)]));
}
ss << make_border(get_codec_pp_string(type, dboard[usrp::DBOARD_PROP_CODEC]));
return ss.str();
}