summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/types/CMakeLists.txt1
-rw-r--r--host/include/uhd/types/dict.ipp11
-rw-r--r--host/include/uhd/types/ranges.hpp89
-rw-r--r--host/include/uhd/types/ranges.ipp168
-rw-r--r--host/include/uhd/usrp/mimo_usrp.hpp2
-rw-r--r--host/lib/types.cpp19
-rw-r--r--host/lib/usrp/dboard/db_dbsrx.cpp16
-rw-r--r--host/lib/usrp/dboard/db_dbsrx2.cpp12
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp40
-rw-r--r--host/lib/usrp/dboard/db_tvrx.cpp14
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp23
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp28
-rw-r--r--host/lib/usrp/usrp1/codec_ctrl.cpp8
-rw-r--r--host/lib/usrp/wrapper_utils.hpp2
-rw-r--r--host/lib/utils/gain_group.cpp22
-rw-r--r--host/test/CMakeLists.txt1
-rw-r--r--host/test/gain_group_test.cpp18
-rw-r--r--host/test/ranges_test.cpp57
-rw-r--r--host/utils/uhd_usrp_probe.cpp6
19 files changed, 403 insertions, 134 deletions
diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt
index a96976b5e..1d2c0c41c 100644
--- a/host/include/uhd/types/CMakeLists.txt
+++ b/host/include/uhd/types/CMakeLists.txt
@@ -25,6 +25,7 @@ INSTALL(FILES
mac_addr.hpp
metadata.hpp
otw_type.hpp
+ ranges.ipp
ranges.hpp
serial.hpp
stream_cmd.hpp
diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp
index ba05d5272..f037d7988 100644
--- a/host/include/uhd/types/dict.ipp
+++ b/host/include/uhd/types/dict.ipp
@@ -46,12 +46,11 @@ namespace uhd{
/* NOP */
}
- template <typename Key, typename Val>
- template <typename InputIterator>
- dict<Key, Val>::dict(InputIterator first, InputIterator last){
- for(InputIterator it = first; it != last; it++){
- _map.push_back(*it);
- }
+ template <typename Key, typename Val> template <typename InputIterator>
+ dict<Key, Val>::dict(InputIterator first, InputIterator last):
+ _map(first, last)
+ {
+ /* NOP */
}
template <typename Key, typename Val>
diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp
index a2057d1c8..206c64726 100644
--- a/host/include/uhd/types/ranges.hpp
+++ b/host/include/uhd/types/ranges.hpp
@@ -19,28 +19,95 @@
#define INCLUDED_UHD_TYPES_RANGES_HPP
#include <uhd/config.hpp>
+#include <uhd/utils/pimpl.hpp>
+#include <vector>
namespace uhd{
/*!
- * The gain range struct describes possible gain settings.
- * The mimumum gain, maximum gain, and step size are in dB.
+ * A range object describes a set of discrete values of the form:
+ * y = start + step*n, where n is an integer between 0 and (stop - start)/step
*/
- struct UHD_API gain_range_t{
- float min, max, step;
- gain_range_t(float min = 0.0, float max = 0.0, float step = 0.0);
+ template <typename T> class range_t{
+ public:
+ /*!
+ * Create a range from a single value.
+ * The step size will be taken as zero.
+ * \param value the only possible value in this range
+ */
+ range_t(const T &value = T(0));
+
+ /*!
+ * Create a range from a full set of values.
+ * A step size of zero implies infinite precision.
+ * \param start the minimum value for this range
+ * \param stop the maximum value for this range
+ * \param step the step size for this range
+ */
+ range_t(const T &start, const T &stop, const T &step = T(0));
+
+ //! Get the start value for this range.
+ const T start(void) const;
+
+ //! Get the stop value for this range.
+ const T stop(void) const;
+
+ //! Get the step value for this range.
+ const T step(void) const;
+
+ private: UHD_PIMPL_DECL(impl) _impl;
};
/*!
- * The frequency range struct describes possible frequency settings.
- * Because tuning is very granular (sub-Hz), step size is not listed.
- * The mimumum frequency and maximum frequency are in Hz.
+ * A meta-range object holds a list of individual ranges.
*/
- struct UHD_API freq_range_t{
- double min, max;
- freq_range_t(double min = 0.0, double max = 0.0);
+ template <typename T> struct meta_range_t : std::vector<range_t<T> >{
+
+ //! A default constructor for an empty meta-range
+ meta_range_t(void);
+
+ /*!
+ * Input iterator constructor:
+ * Makes boost::assign::list_of work.
+ * \param first the begin iterator
+ * \param last the end iterator
+ */
+ template <typename InputIterator>
+ meta_range_t(InputIterator first, InputIterator last);
+
+ /*!
+ * A convenience constructor for a single range.
+ * A step size of zero implies infinite precision.
+ * \param start the minimum value for this range
+ * \param stop the maximum value for this range
+ * \param step the step size for this range
+ */
+ meta_range_t(const T &start, const T &stop, const T &step = T(0));
+
+ //! Get the overall start value for this meta-range.
+ const T start(void) const;
+
+ //! Get the overall stop value for this meta-range.
+ const T stop(void) const;
+
+ //! Get the overall step value for this meta-range.
+ const T step(void) const;
+
+ /*!
+ * Clip the target value to a possible range value.
+ * \param value the value to clip to this range
+ * \param clip_step if true, clip to steps as well
+ * \return a value that is in one of the ranges
+ */
+ const T clip(const T &value, bool clip_step = false) const;
+
};
+ typedef meta_range_t<float> gain_range_t;
+ typedef meta_range_t<double> freq_range_t;
+
} //namespace uhd
+#include <uhd/types/ranges.ipp>
+
#endif /* INCLUDED_UHD_TYPES_RANGES_HPP */
diff --git a/host/include/uhd/types/ranges.ipp b/host/include/uhd/types/ranges.ipp
new file mode 100644
index 000000000..8b602a24d
--- /dev/null
+++ b/host/include/uhd/types/ranges.ipp
@@ -0,0 +1,168 @@
+//
+// 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_TYPES_RANGES_IPP
+#define INCLUDED_UHD_TYPES_RANGES_IPP
+
+#include <boost/math/special_functions/round.hpp>
+#include <boost/foreach.hpp>
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+
+namespace uhd{
+
+ /*******************************************************************
+ * range_t implementation code
+ ******************************************************************/
+ template <typename T> struct range_t<T>::impl{
+ impl(const T &start, const T &stop, const T &step):
+ start(start), stop(stop), step(step)
+ {
+ /* NOP */
+ }
+ const T start, stop, step;
+ };
+
+ template <typename T> range_t<T>::range_t(const T &value):
+ _impl(UHD_PIMPL_MAKE(impl, (value, value, T(0))))
+ {
+ /* NOP */
+ }
+
+ template <typename T> range_t<T>::range_t(
+ const T &start, const T &stop, const T &step
+ ):
+ _impl(UHD_PIMPL_MAKE(impl, (start, stop, step)))
+ {
+ if (stop < start){
+ throw std::invalid_argument("cannot make range where stop < start");
+ }
+ }
+
+ template <typename T> const T range_t<T>::start(void) const{
+ return _impl->start;
+ }
+
+ template <typename T> const T range_t<T>::stop(void) const{
+ return _impl->stop;
+ }
+
+ template <typename T> const T range_t<T>::step(void) const{
+ return _impl->step;
+ }
+
+ /*******************************************************************
+ * meta_range_t implementation code
+ ******************************************************************/
+
+ namespace /*anon*/{
+ template <typename T> inline
+ void check_meta_range_monotonic(const meta_range_t<T> &mr){
+ if (mr.empty()){
+ throw std::runtime_error("meta-range cannot be empty");
+ }
+ for (size_t i = 1; i < mr.size(); i++){
+ if (mr.at(i).start() < mr.at(i-1).stop()){
+ throw std::runtime_error("meta-range is not monotonic");
+ }
+ }
+ }
+ } //namespace /*anon*/
+
+
+ template <typename T> meta_range_t<T>::meta_range_t(void){
+ /* NOP */
+ }
+
+ template <typename T> template <typename InputIterator>
+ meta_range_t<T>::meta_range_t(
+ InputIterator first, InputIterator last
+ ):
+ std::vector<range_t<T> >(first, last)
+ {
+ /* NOP */
+ }
+
+ template <typename T> meta_range_t<T>::meta_range_t(
+ const T &start, const T &stop, const T &step
+ ):
+ std::vector<range_t<T> > (1, range_t<T>(start, stop, step))
+ {
+ /* NOP */
+ }
+
+ template <typename T> const T meta_range_t<T>::start(void) const{
+ check_meta_range_monotonic(*this);
+ T min_start = this->front().start();
+ BOOST_FOREACH(const range_t<T> &r, (*this)){
+ min_start = std::min(min_start, r.start());
+ }
+ return min_start;
+ }
+
+ template <typename T> const T meta_range_t<T>::stop(void) const{
+ check_meta_range_monotonic(*this);
+ T max_stop = this->front().stop();
+ BOOST_FOREACH(const range_t<T> &r, (*this)){
+ max_stop = std::max(max_stop, r.stop());
+ }
+ return max_stop;
+ }
+
+ template <typename T> const T meta_range_t<T>::step(void) const{
+ check_meta_range_monotonic(*this);
+ std::vector<T> non_zero_steps;
+ range_t<T> last = this->front();
+ BOOST_FOREACH(const range_t<T> &r, (*this)){
+ //steps at each range
+ if (r.step() > T(0)) non_zero_steps.push_back(r.step());
+ //and steps in-between ranges
+ T ibtw_step = r.start() - last.stop();
+ if (ibtw_step > T(0)) non_zero_steps.push_back(ibtw_step);
+ //store ref to last
+ last = r;
+ }
+ if (non_zero_steps.empty()) return T(0); //all zero steps, its zero...
+ return *std::min_element(non_zero_steps.begin(), non_zero_steps.end());
+ }
+
+ template <typename T> const T meta_range_t<T>::clip(
+ const T &value, bool clip_step
+ ) const{
+ check_meta_range_monotonic(*this);
+ T last_stop = this->front().stop();
+ BOOST_FOREACH(const range_t<T> &r, (*this)){
+ //in-between ranges, clip to nearest
+ if (value < r.start()){
+ return (std::abs(value - r.start()) < std::abs(value - last_stop))?
+ r.start() : last_stop;
+ }
+ //in this range, clip here
+ if (value <= r.stop()){
+ if (not clip_step or r.step() == T(0)) return value;
+ return boost::math::round((value - r.start())/r.step())*r.step() + r.start();
+ }
+ //continue on to the next range
+ last_stop = r.stop();
+ }
+ return last_stop;
+ }
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_RANGES_IPP */
diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp
index a2092f04f..977559b0b 100644
--- a/host/include/uhd/usrp/mimo_usrp.hpp
+++ b/host/include/uhd/usrp/mimo_usrp.hpp
@@ -200,7 +200,7 @@ namespace uhd{ namespace usrp{ namespace /*anon*/{
static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){
double codec_rate = dsp[DSP_PROP_CODEC_RATE].as<double>();
- return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0);
+ return freq_range_t(range.start() - codec_rate/2.0, range.stop() + codec_rate/2.0);
}
/***********************************************************************
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index e5e6a2512..8ccb664d5 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -16,7 +16,6 @@
//
#include <uhd/utils/assert.hpp>
-#include <uhd/types/ranges.hpp>
#include <uhd/types/tune_request.hpp>
#include <uhd/types/tune_result.hpp>
#include <uhd/types/clock_config.hpp>
@@ -41,24 +40,6 @@
using namespace uhd;
/***********************************************************************
- * ranges
- **********************************************************************/
-gain_range_t::gain_range_t(float min, float max, float step):
- min(min),
- max(max),
- step(step)
-{
- /* NOP */
-}
-
-freq_range_t::freq_range_t(double min, double max):
- min(min),
- max(max)
-{
- /* NOP */
-}
-
-/***********************************************************************
* tune request
**********************************************************************/
tune_request_t::tune_request_t(double target_freq):
diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp
index aa3eeb6b5..7edc1822c 100644
--- a/host/lib/usrp/dboard/db_dbsrx.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx.cpp
@@ -212,10 +212,10 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){
//set defaults for LO, gains, and filter bandwidth
_bandwidth = 33e6;
- set_lo_freq(dbsrx_freq_range.min);
+ set_lo_freq(dbsrx_freq_range.start());
BOOST_FOREACH(const std::string &name, dbsrx_gain_ranges.keys()){
- set_gain(dbsrx_gain_ranges[name].min, name);
+ set_gain(dbsrx_gain_ranges[name].start(), name);
}
set_bandwidth(33e6); // default bandwidth from datasheet
@@ -229,7 +229,7 @@ dbsrx::~dbsrx(void){
* Tuning
**********************************************************************/
void dbsrx::set_lo_freq(double target_freq){
- target_freq = std::clip(target_freq, dbsrx_freq_range.min, dbsrx_freq_range.max);
+ target_freq = dbsrx_freq_range.clip(target_freq);
double actual_freq=0.0, pfd_freq=0.0, ref_clock=0.0;
int R=0, N=0, r=0, m=0;
@@ -261,7 +261,7 @@ void dbsrx::set_lo_freq(double target_freq){
pfd_freq = ref_clock / R;
//constrain the PFD frequency to specified range
- if ((pfd_freq < dbsrx_pfd_freq_range.min) or (pfd_freq > dbsrx_pfd_freq_range.max)) continue;
+ if ((pfd_freq < dbsrx_pfd_freq_range.start()) or (pfd_freq > dbsrx_pfd_freq_range.stop())) continue;
//compute N
N = int(std::floor(target_freq/pfd_freq));
@@ -278,7 +278,7 @@ void dbsrx::set_lo_freq(double target_freq){
//Assert because we failed to find a suitable combination of ref_clock, R and N
UHD_ASSERT_THROW(ref_clock <= 27.0e6 and ref_clock >= 0.0);
UHD_ASSERT_THROW(ref_clock/m >= 1e6 and ref_clock/m <= 2.5e6);
- UHD_ASSERT_THROW((pfd_freq >= dbsrx_pfd_freq_range.min) and (pfd_freq <= dbsrx_pfd_freq_range.max));
+ UHD_ASSERT_THROW((pfd_freq >= dbsrx_pfd_freq_range.start()) and (pfd_freq <= dbsrx_pfd_freq_range.stop()));
UHD_ASSERT_THROW((N >= 256) and (N <= 32768));
if(dbsrx_debug) std::cerr << boost::format(
@@ -420,7 +420,7 @@ void dbsrx::set_lo_freq(double target_freq){
*/
static int gain_to_gc2_vga_reg(float &gain){
int reg = 0;
- gain = std::clip<float>(float(boost::math::iround(gain)), dbsrx_gain_ranges["GC2"].min, dbsrx_gain_ranges["GC2"].max);
+ gain = dbsrx_gain_ranges["GC2"].clip(gain);
// Half dB steps from 0-5dB, 1dB steps from 5-24dB
if (gain < 5) {
@@ -446,11 +446,11 @@ static int gain_to_gc2_vga_reg(float &gain){
*/
static float gain_to_gc1_rfvga_dac(float &gain){
//clip the input
- gain = std::clip<float>(gain, dbsrx_gain_ranges["GC1"].min, dbsrx_gain_ranges["GC1"].max);
+ gain = dbsrx_gain_ranges["GC1"].clip(gain);
//voltage level constants
static const float max_volts = float(1.2), min_volts = float(2.7);
- static const float slope = (max_volts-min_volts)/dbsrx_gain_ranges["GC1"].max;
+ static const float slope = (max_volts-min_volts)/dbsrx_gain_ranges["GC1"].stop();
//calculate the voltage for the aux dac
float dac_volts = gain*slope + min_volts;
diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp
index 5a65e6123..bf5528688 100644
--- a/host/lib/usrp/dboard/db_dbsrx2.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx2.cpp
@@ -195,15 +195,15 @@ dbsrx2::dbsrx2(ctor_args_t args) : rx_dboard_base(args){
//for (boost::uint8_t addr=0; addr<=12; addr++) this->send_reg(addr, addr);
//set defaults for LO, gains
- set_lo_freq(dbsrx2_freq_range.min);
+ set_lo_freq(dbsrx2_freq_range.start());
BOOST_FOREACH(const std::string &name, dbsrx2_gain_ranges.keys()){
- set_gain(dbsrx2_gain_ranges[name].min, name);
+ set_gain(dbsrx2_gain_ranges[name].start(), name);
}
set_bandwidth(40e6); // default bandwidth from datasheet
get_locked();
- _max2112_write_regs.bbg = boost::math::iround(std::clip<float>(0, dbsrx2_gain_ranges["BBG"].min, dbsrx2_gain_ranges["BBG"].max));
+ _max2112_write_regs.bbg = dbsrx2_gain_ranges["BBG"].start();
send_reg(0x9, 0x9);
}
@@ -270,7 +270,7 @@ void dbsrx2::set_lo_freq(double target_freq){
* \return 4 bit the register value
*/
static int gain_to_bbg_vga_reg(float &gain){
- int reg = boost::math::iround(std::clip<float>(gain, dbsrx2_gain_ranges["BBG"].min, dbsrx2_gain_ranges["BBG"].max));
+ int reg = boost::math::iround(dbsrx2_gain_ranges["BBG"].clip(gain));
gain = float(reg);
@@ -290,11 +290,11 @@ static int gain_to_bbg_vga_reg(float &gain){
*/
static float gain_to_gc1_rfvga_dac(float &gain){
//clip the input
- gain = std::clip<float>(gain, dbsrx2_gain_ranges["GC1"].min, dbsrx2_gain_ranges["GC1"].max);
+ gain = dbsrx2_gain_ranges["GC1"].clip(gain);
//voltage level constants
static const float max_volts = float(0.5), min_volts = float(2.7);
- static const float slope = (max_volts-min_volts)/dbsrx2_gain_ranges["GC1"].max;
+ static const float slope = (max_volts-min_volts)/dbsrx2_gain_ranges["GC1"].stop();
//calculate the voltage for the aux dac
float dac_volts = gain*slope + min_volts;
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 152198c3a..4e73fb3a3 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -93,9 +93,9 @@ public:
void tx_set(const wax::obj &key, const wax::obj &val);
private:
- freq_range_t _freq_range;
- uhd::dict<std::string, gain_range_t> _rx_gain_ranges;
- uhd::dict<dboard_iface::unit_t, bool> _div2;
+ const freq_range_t _freq_range;
+ const uhd::dict<std::string, gain_range_t> _rx_gain_ranges;
+ const uhd::dict<dboard_iface::unit_t, bool> _div2;
double _rx_lo_freq, _tx_lo_freq;
std::string _rx_ant;
uhd::dict<std::string, float> _rx_gains;
@@ -168,19 +168,17 @@ rfx_xcvr::rfx_xcvr(
ctor_args_t args,
const freq_range_t &freq_range,
bool rx_div2, bool tx_div2
-) : xcvr_dboard_base(args){
- _freq_range = freq_range;
- _div2[dboard_iface::UNIT_RX] = rx_div2;
- _div2[dboard_iface::UNIT_TX] = tx_div2;
-
- if(this->get_rx_id() == 0x0024) { //RFX400
- _rx_gain_ranges = rfx400_rx_gain_ranges;
- }
- else {
- _rx_gain_ranges = rfx_rx_gain_ranges;
- }
-
-
+):
+ xcvr_dboard_base(args),
+ _freq_range(freq_range),
+ _rx_gain_ranges((this->get_rx_id() == 0x0024)?
+ rfx400_rx_gain_ranges : rfx_rx_gain_ranges
+ ),
+ _div2(map_list_of
+ (dboard_iface::UNIT_RX, rx_div2)
+ (dboard_iface::UNIT_TX, tx_div2)
+ )
+{
//enable the clocks that we need
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true);
@@ -204,12 +202,12 @@ rfx_xcvr::rfx_xcvr(
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_RX2| MIXER_ENB);
//set some default values
- set_rx_lo_freq((_freq_range.min + _freq_range.max)/2.0);
- set_tx_lo_freq((_freq_range.min + _freq_range.max)/2.0);
+ set_rx_lo_freq((_freq_range.start() + _freq_range.stop())/2.0);
+ set_tx_lo_freq((_freq_range.start() + _freq_range.stop())/2.0);
set_rx_ant("RX2");
BOOST_FOREACH(const std::string &name, _rx_gain_ranges.keys()){
- set_rx_gain(_rx_gain_ranges[name].min, name);
+ set_rx_gain(_rx_gain_ranges[name].start(), name);
}
}
@@ -265,7 +263,7 @@ void rfx_xcvr::set_rx_gain(float gain, const std::string &name){
assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name");
if(name == "PGA0"){
float dac_volts = rx_pga0_gain_to_dac_volts(gain,
- (_rx_gain_ranges["PGA0"].max - _rx_gain_ranges["PGA0"].min));
+ (_rx_gain_ranges["PGA0"].stop() - _rx_gain_ranges["PGA0"].start()));
_rx_gains[name] = gain;
//write the new voltage to the aux dac
@@ -294,7 +292,7 @@ double rfx_xcvr::set_lo_freq(
) % (target_freq/1e6) << std::endl;
//clip the input
- target_freq = std::clip(target_freq, _freq_range.min, _freq_range.max);
+ target_freq = _freq_range.clip(target_freq);
if (_div2[unit]) target_freq *= 2;
//map prescalers to the register enums
diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp
index 2873e3d54..17fdad74a 100644
--- a/host/lib/usrp/dboard/db_tvrx.cpp
+++ b/host/lib/usrp/dboard/db_tvrx.cpp
@@ -200,12 +200,12 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){
//send initial register settings if necessary
//set default freq
- _lo_freq = tvrx_freq_range.min + tvrx_if_freq; //init _lo_freq to a sane default
- set_freq(tvrx_freq_range.min);
+ _lo_freq = tvrx_freq_range.start() + tvrx_if_freq; //init _lo_freq to a sane default
+ set_freq(tvrx_freq_range.start());
//set default gains
BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){
- set_gain(get_tvrx_gain_ranges()[name].min, name);
+ set_gain(get_tvrx_gain_ranges()[name].start(), name);
}
}
@@ -219,7 +219,7 @@ tvrx::~tvrx(void){
static std::string get_band(double freq) {
BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) {
- if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max){
+ if(freq >= tvrx_freq_ranges[band].start() && freq <= tvrx_freq_ranges[band].stop()){
if(tvrx_debug) std::cout << "Band: " << band << std::endl;
return band;
}
@@ -277,7 +277,7 @@ static double gain_interp(double gain, boost::array<double, 17> db_vector, boost
static float rf_gain_to_voltage(float gain, double lo_freq){
//clip the input
- gain = std::clip<float>(gain, get_tvrx_gain_ranges()["RF"].min, get_tvrx_gain_ranges()["RF"].max);
+ gain = get_tvrx_gain_ranges()["RF"].clip(gain);
//first we need to find out what band we're in, because gains are different across different bands
std::string band = get_band(lo_freq + tvrx_if_freq);
@@ -305,7 +305,7 @@ static float rf_gain_to_voltage(float gain, double lo_freq){
static float if_gain_to_voltage(float gain){
//clip the input
- gain = std::clip<float>(gain, get_tvrx_gain_ranges()["IF"].min, get_tvrx_gain_ranges()["IF"].max);
+ gain = get_tvrx_gain_ranges()["IF"].clip(gain);
double gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts);
double dac_volts = gain_volts / opamp_gain;
@@ -337,7 +337,7 @@ void tvrx::set_gain(float gain, const std::string &name){
*/
void tvrx::set_freq(double freq) {
- freq = std::clip<double>(freq, tvrx_freq_range.min, tvrx_freq_range.max);
+ freq = tvrx_freq_range.clip(freq);
std::string prev_band = get_band(_lo_freq - tvrx_if_freq);
std::string new_band = get_band(freq);
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 572f5de97..dd5bd600b 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -177,15 +177,15 @@ wbx_xcvr::wbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){
) % RXIO_MASK % TXIO_MASK << std::endl;
//set some default values
- set_rx_lo_freq((wbx_freq_range.min + wbx_freq_range.max)/2.0);
- set_tx_lo_freq((wbx_freq_range.min + wbx_freq_range.max)/2.0);
+ set_rx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0);
+ set_tx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0);
set_rx_ant("RX2");
BOOST_FOREACH(const std::string &name, wbx_tx_gain_ranges.keys()){
- set_tx_gain(wbx_tx_gain_ranges[name].min, name);
+ set_tx_gain(wbx_tx_gain_ranges[name].start(), name);
}
BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){
- set_rx_gain(wbx_rx_gain_ranges[name].min, name);
+ set_rx_gain(wbx_rx_gain_ranges[name].start(), name);
}
}
@@ -198,33 +198,32 @@ wbx_xcvr::~wbx_xcvr(void){
**********************************************************************/
static int rx_pga0_gain_to_iobits(float &gain){
//clip the input
- gain = std::clip<float>(gain, wbx_rx_gain_ranges["PGA0"].min, wbx_rx_gain_ranges["PGA0"].max);
+ gain = wbx_rx_gain_ranges["PGA0"].clip(gain);
//convert to attenuation and update iobits for atr
- float attn = wbx_rx_gain_ranges["PGA0"].max - gain;
+ float attn = wbx_rx_gain_ranges["PGA0"].stop() - gain;
//calculate the attenuation
- int attn_code = int(floor(attn*2));
+ int attn_code = boost::math::iround(attn*2);
int iobits = ((~attn_code) << RX_ATTN_SHIFT) & RX_ATTN_MASK;
-
if (wbx_debug) std::cerr << boost::format(
"WBX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x"
) % attn % attn_code % (iobits & RX_ATTN_MASK) % RX_ATTN_MASK << std::endl;
//the actual gain setting
- gain = wbx_rx_gain_ranges["PGA0"].max - float(attn_code)/2;
+ gain = wbx_rx_gain_ranges["PGA0"].stop() - float(attn_code)/2;
return iobits;
}
static float tx_pga0_gain_to_dac_volts(float &gain){
//clip the input
- gain = std::clip<float>(gain, wbx_tx_gain_ranges["PGA0"].min, wbx_tx_gain_ranges["PGA0"].max);
+ gain = wbx_tx_gain_ranges["PGA0"].clip(gain);
//voltage level constants
static const float max_volts = float(0.5), min_volts = float(1.4);
- static const float slope = (max_volts-min_volts)/wbx_tx_gain_ranges["PGA0"].max;
+ static const float slope = (max_volts-min_volts)/wbx_tx_gain_ranges["PGA0"].stop();
//calculate the voltage for the aux dac
float dac_volts = gain*slope + min_volts;
@@ -328,7 +327,7 @@ double wbx_xcvr::set_lo_freq(
) % (target_freq/1e6) << std::endl;
//clip the input
- target_freq = std::clip(target_freq, wbx_freq_range.min, wbx_freq_range.max);
+ target_freq = wbx_freq_range.clip(target_freq);
//map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler)
static const uhd::dict<int, int> prescaler_to_min_int_div = map_list_of
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index be0e42b92..a3a1e6242 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -72,8 +72,10 @@ using namespace boost::assign;
**********************************************************************/
static const bool xcvr2450_debug = false;
-static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9);
-static const freq_range_t xcvr_freq_band_seperation(2.5e9, 4.9e9);
+static const freq_range_t xcvr_freq_range = list_of
+ (range_t<double>(2.4e9, 2.5e9))
+ (range_t<double>(4.9e9, 6.0e9))
+;
static const prop_names_t xcvr_antennas = list_of("J1")("J2");
@@ -82,7 +84,11 @@ static const uhd::dict<std::string, gain_range_t> xcvr_tx_gain_ranges = map_list
("BB", gain_range_t(0, 5, 1.5))
;
static const uhd::dict<std::string, gain_range_t> xcvr_rx_gain_ranges = map_list_of
- ("LNA", gain_range_t(0, 30.5, 15))
+ ("LNA", gain_range_t(list_of
+ (range_t<float>(0))
+ (range_t<float>(15))
+ (range_t<float>(30.5))
+ ))
("VGA", gain_range_t(0, 62, 2.0))
;
@@ -212,10 +218,10 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){
set_rx_ant(xcvr_antennas.at(0));
set_tx_ant(xcvr_antennas.at(1));
BOOST_FOREACH(const std::string &name, xcvr_tx_gain_ranges.keys()){
- set_tx_gain(xcvr_tx_gain_ranges[name].min, name);
+ set_tx_gain(xcvr_tx_gain_ranges[name].start(), name);
}
BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){
- set_rx_gain(xcvr_rx_gain_ranges[name].min, name);
+ set_rx_gain(xcvr_rx_gain_ranges[name].start(), name);
}
}
@@ -259,17 +265,9 @@ void xcvr2450::update_atr(void){
* Tuning
**********************************************************************/
void xcvr2450::set_lo_freq(double target_freq){
- //clip for highband and lowband
- if((target_freq > xcvr_freq_band_seperation.min) and (target_freq < xcvr_freq_band_seperation.max)){
- if(target_freq - xcvr_freq_band_seperation.min < xcvr_freq_band_seperation.max - target_freq){
- target_freq = xcvr_freq_band_seperation.min;
- }else{
- target_freq = xcvr_freq_band_seperation.max;
- }
- }
- //clip for max and min
- target_freq = std::clip(target_freq, xcvr_freq_range.min, xcvr_freq_range.max);
+ //clip the input to the range
+ target_freq = xcvr_freq_range.clip(target_freq);
//variables used in the calculation below
double scaler = xcvr2450::is_highband(target_freq)? (4.0/5.0) : (4.0/3.0);
diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp
index 4aa730573..18f794632 100644
--- a/host/lib/usrp/usrp1/codec_ctrl.cpp
+++ b/host/lib/usrp/usrp1/codec_ctrl.cpp
@@ -160,19 +160,19 @@ usrp1_codec_ctrl_impl::~usrp1_codec_ctrl_impl(void)
static const int mtpgw = 255; //maximum tx pga gain word
void usrp1_codec_ctrl_impl::set_tx_pga_gain(float gain){
- int gain_word = int(mtpgw*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min));
+ int gain_word = int(mtpgw*(gain - tx_pga_gain_range.start())/(tx_pga_gain_range.stop() - tx_pga_gain_range.start()));
_ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw);
this->send_reg(16);
}
float usrp1_codec_ctrl_impl::get_tx_pga_gain(void){
- return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/mtpgw) + tx_pga_gain_range.min;
+ return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.stop() - tx_pga_gain_range.start())/mtpgw) + tx_pga_gain_range.start();
}
static const int mrpgw = 0x14; //maximum rx pga gain word
void usrp1_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){
- int gain_word = int(mrpgw*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min));
+ int gain_word = int(mrpgw*(gain - rx_pga_gain_range.start())/(rx_pga_gain_range.stop() - rx_pga_gain_range.start()));
gain_word = std::clip(gain_word, 0, mrpgw);
switch(which){
case 'A':
@@ -194,7 +194,7 @@ float usrp1_codec_ctrl_impl::get_rx_pga_gain(char which){
case 'B': gain_word = _ad9862_regs.rx_pga_b; break;
default: UHD_THROW_INVALID_CODE_PATH();
}
- return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/mrpgw) + rx_pga_gain_range.min;
+ return (gain_word*(rx_pga_gain_range.stop() - rx_pga_gain_range.start())/mrpgw) + rx_pga_gain_range.start();
}
/***********************************************************************
diff --git a/host/lib/usrp/wrapper_utils.hpp b/host/lib/usrp/wrapper_utils.hpp
index 6f9fdbfca..a7b5c5da6 100644
--- a/host/lib/usrp/wrapper_utils.hpp
+++ b/host/lib/usrp/wrapper_utils.hpp
@@ -30,7 +30,7 @@ static inline uhd::freq_range_t add_dsp_shift(
wax::obj dsp
){
double codec_rate = dsp[uhd::usrp::DSP_PROP_CODEC_RATE].as<double>();
- return uhd::freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0);
+ return uhd::freq_range_t(range.start() - codec_rate/2.0, range.stop() + codec_rate/2.0);
}
static inline void do_samp_rate_warning_message(
diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp
index 54146726a..11bbb8c0a 100644
--- a/host/lib/utils/gain_group.cpp
+++ b/host/lib/utils/gain_group.cpp
@@ -32,7 +32,7 @@ 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;
+ return fcns.at(rhs).get_range().step() > fcns.at(lhs).get_range().step();
}
/*!
@@ -69,11 +69,11 @@ public:
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;
+ overall_min += range.start();
+ overall_max += range.stop();
//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);
+ 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);
}
@@ -97,7 +97,7 @@ public:
//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);
+ max_step = std::max(max_step, fcns.get_range().step());
}
//create gain bucket to distribute power
@@ -108,7 +108,7 @@ public:
BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){
const gain_range_t range = fcns.get_range();
gain_bucket.push_back(floor_step(std::clip(
- gain_left_to_distribute, range.min, range.max
+ gain_left_to_distribute, range.start(), range.stop()
), max_step));
gain_left_to_distribute -= gain_bucket.back();
}
@@ -123,8 +123,8 @@ public:
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
+ 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)
@@ -132,8 +132,8 @@ public:
BOOST_FOREACH(size_t i, indexes_step_size_dec){
const gain_range_t range = all_fcns.at(i).get_range();
float additional_gain = floor_step(std::clip(
- gain_bucket.at(i) + gain_left_to_distribute, range.min, range.max
- ), range.step) - gain_bucket.at(i);
+ gain_bucket.at(i) + gain_left_to_distribute, range.start(), range.stop()
+ ), range.step()) - gain_bucket.at(i);
gain_bucket.at(i) += additional_gain;
gain_left_to_distribute -= additional_gain;
}
diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt
index d67399e5b..5d7433c67 100644
--- a/host/test/CMakeLists.txt
+++ b/host/test/CMakeLists.txt
@@ -26,6 +26,7 @@ SET(test_sources
dict_test.cpp
error_test.cpp
gain_group_test.cpp
+ ranges_test.cpp
subdev_spec_test.cpp
time_spec_test.cpp
tune_helper_test.cpp
diff --git a/host/test/gain_group_test.cpp b/host/test/gain_group_test.cpp
index 555ccaed3..dbb585987 100644
--- a/host/test/gain_group_test.cpp
+++ b/host/test/gain_group_test.cpp
@@ -40,7 +40,7 @@ public:
}
void set_value(float gain){
- float step = get_range().step;
+ float step = get_range().step();
_gain = step*rint(gain/step);
}
@@ -60,7 +60,7 @@ public:
}
void set_value(float gain){
- float step = get_range().step;
+ float step = get_range().step();
_gain = step*rint(gain/step);
}
@@ -102,9 +102,9 @@ BOOST_AUTO_TEST_CASE(test_gain_group_overall){
//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_CHECK_CLOSE(gg->get_range().start(), float(-20), tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().stop(), float(100), tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().step(), float(0.1), tolerance);
}
BOOST_AUTO_TEST_CASE(test_gain_group_priority){
@@ -113,10 +113,10 @@ BOOST_AUTO_TEST_CASE(test_gain_group_priority){
//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_CHECK_CLOSE(gg->get_range().start(), float(-20), tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().stop(), 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);
+ BOOST_CHECK_CLOSE(g2.get_value(), g2.get_range().stop(), tolerance);
}
diff --git a/host/test/ranges_test.cpp b/host/test/ranges_test.cpp
new file mode 100644
index 000000000..ad61867e1
--- /dev/null
+++ b/host/test/ranges_test.cpp
@@ -0,0 +1,57 @@
+//
+// 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/types/ranges.hpp>
+#include <iostream>
+
+using namespace uhd;
+
+static const double tolerance = 0.001;
+
+BOOST_AUTO_TEST_CASE(test_ranges_bounds){
+ meta_range_t<double> mr;
+ mr.push_back(range_t<double>(-1.0, +1.0, 0.1));
+ BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.stop(), +1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance);
+
+ mr.push_back(range_t<double>(40.0, 60.0, 1.0));
+ BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.stop(), 60.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance);
+
+ BOOST_CHECK_EQUAL(mr.size(), 2);
+
+ BOOST_CHECK_CLOSE(mr[0].start(), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr[0].stop(), +1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr[0].step(), 0.1, tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(test_ranges_clip){
+ meta_range_t<double> mr;
+ mr.push_back(range_t<double>(-1.0, +1.0, 0.1));
+ mr.push_back(range_t<double>(40.0, 60.0, 1.0));
+
+ BOOST_CHECK_CLOSE(mr.clip(-30.0), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(70.0), 60.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(20.0), 1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(50.0), 50.0, tolerance);
+
+ BOOST_CHECK_CLOSE(mr.clip(50.9, false), 50.9, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(50.9, true), 51.0, tolerance);
+}
diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp
index 8cea52fa6..5cba7c362 100644
--- a/host/utils/uhd_usrp_probe.cpp
+++ b/host/utils/uhd_usrp_probe.cpp
@@ -81,13 +81,13 @@ static std::string get_subdev_pp_string(const std::string &type, wax::obj subdev
ss << boost::format("Antennas: %s") % prop_names_to_pp_string(ant_names) << std::endl;
freq_range_t freq_range(subdev[usrp::SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>());
- ss << boost::format("Freq range: %.3f to %.3f Mhz") % (freq_range.min/1e6) % (freq_range.max/1e6) << std::endl;
+ ss << boost::format("Freq range: %.3f to %.3f Mhz") % (freq_range.start()/1e6) % (freq_range.stop()/1e6) << std::endl;
prop_names_t gain_names(subdev[usrp::SUBDEV_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(subdev[named_prop_t(usrp::SUBDEV_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;
+ ss << boost::format("Gain range %s: %.1f to %.1f step %.1f dB") % gain_name % gain_range.start() % gain_range.stop() % gain_range.step() << std::endl;
}
ss << boost::format("Connection Type: %c") % char(subdev[usrp::SUBDEV_PROP_CONNECTION].as<usrp::subdev_conn_t>()) << std::endl;
@@ -104,7 +104,7 @@ static std::string get_codec_pp_string(const std::string &type, wax::obj codec){
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;
+ ss << boost::format("Gain range %s: %.1f to %.1f step %.1f dB") % gain_name % gain_range.start() % gain_range.stop() % gain_range.step() << std::endl;
}
return ss.str();
}