summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-07-15 22:59:37 -0700
committerJosh Blum <josh@joshknows.com>2010-07-16 16:51:30 -0700
commitb25e610868752ac55b6f8e0c05bc2e0f7b18e223 (patch)
tree50ca897af5ab54b3d104a03fc9ec11058bfea55d /host
parent2ff23daec6e82661499a7cbbdea8d2ef7cc8711b (diff)
downloaduhd-b25e610868752ac55b6f8e0c05bc2e0f7b18e223.tar.gz
uhd-b25e610868752ac55b6f8e0c05bc2e0f7b18e223.tar.bz2
uhd-b25e610868752ac55b6f8e0c05bc2e0f7b18e223.zip
usrp: added functions to derive tuned frequency, tweaked logic, added unit test
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/types/tune_result.hpp10
-rw-r--r--host/include/uhd/usrp/mimo_usrp.hpp2
-rw-r--r--host/include/uhd/usrp/simple_usrp.hpp2
-rw-r--r--host/include/uhd/usrp/tune_helper.hpp112
-rw-r--r--host/lib/types.cpp19
-rw-r--r--host/lib/usrp/mimo_usrp.cpp16
-rw-r--r--host/lib/usrp/simple_usrp.cpp16
-rw-r--r--host/lib/usrp/tune_helper.cpp99
-rw-r--r--host/test/CMakeLists.txt1
-rw-r--r--host/test/tune_helper_test.cpp136
10 files changed, 311 insertions, 102 deletions
diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp
index c428a7692..9eebc161a 100644
--- a/host/include/uhd/types/tune_result.hpp
+++ b/host/include/uhd/types/tune_result.hpp
@@ -19,6 +19,7 @@
#define INCLUDED_UHD_TYPES_TUNE_RESULT_HPP
#include <uhd/config.hpp>
+#include <string>
namespace uhd{
@@ -28,15 +29,18 @@ namespace uhd{
* the target and actual intermediate frequency.
* The struct hold the result of tuning the DSP as
* the target and actual digital converter frequency.
- * It also tell us weather or not the spectrum is inverted.
*/
struct UHD_API tune_result_t{
double target_inter_freq;
double actual_inter_freq;
double target_dsp_freq;
double actual_dsp_freq;
- bool spectrum_inverted;
- tune_result_t(void);
+
+ /*!
+ * Create a pretty print string for this tune result struct.
+ * \return the printable string
+ */
+ std::string to_pp_string(void) const;
};
} //namespace uhd
diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp
index 68a42cad8..fd0f4596f 100644
--- a/host/include/uhd/usrp/mimo_usrp.hpp
+++ b/host/include/uhd/usrp/mimo_usrp.hpp
@@ -124,6 +124,7 @@ public:
virtual tune_result_t set_rx_freq(size_t chan, double freq) = 0;
virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0;
+ virtual double get_rx_freq(size_t chan) = 0;
virtual freq_range_t get_rx_freq_range(size_t chan) = 0;
virtual void set_rx_gain(size_t chan, float gain) = 0;
@@ -152,6 +153,7 @@ public:
virtual tune_result_t set_tx_freq(size_t chan, double freq) = 0;
virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0;
+ virtual double get_tx_freq(size_t chan) = 0;
virtual freq_range_t get_tx_freq_range(size_t chan) = 0;
virtual void set_tx_gain(size_t chan, float gain) = 0;
diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp
index 1d9136f08..a100579ce 100644
--- a/host/include/uhd/usrp/simple_usrp.hpp
+++ b/host/include/uhd/usrp/simple_usrp.hpp
@@ -112,6 +112,7 @@ public:
virtual tune_result_t set_rx_freq(double freq) = 0;
virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0;
+ virtual double get_rx_freq(void) = 0;
virtual freq_range_t get_rx_freq_range(void) = 0;
virtual void set_rx_gain(float gain) = 0;
@@ -139,6 +140,7 @@ public:
virtual tune_result_t set_tx_freq(double freq) = 0;
virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0;
+ virtual double get_tx_freq(void) = 0;
virtual freq_range_t get_tx_freq_range(void) = 0;
virtual void set_tx_gain(float gain) = 0;
diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp
index f1e276d4f..df3907b3e 100644
--- a/host/include/uhd/usrp/tune_helper.hpp
+++ b/host/include/uhd/usrp/tune_helper.hpp
@@ -24,55 +24,75 @@
namespace uhd{ namespace usrp{
-/*!
- * Tune a rx chain to the desired frequency:
- * The IF of the subdevice is set as close as possible to
- * the given target frequency + the LO offset (when applicable).
- * The ddc cordic is setup to bring the IF down to baseband.
- * \param subdev the dboard subdevice object with properties
- * \param ddc the ddc properties object (with "if_rate", "bb_rate", "freq")
- * \param target_freq the desired center frequency
- * \param lo_offset an offset for the subdevice IF from center
- * \return a tune result struct
- */
-UHD_API tune_result_t tune_rx_subdev_and_ddc(
- wax::obj subdev, wax::obj ddc,
- double target_freq, double lo_offset
-);
+ /*!
+ * Tune a rx chain to the desired frequency:
+ * The IF of the subdevice is set as close as possible to
+ * the given target frequency + the LO offset (when applicable).
+ * The ddc cordic is setup to bring the IF down to baseband.
+ * \param subdev the dboard subdevice object with properties
+ * \param ddc the mboard dsp object with properties
+ * \param target_freq the desired center frequency
+ * \param lo_offset an offset for the subdevice IF from center
+ * \return a tune result struct
+ */
+ UHD_API tune_result_t tune_rx_subdev_and_dsp(
+ wax::obj subdev, wax::obj ddc,
+ double target_freq, double lo_offset
+ );
-/*!
- * Tune a rx chain to the desired frequency:
- * Same as the above, except the LO offset
- * is calculated based on the subdevice and BW.
- */
-UHD_API tune_result_t tune_rx_subdev_and_ddc(
- wax::obj subdev, wax::obj ddc, double target_freq
-);
+ /*!
+ * Tune a rx chain to the desired frequency:
+ * Same as the above, except the LO offset
+ * is calculated based on the subdevice and BW.
+ */
+ UHD_API tune_result_t tune_rx_subdev_and_dsp(
+ wax::obj subdev, wax::obj ddc, double target_freq
+ );
-/*!
- * Tune a tx chain to the desired frequency:
- * The IF of the subdevice is set as close as possible to
- * the given target frequency + the LO offset (when applicable).
- * The duc cordic is setup to bring the baseband up to IF.
- * \param subdev the dboard subdevice object with properties
- * \param duc the duc properties object (with "if_rate", "bb_rate", "freq")
- * \param target_freq the desired center frequency
- * \param lo_offset an offset for the subdevice IF from center
- * \return a tune result struct
- */
-UHD_API tune_result_t tune_tx_subdev_and_duc(
- wax::obj subdev, wax::obj duc,
- double target_freq, double lo_offset
-);
+ /*!
+ * Calculate the overall frequency from the combination of dboard IF and DDC shift.
+ * \param subdev the dboard subdevice object with properties
+ * \param ddc the mboard dsp object with properties
+ * \return the overall tune frequency of the system in Hz
+ */
+ UHD_API double derive_freq_from_rx_subdev_and_dsp(
+ wax::obj subdev, wax::obj ddc
+ );
-/*!
- * Tune a tx chain to the desired frequency:
- * Same as the above, except the LO offset
- * is calculated based on the subdevice and BW.
- */
-UHD_API tune_result_t tune_tx_subdev_and_duc(
- wax::obj subdev, wax::obj duc, double target_freq
-);
+ /*!
+ * Tune a tx chain to the desired frequency:
+ * The IF of the subdevice is set as close as possible to
+ * the given target frequency + the LO offset (when applicable).
+ * The duc cordic is setup to bring the baseband up to IF.
+ * \param subdev the dboard subdevice object with properties
+ * \param duc the mboard dsp object with properties
+ * \param target_freq the desired center frequency
+ * \param lo_offset an offset for the subdevice IF from center
+ * \return a tune result struct
+ */
+ UHD_API tune_result_t tune_tx_subdev_and_dsp(
+ wax::obj subdev, wax::obj duc,
+ double target_freq, double lo_offset
+ );
+
+ /*!
+ * Tune a tx chain to the desired frequency:
+ * Same as the above, except the LO offset
+ * is calculated based on the subdevice and BW.
+ */
+ UHD_API tune_result_t tune_tx_subdev_and_dsp(
+ wax::obj subdev, wax::obj duc, double target_freq
+ );
+
+ /*!
+ * Calculate the overall frequency from the combination of dboard IF and DUC shift.
+ * \param subdev the dboard subdevice object with properties
+ * \param duc the mboard dsp object with properties
+ * \return the overall tune frequency of the system in Hz
+ */
+ UHD_API double derive_freq_from_tx_subdev_and_dsp(
+ wax::obj subdev, wax::obj duc
+ );
}}
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index e0ce61058..fdc435fef 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -60,14 +60,17 @@ freq_range_t::freq_range_t(double min, double max):
/***********************************************************************
* tune result
**********************************************************************/
-tune_result_t::tune_result_t(void):
- target_inter_freq(0.0),
- actual_inter_freq(0.0),
- target_dsp_freq(0.0),
- actual_dsp_freq(0.0),
- spectrum_inverted(false)
-{
- /* NOP */
+std::string tune_result_t::to_pp_string(void) const{
+ return str(boost::format(
+ "Tune Result:\n"
+ " Target Intermediate Freq: %f (MHz)\n"
+ " Actual Intermediate Freq: %f (MHz)\n"
+ " Target DSP Freq Shift: %f (MHz)\n"
+ " Actual DSP Freq Shift: %f (MHz)\n"
+ )
+ % (target_inter_freq/1e6) % (actual_inter_freq/1e6)
+ % (target_dsp_freq/1e6) % (actual_dsp_freq/1e6)
+ );
}
/***********************************************************************
diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp
index fbb863022..ec0f1dcc8 100644
--- a/host/lib/usrp/mimo_usrp.cpp
+++ b/host/lib/usrp/mimo_usrp.cpp
@@ -185,11 +185,15 @@ public:
}
tune_result_t set_rx_freq(size_t chan, double target_freq){
- return tune_rx_subdev_and_ddc(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq);
+ return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq);
}
tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){
- return tune_rx_subdev_and_ddc(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq, lo_off);
+ return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq, lo_off);
+ }
+
+ double get_rx_freq(size_t chan){
+ return derive_freq_from_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan));
}
freq_range_t get_rx_freq_range(size_t chan){
@@ -248,11 +252,15 @@ public:
}
tune_result_t set_tx_freq(size_t chan, double target_freq){
- return tune_tx_subdev_and_duc(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq);
+ return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq);
}
tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){
- return tune_tx_subdev_and_duc(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq, lo_off);
+ return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq, lo_off);
+ }
+
+ double get_tx_freq(size_t chan){
+ return derive_freq_from_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan));
}
freq_range_t get_tx_freq_range(size_t chan){
diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp
index f06cc9135..5cb9511f4 100644
--- a/host/lib/usrp/simple_usrp.cpp
+++ b/host/lib/usrp/simple_usrp.cpp
@@ -123,11 +123,15 @@ public:
}
tune_result_t set_rx_freq(double target_freq){
- return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq);
+ return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq);
}
tune_result_t set_rx_freq(double target_freq, double lo_off){
- return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq, lo_off);
+ return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq, lo_off);
+ }
+
+ double get_rx_freq(void){
+ return derive_freq_from_rx_subdev_and_dsp(_rx_subdev, _rx_dsp);
}
freq_range_t get_rx_freq_range(void){
@@ -178,11 +182,15 @@ public:
}
tune_result_t set_tx_freq(double target_freq){
- return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq);
+ return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq);
}
tune_result_t set_tx_freq(double target_freq, double lo_off){
- return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq, lo_off);
+ return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq, lo_off);
+ }
+
+ double get_tx_freq(void){
+ return derive_freq_from_tx_subdev_and_dsp(_tx_subdev, _tx_dsp);
}
freq_range_t get_tx_freq_range(void){
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index 082c39f6d..1d584913c 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -19,16 +19,28 @@
#include <uhd/utils/algorithm.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dsp_props.hpp>
+#include <uhd/usrp/dboard_iface.hpp> //unit_t
#include <cmath>
using namespace uhd;
using namespace uhd::usrp;
/***********************************************************************
- * Tune Helper Function
+ * Tune Helper Functions
**********************************************************************/
+static bool invert_dxc_freq(
+ bool outside_of_nyquist,
+ bool subdev_spectrum_inverted,
+ bool subdev_quadrature,
+ dboard_iface::unit_t unit
+){
+ bool is_tx = unit == dboard_iface::UNIT_TX;
+ if (subdev_quadrature) return is_tx;
+ return outside_of_nyquist xor subdev_spectrum_inverted xor is_tx;
+}
+
static tune_result_t tune_xx_subdev_and_dxc(
- bool is_tx,
+ dboard_iface::unit_t unit,
wax::obj subdev, wax::obj dxc,
double target_freq, double lo_offset
){
@@ -43,55 +55,61 @@ static tune_result_t tune_xx_subdev_and_dxc(
subdev_freq_proxy = target_inter_freq;
double actual_inter_freq = subdev_freq_proxy.as<double>();
- // Calculate the DDC setting that will downconvert the baseband from the
- // daughterboard to our target frequency.
- double delta_freq = target_freq - actual_inter_freq;
- int delta_sign = std::signum(delta_freq);
- delta_freq *= delta_sign;
- delta_freq = std::fmod(delta_freq, dxc_sample_rate);
- bool inverted = delta_freq > dxc_sample_rate/2.0;
- double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq);
- target_dxc_freq *= delta_sign;
-
- // If the spectrum is inverted, and the daughterboard doesn't do
- // quadrature downconversion, we can fix the inversion by flipping the
- // sign of the dxc_freq... (This only happens using the basic_rx board)
- if (subdev_spectrum_inverted){
- inverted = not inverted;
- }
- if (inverted and not subdev_quadrature){
- target_dxc_freq *= -1.0;
- inverted = not inverted;
- }
- // down conversion versus up conversion, fight!
- // your mother is ugly and your going down...
- target_dxc_freq *= (is_tx)? -1.0 : +1.0;
+ //perform the correction correction for dxc rates outside of nyquist
+ double target_dxc_freq = std::fmod(target_freq - actual_inter_freq, dxc_sample_rate);
+ if (target_dxc_freq >= dxc_sample_rate/2.0) target_dxc_freq -= dxc_sample_rate;
+ else if (target_dxc_freq < -dxc_sample_rate/2.0) target_dxc_freq += dxc_sample_rate;
+ else target_dxc_freq *= -1.0;
+
+ //invert the sign on the dxc freq given the following conditions
+ bool outside_of_nyquist = std::abs(target_freq - actual_inter_freq) > dxc_sample_rate/2.0;
+ if (invert_dxc_freq(
+ outside_of_nyquist, subdev_spectrum_inverted, subdev_quadrature, unit
+ )) target_dxc_freq *= -1.0;
dxc_freq_proxy = target_dxc_freq;
double actual_dxc_freq = dxc_freq_proxy.as<double>();
- //return some kind of tune result tuple/struct
+ //load and return the tune result
tune_result_t tune_result;
tune_result.target_inter_freq = target_inter_freq;
tune_result.actual_inter_freq = actual_inter_freq;
tune_result.target_dsp_freq = target_dxc_freq;
tune_result.actual_dsp_freq = actual_dxc_freq;
- tune_result.spectrum_inverted = inverted;
return tune_result;
}
+static double derive_freq_from_xx_subdev_and_dxc(
+ dboard_iface::unit_t unit,
+ wax::obj subdev, wax::obj dxc
+){
+ //extract subdev properties
+ bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
+ bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>();
+
+ //extract actual dsp and IF frequencies
+ double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>();
+ double actual_dxc_freq = dxc[DSP_PROP_FREQ_SHIFT].as<double>();
+
+ //invert the sign on the dxc freq given the following conditions
+ if (invert_dxc_freq(
+ false, subdev_spectrum_inverted, subdev_quadrature, unit
+ )) actual_dxc_freq *= -1.0;
+
+ return actual_inter_freq - actual_dxc_freq;
+}
+
/***********************************************************************
* RX Tune
**********************************************************************/
-tune_result_t uhd::usrp::tune_rx_subdev_and_ddc(
+tune_result_t usrp::tune_rx_subdev_and_dsp(
wax::obj subdev, wax::obj ddc,
double target_freq, double lo_offset
){
- bool is_tx = false;
- return tune_xx_subdev_and_dxc(is_tx, subdev, ddc, target_freq, lo_offset);
+ return tune_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, target_freq, lo_offset);
}
-tune_result_t uhd::usrp::tune_rx_subdev_and_ddc(
+tune_result_t usrp::tune_rx_subdev_and_dsp(
wax::obj subdev, wax::obj ddc,
double target_freq
){
@@ -100,21 +118,24 @@ tune_result_t uhd::usrp::tune_rx_subdev_and_ddc(
if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
lo_offset = 2.0*ddc[DSP_PROP_HOST_RATE].as<double>();
}
- return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset);
+ return tune_rx_subdev_and_dsp(subdev, ddc, target_freq, lo_offset);
+}
+
+double usrp::derive_freq_from_rx_subdev_and_dsp(wax::obj subdev, wax::obj ddc){
+ return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc);
}
/***********************************************************************
* TX Tune
**********************************************************************/
-tune_result_t uhd::usrp::tune_tx_subdev_and_duc(
+tune_result_t usrp::tune_tx_subdev_and_dsp(
wax::obj subdev, wax::obj duc,
double target_freq, double lo_offset
){
- bool is_tx = true;
- return tune_xx_subdev_and_dxc(is_tx, subdev, duc, target_freq, lo_offset);
+ return tune_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, target_freq, lo_offset);
}
-tune_result_t uhd::usrp::tune_tx_subdev_and_duc(
+tune_result_t usrp::tune_tx_subdev_and_dsp(
wax::obj subdev, wax::obj duc,
double target_freq
){
@@ -123,5 +144,9 @@ tune_result_t uhd::usrp::tune_tx_subdev_and_duc(
if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
lo_offset = 2.0*duc[DSP_PROP_HOST_RATE].as<double>();
}
- return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset);
+ return tune_tx_subdev_and_dsp(subdev, duc, target_freq, lo_offset);
+}
+
+double usrp::derive_freq_from_tx_subdev_and_dsp(wax::obj subdev, wax::obj duc){
+ return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc);
}
diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt
index 74f3376e6..b7dcb741a 100644
--- a/host/test/CMakeLists.txt
+++ b/host/test/CMakeLists.txt
@@ -27,6 +27,7 @@ ADD_EXECUTABLE(main_test
dict_test.cpp
error_test.cpp
gain_handler_test.cpp
+ tune_helper_test.cpp
vrt_test.cpp
wax_test.cpp
)
diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp
new file mode 100644
index 000000000..e9fb93081
--- /dev/null
+++ b/host/test/tune_helper_test.cpp
@@ -0,0 +1,136 @@
+//
+// 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/usrp/tune_helper.hpp>
+#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/usrp/dsp_props.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Dummy properties objects
+ **********************************************************************/
+class dummy_subdev : public wax::obj{
+public:
+ dummy_subdev(bool is_quadrature, bool is_spectrum_inverted, double resolution):
+ _is_quadrature(is_quadrature),
+ _is_spectrum_inverted(is_spectrum_inverted),
+ _resolution(resolution)
+ {
+ /* NOP */
+ }
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_QUADRATURE:
+ val = _is_quadrature;
+ return;
+
+ case SUBDEV_PROP_SPECTRUM_INVERTED:
+ val = _is_spectrum_inverted;
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ val = _freq;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key, const wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_FREQ:
+ _freq = _resolution*int(val.as<double>()/_resolution);
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+
+ bool _is_quadrature, _is_spectrum_inverted;
+ double _freq, _resolution;
+};
+
+class dummy_dsp : public wax::obj{
+public:
+ dummy_dsp(double codec_rate):
+ _codec_rate(codec_rate)
+ {
+ /* NOP */
+ }
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_CODEC_RATE:
+ val = _codec_rate;
+ return;
+
+ case DSP_PROP_FREQ_SHIFT:
+ val = _freq_shift;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key, const wax::obj &val){
+ switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_FREQ_SHIFT:
+ _freq_shift = val.as<double>();
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+
+ double _codec_rate, _freq_shift;
+};
+
+/***********************************************************************
+ * Tests
+ **********************************************************************/
+static const double tolerance = 0.001;
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_rx){
+ dummy_subdev subdev(true, false, 1e6);
+ dummy_dsp dsp(100e6);
+
+ std::cout << "Testing tune helper RX automatic LO offset" << std::endl;
+ tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
+ BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_tx){
+ dummy_subdev subdev(true, false, 1e6);
+ dummy_dsp dsp(100e6);
+
+ std::cout << "Testing tune helper TX automatic LO offset" << std::endl;
+ tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
+ BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance);
+}