diff options
author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-08-05 14:05:09 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2014-10-07 14:57:03 +0200 |
commit | 47534e78f8fe7bf01251afd9ae1f3b70c68f4f29 (patch) | |
tree | 7e0c9a2bab9909320bac9bd3ab04bded512c005d | |
parent | 800f58430fdc577a2edd717d27b5902f75a1b1e4 (diff) | |
download | uhd-47534e78f8fe7bf01251afd9ae1f3b70c68f4f29.tar.gz uhd-47534e78f8fe7bf01251afd9ae1f3b70c68f4f29.tar.bz2 uhd-47534e78f8fe7bf01251afd9ae1f3b70c68f4f29.zip |
uhd: Improved tuning code and corresponding outputs/warnings
* Added convenience function for frequency comparisons
* ABI change required
-rw-r--r-- | host/include/uhd/types/tune_result.hpp | 46 | ||||
-rw-r--r-- | host/include/uhd/version.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/multi_usrp.cpp | 159 |
3 files changed, 170 insertions, 37 deletions
diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp index e51473085..723adcfbf 100644 --- a/host/include/uhd/types/tune_result.hpp +++ b/host/include/uhd/types/tune_result.hpp @@ -24,12 +24,56 @@ namespace uhd{ /*! - * The tune result struct holds result of a 2-phase tuning. + * The tune result struct holds the RF and DSP tuned frequencies. */ struct UHD_API tune_result_t{ + /*! The target RF frequency, clipped to be within system range + * + * If the requested frequency is within the range of the system, then + * this variable will equal the requested frequency. If the requested + * frequency is outside of the tunable range, however, this variable + * will hold the value that it was 'clipped' to in order to keep tuning + * in-bounds. */ + double clipped_rf_freq; + + /*! Target RF Freq, including RF FE offset + * + * AUTO Tuning Policy: + * This variable holds the requested center frequency, plus any LO + * offset required by the radio front-end. Note that this is *not* the + * LO offset requested by the user (if one exists), but rather one + * required by the hardware (if required). + * + * MANUAL Tuning Policy: + * This variable equals the RF frequency in the tune request. */ double target_rf_freq; + + /*! The frequency to which the RF LO actually tuned + * + * If this does not equal the `target_rf_freq`, then it is because the + * target was outside of the range of the LO, or the LO was not able to + * hit it exactly due to tuning accuracy. */ double actual_rf_freq; + + /*! The frequency the CORDIC must adjust the RF + * + * AUTO Tuning Policy: + * It is fairly common for the RF LO to not be able to exactly hit the + * requested frequency. This variable holds the required adjustment the + * CORDIC must make to the signal to bring it to the requested center + * frequency. + * + * MANUAL Tuning Policy + * This variable equals the DSP frequency in the tune request, clipped + * to be within range of the DSP if it was outside. */ double target_dsp_freq; + + /*! The frequency to which the CORDIC in the DSP actually tuned + * + * If we failed to hit the target DSP frequency, it is either because + * the requested resolution wasn't possible or something went wrong in + * the DSP. In most cases, it should equal the `target_dsp_freq` above. + */ double actual_dsp_freq; /*! diff --git a/host/include/uhd/version.hpp b/host/include/uhd/version.hpp index 0a8347afe..ae583bf96 100644 --- a/host/include/uhd/version.hpp +++ b/host/include/uhd/version.hpp @@ -27,7 +27,7 @@ * The format is oldest API compatible release - ABI compat number. * The compatibility number allows pre-release ABI to be versioned. */ -#define UHD_VERSION_ABI_STRING "3.7.2-0" +#define UHD_VERSION_ABI_STRING "3.7.3-0" namespace uhd{ diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 471d453c2..ac1ec116c 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -20,6 +20,7 @@ #include <uhd/utils/msg.hpp> #include <uhd/exception.hpp> #include <uhd/utils/log.hpp> +#include <uhd/utils/math.hpp> #include <uhd/utils/gain_group.hpp> #include <uhd/usrp/dboard_id.hpp> #include <uhd/usrp/mboard_eeprom.hpp> @@ -68,23 +69,107 @@ static void do_samp_rate_warning_message( } } -static void do_tune_freq_warning_message( +static void do_tune_freq_results_message( const tune_request_t &tune_req, + const tune_result_t &tune_result, double actual_freq, const std::string &xx ){ - //forget the warning when manual policy - if (tune_req.dsp_freq_policy == tune_request_t::POLICY_MANUAL) return; + const double target_freq = tune_req.target_freq; + const double clipped_target_freq = tune_result.clipped_rf_freq; + const double target_rf_freq = tune_result.target_rf_freq; + const double actual_rf_freq = tune_result.actual_rf_freq; + const double target_dsp_freq = tune_result.target_dsp_freq; + const double actual_dsp_freq = tune_result.actual_dsp_freq; + if (tune_req.rf_freq_policy == tune_request_t::POLICY_MANUAL) return; + if (tune_req.dsp_freq_policy == tune_request_t::POLICY_MANUAL) return; - const double target_freq = tune_req.target_freq; - static const double max_allowed_error = 1.0; //Hz - if (std::abs(target_freq - actual_freq) > max_allowed_error){ - UHD_MSG(warning) << boost::format( - "The hardware does not support the requested %s frequency:\n" - "Target frequency: %f MHz\n" - "Actual frequency: %f MHz\n" - ) % xx % (target_freq/1e6) % (actual_freq/1e6); + bool requested_freq_success = uhd::math::frequencies_are_equal(target_freq, clipped_target_freq); + bool target_freq_success = uhd::math::frequencies_are_equal(clipped_target_freq, actual_freq); + bool rf_lo_tune_success = uhd::math::frequencies_are_equal(target_rf_freq, actual_rf_freq); + bool dsp_tune_success = uhd::math::frequencies_are_equal(target_dsp_freq, actual_dsp_freq); + + if(requested_freq_success and target_freq_success and rf_lo_tune_success + and dsp_tune_success) { + UHD_MSG(status) << boost::format( + "Successfully tuned to %f MHz\n\n") + % (actual_freq / 1e6); + } else { + boost::format base_message ("Tune Request: %f MHz\n"); + base_message % (target_freq / 1e6); + std::string results_string = base_message.str(); + + if(requested_freq_success and (not rf_lo_tune_success)) { + boost::format rf_lo_message( + " The RF LO does not support the requested frequency:\n" + " Requested LO Frequency: %f MHz\n" + " RF LO Result: %f MHz\n" + " Attempted to use the DSP to reach the requested frequency:\n" + " Desired DSP Frequency: %f MHz\n" + " DSP Result: %f MHz\n" + " Successfully tuned to %f MHz\n\n"); + rf_lo_message % (target_rf_freq / 1e6) % (actual_rf_freq / 1e6) + % (target_dsp_freq / 1e6) % (actual_dsp_freq / 1e6) + % (actual_freq / 1e6); + + results_string += rf_lo_message.str(); + + UHD_MSG(status) << results_string; + + return; + } + + if(not requested_freq_success) { + boost::format failure_message( + " The requested %s frequency is outside of the system range, and has been clipped:\n" + " Target Frequency: %f MHz\n" + " Clipped Target Frequency: %f MHz\n"); + failure_message % xx % (target_freq / 1e6) % (clipped_target_freq / 1e6); + + results_string += failure_message.str(); + } + + if(not rf_lo_tune_success) { + boost::format rf_lo_message( + " The RF LO does not support the requested frequency:\n" + " Requested LO Frequency: %f MHz\n" + " RF LO Result: %f MHz\n" + " Attempted to use the DSP to reach the requested frequency:\n" + " Desired DSP Frequency: %f MHz\n" + " DSP Result: %f MHz\n"); + rf_lo_message % (target_rf_freq / 1e6) % (actual_rf_freq / 1e6) + % (target_dsp_freq / 1e6) % (actual_dsp_freq / 1e6); + + results_string += rf_lo_message.str(); + + } else if(not dsp_tune_success) { + boost::format dsp_message( + " The DSP does not support the requested frequency:\n" + " Requested DSP Frequency: %f MHz\n" + " DSP Result: %f MHz\n"); + dsp_message % (target_dsp_freq / 1e6) % (actual_dsp_freq / 1e6); + + results_string += dsp_message.str(); + } + + if(target_freq_success) { + boost::format success_message( + " Successfully tuned to %f MHz\n\n"); + success_message % (actual_freq / 1e6); + + results_string += success_message.str(); + } else { + boost::format failure_message( + " Failed to tune to target frequency\n" + " Target Frequency: %f MHz\n" + " Actual Frequency: %f MHz\n\n"); + failure_message % (clipped_target_freq / 1e6) % (actual_freq / 1e6); + + results_string += failure_message.str(); + } + + UHD_MSG(warning) << results_string << std::endl; } } @@ -148,7 +233,7 @@ static tune_result_t tune_xx_subdev_and_dsp( const tune_request_t &tune_request ){ //------------------------------------------------------------------ - //-- calculate the tunable frequency range of the system + //-- calculate the tunable frequency ranges of the system //------------------------------------------------------------------ freq_range_t tune_range = make_overall_tune_range( rf_fe_subtree->access<meta_range_t>("freq/range").get(), @@ -156,6 +241,10 @@ static tune_result_t tune_xx_subdev_and_dsp( rf_fe_subtree->access<double>("bandwidth/value").get() ); + freq_range_t dsp_range = dsp_subtree->access<meta_range_t>("freq/range").get(); + + double clipped_requested_freq = tune_range.clip(tune_request.target_freq); + //------------------------------------------------------------------ //-- If the RF FE requires an LO offset, build it into the tune request //------------------------------------------------------------------ @@ -184,8 +273,7 @@ static tune_result_t tune_xx_subdev_and_dsp( //------------------------------------------------------------------ //-- poke the tune request args into the dboard //------------------------------------------------------------------ - if (rf_fe_subtree->exists("tune_args")) - { + if (rf_fe_subtree->exists("tune_args")) { rf_fe_subtree->access<device_addr_t>("tune_args").set(tune_request.args); } @@ -195,12 +283,12 @@ 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; + target_rf_freq = clipped_requested_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 + // 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. @@ -216,19 +304,17 @@ static tune_result_t tune_xx_subdev_and_dsp( break; //does not set } - /* Tune the RF front-end. */ + //------------------------------------------------------------------ + //-- Tune the RF frontend + //------------------------------------------------------------------ rf_fe_subtree->access<double>("freq/value").set(target_rf_freq); const double actual_rf_freq = rf_fe_subtree->access<double>("freq/value").get(); //------------------------------------------------------------------ - //-- set the dsp frequency depending upon the dsp frequency policy + //-- Set the DSP frequency depending upon the DSP frequency policy. //------------------------------------------------------------------ double target_dsp_freq = 0.0; - double forced_target_rf_freq = target_rf_freq; - - freq_range_t dsp_range = dsp_subtree->access<meta_range_t>("freq/range").get(); - - switch (tune_request.dsp_freq_policy){ + switch (tune_request.dsp_freq_policy) { 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 @@ -236,9 +322,7 @@ static tune_result_t tune_xx_subdev_and_dsp( * 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); + target_dsp_freq = actual_rf_freq - clipped_requested_freq; //invert the sign on the dsp freq for transmit (spinning up vs down) target_dsp_freq *= xx_sign; @@ -247,7 +331,9 @@ static tune_result_t tune_xx_subdev_and_dsp( case tune_request_t::POLICY_MANUAL: /* If the user has specified a manual tune policy, we will allow - * tuning outside of the baseband filter. */ + * tuning outside of the baseband filter, but will still clip the + * target DSP frequency to within the bounds of the CORDIC to + * prevent undefined behavior (likely an overflow). */ target_dsp_freq = dsp_range.clip(tune_request.dsp_freq); break; @@ -255,14 +341,17 @@ static tune_result_t tune_xx_subdev_and_dsp( break; //does not set } - /* Set the DSP frequency. */ + //------------------------------------------------------------------ + //-- Tune the DSP + //------------------------------------------------------------------ dsp_subtree->access<double>("freq/value").set(target_dsp_freq); const double actual_dsp_freq = dsp_subtree->access<double>("freq/value").get(); //------------------------------------------------------------------ - //-- load and return the tune result + //-- Load and return the tune result //------------------------------------------------------------------ tune_result_t tune_result; + tune_result.clipped_rf_freq = clipped_requested_freq; tune_result.target_rf_freq = target_rf_freq; tune_result.actual_rf_freq = actual_rf_freq; tune_result.target_dsp_freq = target_dsp_freq; @@ -705,12 +794,12 @@ 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, + tune_result_t result = 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; + do_tune_freq_results_message(tune_request, result, get_rx_freq(chan), "RX"); + return result; } double get_rx_freq(size_t chan){ @@ -906,12 +995,12 @@ 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, + tune_result_t result = 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; + do_tune_freq_results_message(tune_request, result, get_tx_freq(chan), "TX"); + return result; } double get_tx_freq(size_t chan){ |