aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
authorBen Hilburn <ben.hilburn@ettus.com>2014-06-20 18:43:27 -0700
committerMartin Braun <martin.braun@ettus.com>2014-10-07 13:58:12 +0200
commitfe88d8065371f01b61cd14e10e8f9cfd184480f3 (patch)
tree9683af6a8dbd8d4ff78a15dfd8beea1f5828b3fa /host/lib/usrp
parentc8454c9f6a63430783874a0304d284aedc39ada0 (diff)
downloaduhd-fe88d8065371f01b61cd14e10e8f9cfd184480f3.tar.gz
uhd-fe88d8065371f01b61cd14e10e8f9cfd184480f3.tar.bz2
uhd-fe88d8065371f01b61cd14e10e8f9cfd184480f3.zip
significant changes to multi_usrp tuning algorithms - changing DSP tuning
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/multi_usrp.cpp144
1 files changed, 107 insertions, 37 deletions
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 80f61935c..53530d05f 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -30,6 +30,7 @@
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <cmath>
+#include <iostream>
using namespace uhd;
using namespace uhd::usrp;
@@ -88,11 +89,22 @@ static void do_tune_freq_warning_message(
}
}
+/*! The CORDIC can be used to shift the baseband below / past the tunable
+ * limits of the actual RF front-end. The baseband filter, located on the
+ * daughterboard, however, limits the useful instantaneous bandwidth. We
+ * allow the user to tune to the edge of the filter, where the roll-off
+ * begins. This prevents the user from tuning past the point where less
+ * than half of the spectrum would be useful. */
static meta_range_t make_overall_tune_range(
const meta_range_t &fe_range,
const meta_range_t &dsp_range,
const double bw
){
+ std::cout << "Entering make_overall_tune_range..." << std::endl;
+ UHD_VAR(dsp_range.start());
+ UHD_VAR(dsp_range.stop());
+ UHD_VAR(bw);
+
meta_range_t range;
BOOST_FOREACH(const range_t &sub_range, fe_range){
range.push_back(range_t(
@@ -142,12 +154,31 @@ static tune_result_t tune_xx_subdev_and_dsp(
const tune_request_t &tune_request
){
//------------------------------------------------------------------
- //-- calculate the LO offset, only used with automatic policy
+ //-- calculate the tunable frequency range of the system
+ //------------------------------------------------------------------
+ freq_range_t tune_range = make_overall_tune_range(
+ rf_fe_subtree->access<meta_range_t>("freq/range").get(),
+ dsp_subtree->access<meta_range_t>("freq/range").get(),
+ rf_fe_subtree->access<double>("bandwidth/value").get()
+ );
+
//------------------------------------------------------------------
+ //-- If the RF FE requires an LO offset, build it into the tune request
+ //------------------------------------------------------------------
+
+ /*! The automatically calculated LO offset is only used if the
+ * 'use_lo_offset' field in the daughterboard property tree is set to TRUE,
+ * and the tune policy is set to AUTO. To use an LO offset normally, the
+ * user should specify the MANUAL tune policy and lo_offset as part of the
+ * tune_request. This lo_offset is based on the requirements of the FE, and
+ * does not reflect a user-requested lo_offset, which is handled later. */
double lo_offset = 0.0;
if (rf_fe_subtree->access<bool>("use_lo_offset").get()){
- //If the frontend has lo_offset value and range properties, trust it for lo_offset
- if (rf_fe_subtree->exists("lo_offset/value")) lo_offset = rf_fe_subtree->access<double>("lo_offset/value").get();
+ // If the frontend has lo_offset value and range properties, trust it
+ // for lo_offset
+ if (rf_fe_subtree->exists("lo_offset/value")) {
+ lo_offset = rf_fe_subtree->access<double>("lo_offset/value").get();
+ }
//If the local oscillator will be in the passband, use an offset.
//But constrain the LO offset by the width of the filter bandwidth.
@@ -169,53 +200,83 @@ static tune_result_t tune_xx_subdev_and_dsp(
//------------------------------------------------------------------
double target_rf_freq = 0.0;
switch (tune_request.rf_freq_policy){
- case tune_request_t::POLICY_AUTO:
- target_rf_freq = tune_request.target_freq + lo_offset;
- rf_fe_subtree->access<double>("freq/value").set(target_rf_freq);
- break;
-
- case tune_request_t::POLICY_MANUAL:
- //If the rf_fe understands lo_offset settings, infer the desired lo_offset and set it
- // Side effect: In TVRX2 for example, after setting the lo_offset (if_freq) with a
- // POLICY_MANUAL, there is no way for the user to automatically get back to default
- // if_freq without deconstruct/reconstruct the rf_fe objects.
- if (rf_fe_subtree->exists("lo_offset/value")) {
- rf_fe_subtree->access<double>("lo_offset/value").set(tune_request.rf_freq - tune_request.target_freq);
- }
+ case tune_request_t::POLICY_AUTO:
+ target_rf_freq = tune_request.target_freq + lo_offset;
+ break;
+
+ case tune_request_t::POLICY_MANUAL:
+ // If the rf_fe understands lo_offset settings, infer the desired
+ // lo_offset and set it Side effect: In TVRX2 for example, after
+ // setting the lo_offset (if_freq) with a POLICY_MANUAL, there is no
+ // way for the user to automatically get back to default if_freq
+ // without deconstruct/reconstruct the rf_fe objects.
+ if (rf_fe_subtree->exists("lo_offset/value")) {
+ rf_fe_subtree->access<double>("lo_offset/value")
+ .set(tune_request.rf_freq - tune_request.target_freq);
+ }
- target_rf_freq = tune_request.rf_freq;
- rf_fe_subtree->access<double>("freq/value").set(target_rf_freq);
- break;
+ target_rf_freq = tune_request.rf_freq;
+ break;
- case tune_request_t::POLICY_NONE: break; //does not set
+ case tune_request_t::POLICY_NONE:
+ break; //does not set
}
- const double actual_rf_freq = rf_fe_subtree->access<double>("freq/value").get();
- //------------------------------------------------------------------
- //-- calculate the dsp freq, only used with automatic policy
- //------------------------------------------------------------------
- double target_dsp_freq = actual_rf_freq - tune_request.target_freq;
+ /* Tune the RF front-end. */
+ rf_fe_subtree->access<double>("freq/value").set(target_rf_freq);
+ const double actual_rf_freq = rf_fe_subtree->access<double>("freq/value").get();
- //invert the sign on the dsp freq for transmit
- target_dsp_freq *= xx_sign;
+ std::cout << "multi_usrp - done tuning FE..." << std::endl;
+ UHD_VAR(target_rf_freq);
+ UHD_VAR(actual_rf_freq);
//------------------------------------------------------------------
//-- set the dsp frequency depending upon the dsp frequency policy
//------------------------------------------------------------------
+ double target_dsp_freq = 0.0;
+ double forced_target_rf_freq = target_rf_freq;
+
+ UHD_VAR(tune_range.start());
+ UHD_VAR(tune_range.stop());
+
+ freq_range_t dsp_range = dsp_subtree->access<meta_range_t>("freq/range").get();
+
switch (tune_request.dsp_freq_policy){
- case tune_request_t::POLICY_AUTO:
- dsp_subtree->access<double>("freq/value").set(target_dsp_freq);
- break;
+ case tune_request_t::POLICY_AUTO:
+ /* If we are using the AUTO tuning policy, then we prevent the
+ * CORDIC from spinning us outside of the range of the baseband
+ * filter, regardless of what the user requested. This could happen
+ * if the user requested a center frequency so far outside of the
+ * tunable range of the FE that the CORDIC would spin outside the
+ * filtered baseband. */
+ forced_target_rf_freq = tune_range.clip(target_rf_freq);
+
+ target_dsp_freq = dsp_range.clip(actual_rf_freq - forced_target_rf_freq);
- case tune_request_t::POLICY_MANUAL:
- target_dsp_freq = tune_request.dsp_freq;
- dsp_subtree->access<double>("freq/value").set(target_dsp_freq);
- break;
+ //invert the sign on the dsp freq for transmit (spinning up vs down)
+ target_dsp_freq *= xx_sign;
- case tune_request_t::POLICY_NONE: break; //does not set
+ break;
+
+ case tune_request_t::POLICY_MANUAL:
+ /* If the user has specified a manual tune policy, we will allow
+ * tuning outside of the baseband filter. */
+ target_dsp_freq = dsp_range.clip(tune_request.dsp_freq);
+ break;
+
+ case tune_request_t::POLICY_NONE:
+ break; //does not set
}
+
+ UHD_VAR(forced_target_rf_freq);
+ UHD_VAR(target_dsp_freq);
+
+ /* Set the DSP frequency. */
+ dsp_subtree->access<double>("freq/value").set(target_dsp_freq);
const double actual_dsp_freq = dsp_subtree->access<double>("freq/value").get();
+ UHD_VAR(actual_dsp_freq);
+
//------------------------------------------------------------------
//-- load and return the tune result
//------------------------------------------------------------------
@@ -236,6 +297,9 @@ static double derive_freq_from_xx_subdev_and_dsp(
const double actual_rf_freq = rf_fe_subtree->access<double>("freq/value").get();
const double actual_dsp_freq = dsp_subtree->access<double>("freq/value").get();
+ UHD_VAR(actual_rf_freq);
+ UHD_VAR(actual_dsp_freq);
+
//invert the sign on the dsp freq for transmit
return actual_rf_freq - actual_dsp_freq * xx_sign;
}
@@ -662,7 +726,10 @@ public:
}
tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){
- tune_result_t r = tune_xx_subdev_and_dsp(RX_SIGN, _tree->subtree(rx_dsp_root(chan)), _tree->subtree(rx_rf_fe_root(chan)), tune_request);
+ tune_result_t r = tune_xx_subdev_and_dsp(RX_SIGN,
+ _tree->subtree(rx_dsp_root(chan)),
+ _tree->subtree(rx_rf_fe_root(chan)),
+ tune_request);
do_tune_freq_warning_message(tune_request, get_rx_freq(chan), "RX");
return r;
}
@@ -860,7 +927,10 @@ public:
}
tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){
- tune_result_t r = tune_xx_subdev_and_dsp(TX_SIGN, _tree->subtree(tx_dsp_root(chan)), _tree->subtree(tx_rf_fe_root(chan)), tune_request);
+ tune_result_t r = tune_xx_subdev_and_dsp(TX_SIGN,
+ _tree->subtree(tx_dsp_root(chan)),
+ _tree->subtree(tx_rf_fe_root(chan)),
+ tune_request);
do_tune_freq_warning_message(tune_request, get_tx_freq(chan), "TX");
return r;
}