diff options
author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-06-20 18:43:27 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2014-10-07 13:58:12 +0200 |
commit | fe88d8065371f01b61cd14e10e8f9cfd184480f3 (patch) | |
tree | 9683af6a8dbd8d4ff78a15dfd8beea1f5828b3fa /host/lib | |
parent | c8454c9f6a63430783874a0304d284aedc39ada0 (diff) | |
download | uhd-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')
-rw-r--r-- | host/lib/usrp/multi_usrp.cpp | 144 |
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; } |