summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/tune_helper.cpp9
-rw-r--r--host/test/tune_helper_test.cpp79
2 files changed, 82 insertions, 6 deletions
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index a6b615926..fa40a8a26 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -19,6 +19,7 @@
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dsp_props.hpp>
#include <uhd/usrp/dboard_iface.hpp> //unit_t
+#include <uhd/utils/algorithm.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <cmath>
@@ -43,9 +44,11 @@ static tune_result_t tune_xx_subdev_and_dsp(
//------------------------------------------------------------------
double lo_offset = 0.0;
if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
- //if the local oscillator will be in the passband, use an offset
- //TODO make this nicer, use bandwidth property to clip bounds
- lo_offset = 2.0*dsp[DSP_PROP_HOST_RATE].as<double>();
+ //If the local oscillator will be in the passband, use an offset.
+ //But constrain the LO offset by the width of the filter bandwidth.
+ double rate = dsp[DSP_PROP_HOST_RATE].as<double>();
+ double bw = subdev[SUBDEV_PROP_BANDWIDTH].as<double>();
+ if (bw > rate) lo_offset = std::min((bw - rate)/2, rate/2);
}
//------------------------------------------------------------------
diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp
index 1ef4af330..e0500ae3f 100644
--- a/host/test/tune_helper_test.cpp
+++ b/host/test/tune_helper_test.cpp
@@ -91,6 +91,44 @@ private:
}
};
+class dummy_subdev_bw : public wax::obj{
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ val = _freq;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = true;
+ return;
+
+ case SUBDEV_PROP_BANDWIDTH:
+ val = _bandwidth;
+ 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 = val.as<double>();
+ return;
+
+ case SUBDEV_PROP_BANDWIDTH:
+ _bandwidth = val.as<double>();
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+
+ double _freq, _bandwidth;
+};
+
class dummy_dsp : public wax::obj{
public:
dummy_dsp(double codec_rate):
@@ -106,6 +144,10 @@ private:
val = _codec_rate;
return;
+ case DSP_PROP_HOST_RATE:
+ val = _host_rate;
+ return;
+
case DSP_PROP_FREQ_SHIFT:
val = _freq_shift;
return;
@@ -125,11 +167,15 @@ private:
_freq_shift = val.as<double>();
return;
+ case DSP_PROP_HOST_RATE:
+ _host_rate = val.as<double>();
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
- double _codec_rate, _freq_shift;
+ double _codec_rate, _freq_shift, _host_rate;
};
/***********************************************************************
@@ -141,7 +187,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){
dummy_subdev subdev(1e6);
dummy_dsp dsp(100e6);
- std::cout << "Testing tune helper RX automatic LO offset" << std::endl;
+ std::cout << "Testing tune helper RX automatic IF offset" << std::endl;
tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
@@ -155,7 +201,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){
dummy_subdev subdev(1e6);
dummy_dsp dsp(100e6);
- std::cout << "Testing tune helper TX automatic LO offset" << std::endl;
+ std::cout << "Testing tune helper TX automatic IF offset" << std::endl;
tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
@@ -178,3 +224,30 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){
double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0);
BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance);
}
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){
+ dummy_subdev_bw subdev;
+ dummy_dsp dsp(100e6);
+ tune_result_t tr;
+
+ std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
+ dsp[DSP_PROP_HOST_RATE] = double(4e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance);
+
+ std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
+ dsp[DSP_PROP_HOST_RATE] = double(25e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance);
+
+ std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6);
+ dsp[DSP_PROP_HOST_RATE] = double(25e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance);
+}