aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/usrp/CMakeLists.txt1
-rw-r--r--host/include/uhd/usrp/codec_props.hpp42
-rw-r--r--host/include/uhd/usrp/dboard_props.hpp9
-rw-r--r--host/include/uhd/usrp/device_props.hpp16
-rw-r--r--host/include/uhd/usrp/subdev_props.hpp2
-rw-r--r--host/include/uhd/utils/CMakeLists.txt2
-rw-r--r--host/include/uhd/utils/gain_group.hpp85
-rw-r--r--host/include/uhd/utils/gain_handler.hpp90
-rw-r--r--host/lib/usrp/CMakeLists.txt2
-rw-r--r--host/lib/usrp/dboard_manager.cpp23
-rw-r--r--host/lib/usrp/mimo_usrp.cpp21
-rw-r--r--host/lib/usrp/misc_utils.cpp114
-rw-r--r--host/lib/usrp/misc_utils.hpp35
-rw-r--r--host/lib/usrp/simple_usrp.cpp21
-rw-r--r--host/lib/usrp/usrp2/CMakeLists.txt1
-rw-r--r--host/lib/usrp/usrp2/codec_impl.cpp96
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp22
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp3
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp9
-rw-r--r--host/lib/utils/CMakeLists.txt2
-rw-r--r--host/lib/utils/gain_group.cpp149
-rw-r--r--host/lib/utils/gain_handler.cpp177
-rw-r--r--host/test/CMakeLists.txt2
-rw-r--r--host/test/gain_group_test.cpp122
-rw-r--r--host/test/gain_handler_test.cpp121
-rw-r--r--host/utils/uhd_usrp_probe.cpp17
26 files changed, 738 insertions, 446 deletions
diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt
index ef0696700..76ee24e5f 100644
--- a/host/include/uhd/usrp/CMakeLists.txt
+++ b/host/include/uhd/usrp/CMakeLists.txt
@@ -18,6 +18,7 @@
INSTALL(FILES
#### props headers ###
+ codec_props.hpp
dboard_props.hpp
device_props.hpp
dsp_props.hpp
diff --git a/host/include/uhd/usrp/codec_props.hpp b/host/include/uhd/usrp/codec_props.hpp
new file mode 100644
index 000000000..ab09b1703
--- /dev/null
+++ b/host/include/uhd/usrp/codec_props.hpp
@@ -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 */
diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp
index 8a6ef9129..aab6c31ce 100644
--- a/host/include/uhd/usrp/dboard_props.hpp
+++ b/host/include/uhd/usrp/dboard_props.hpp
@@ -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
diff --git a/host/include/uhd/usrp/device_props.hpp b/host/include/uhd/usrp/device_props.hpp
index 983bcb672..346eec179 100644
--- a/host/include/uhd/usrp/device_props.hpp
+++ b/host/include/uhd/usrp/device_props.hpp
@@ -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 */
diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp
index f7bdcd161..cd07cb7a8 100644
--- a/host/include/uhd/usrp/subdev_props.hpp
+++ b/host/include/uhd/usrp/subdev_props.hpp
@@ -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
diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt
index aa7842094..ef8e64ce0 100644
--- a/host/include/uhd/utils/CMakeLists.txt
+++ b/host/include/uhd/utils/CMakeLists.txt
@@ -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
diff --git a/host/include/uhd/utils/gain_group.hpp b/host/include/uhd/utils/gain_group.hpp
new file mode 100644
index 000000000..3955dfa9a
--- /dev/null
+++ b/host/include/uhd/utils/gain_group.hpp
@@ -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 */
+
diff --git a/host/include/uhd/utils/gain_handler.hpp b/host/include/uhd/utils/gain_handler.hpp
deleted file mode 100644
index f4629e6a7..000000000
--- a/host/include/uhd/utils/gain_handler.hpp
+++ /dev/null
@@ -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 */
-
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index a403296fa..d951ab412 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -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
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index bfaaf0969..ab80875f5 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -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);
diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp
index 34dee42b8..7965e4016 100644
--- a/host/lib/usrp/mimo_usrp.cpp
+++ b/host/lib/usrp/mimo_usrp.cpp
@@ -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;
diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp
new file mode 100644
index 000000000..0aa03a6cc
--- /dev/null
+++ b/host/lib/usrp/misc_utils.cpp
@@ -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;
+}
diff --git a/host/lib/usrp/misc_utils.hpp b/host/lib/usrp/misc_utils.hpp
new file mode 100644
index 000000000..7fe3c899d
--- /dev/null
+++ b/host/lib/usrp/misc_utils.hpp
@@ -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 */
+
diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp
index ebba5e137..40b71d355 100644
--- a/host/lib/usrp/simple_usrp.cpp
+++ b/host/lib/usrp/simple_usrp.cpp
@@ -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>();
+ }
};
/***********************************************************************
diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt
index 99d0b8bdd..796126d07 100644
--- a/host/lib/usrp/usrp2/CMakeLists.txt
+++ b/host/lib/usrp/usrp2/CMakeLists.txt
@@ -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
diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp
new file mode 100644
index 000000000..b9d51abf5
--- /dev/null
+++ b/host/lib/usrp/usrp2/codec_impl.cpp
@@ -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();
+}
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 8f6182fb5..075f22388 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -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();
}
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 92a87150a..610aade14 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -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();
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index e7e560469..157d17057 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -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 &);
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt
index 07e3b71b3..d6ec44193 100644
--- a/host/lib/utils/CMakeLists.txt
+++ b/host/lib/utils/CMakeLists.txt
@@ -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
diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp
new file mode 100644
index 000000000..1be09dee2
--- /dev/null
+++ b/host/lib/utils/gain_group.cpp
@@ -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());
+}
diff --git a/host/lib/utils/gain_handler.cpp b/host/lib/utils/gain_handler.cpp
deleted file mode 100644
index 36e2e8ed3..000000000
--- a/host/lib/utils/gain_handler.cpp
+++ /dev/null
@@ -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;
-}
diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt
index 1b909aa39..c620fd641 100644
--- a/host/test/CMakeLists.txt
+++ b/host/test/CMakeLists.txt
@@ -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
diff --git a/host/test/gain_group_test.cpp b/host/test/gain_group_test.cpp
new file mode 100644
index 000000000..6a6af8eb2
--- /dev/null
+++ b/host/test/gain_group_test.cpp
@@ -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);
+}
diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp
deleted file mode 100644
index 5a9f2b714..000000000
--- a/host/test/gain_handler_test.cpp
+++ /dev/null
@@ -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));
-}
diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp
index 1b73b5788..097317516 100644
--- a/host/utils/uhd_usrp_probe.cpp
+++ b/host/utils/uhd_usrp_probe.cpp
@@ -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();
}