From 55d792f85fae26b51e059cca5e5a62807f4b3fcf Mon Sep 17 00:00:00 2001 From: Tom Tsou Date: Tue, 23 Jun 2015 12:09:51 -0700 Subject: ad9361: Use separate Tx and RX frequency calibration intervals Patch addresses issue: #872 "B200: Tx and Rx calibration share same frequency state" ADI specifies recalibration for certain paths when the LO shifts by more than 100 MHz. Tx and Rx maintain independent LO frequencies so use separate values for determining whether to perform re-calibration at tuning intervals. Also, maintain last calibration frequencies from initialization and clock rate changes. Doing so prevents a re-calibration if the first requested Tx or Rx frequency is close to the default values of 850 and 800 MHz respectively. Signed-off-by: Tom Tsou --- .../usrp/common/ad9361_driver/ad9361_device.cpp | 54 ++++++++++++++-------- host/lib/usrp/common/ad9361_driver/ad9361_device.h | 4 +- 2 files changed, 39 insertions(+), 19 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index 4ceccc0d9..0505343ab 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -96,6 +96,10 @@ const double ad9361_device_t::AD9361_CAL_VALID_WINDOW = 100e6; // Max bandwdith is due to filter rolloff in analog filter stage const double ad9361_device_t::AD9361_RECOMMENDED_MAX_BANDWIDTH = 56e6; +/* Startup RF frequencies */ +const double ad9361_device_t::DEFAULT_RX_FREQ = 800e6; +const double ad9361_device_t::DEFAULT_TX_FREQ = 850e6; + /* Program either the RX or TX FIR filter. * * The process is the same for both filters, but the function must be told @@ -1527,8 +1531,8 @@ void ad9361_device_t::initialize() _regs.bbftune_mode = 0x1e; /* Initialize private VRQ fields. */ - _rx_freq = 0.0; - _tx_freq = 0.0; + _rx_freq = DEFAULT_RX_FREQ; + _tx_freq = DEFAULT_TX_FREQ; _req_rx_freq = 0.0; _req_tx_freq = 0.0; _baseband_bw = 0.0; @@ -1548,7 +1552,6 @@ void ad9361_device_t::initialize() _rx2_agc_mode = GAIN_MODE_SLOW_AGC; _rx1_agc_enable = false; _rx2_agc_enable = false; - _last_calibration_freq = -AD9361_CAL_VALID_WINDOW; _rx_analog_bw = 0; _tx_analog_bw = 0; _rx_tia_lp_bw = 0; @@ -1700,8 +1703,8 @@ void ad9361_device_t::initialize() _calibrate_synth_charge_pumps(); - _tune_helper(RX, 800e6); - _tune_helper(TX, 850e6); + _tune_helper(RX, _rx_freq); + _tune_helper(TX, _tx_freq); _program_mixer_gm_subtable(); _program_gain_table(); @@ -1726,6 +1729,9 @@ void ad9361_device_t::initialize() if (_use_iq_balance_tracking) _configure_rx_iq_tracking(); + _last_rx_cal_freq = _rx_freq; + _last_tx_cal_freq = _tx_freq; + // cals done, set PPORT config switch (_client_params->get_digital_interface_mode()) { case AD9361_DDR_FDD_LVCMOS: { @@ -1861,6 +1867,9 @@ double ad9361_device_t::set_clock_rate(const double req_rate) if (_use_iq_balance_tracking) _configure_rx_iq_tracking(); + _last_rx_cal_freq = _rx_freq; + _last_tx_cal_freq = _tx_freq; + // cals done, set PPORT config switch (_client_params->get_digital_interface_mode()) { case AD9361_DDR_FDD_LVCMOS: { @@ -1976,17 +1985,18 @@ void ad9361_device_t::set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2) double ad9361_device_t::tune(direction_t direction, const double value) { boost::lock_guard lock(_mutex); + double last_cal_freq; if (direction == RX) { if (freq_is_nearly_equal(value, _req_rx_freq)) { return _rx_freq; } - + last_cal_freq = _last_rx_cal_freq; } else if (direction == TX) { if (freq_is_nearly_equal(value, _req_tx_freq)) { return _tx_freq; } - + last_cal_freq = _last_tx_cal_freq; } else { throw uhd::runtime_error("[ad9361_device_t] [tune] INVALID_CODE_PATH"); } @@ -2011,21 +2021,29 @@ double ad9361_device_t::tune(direction_t direction, const double value) /* Update the gain settings. */ _reprogram_gains(); - /* Only run the following calibrations if we are more than 100MHz away - * from the previous calibration point. */ - if (std::abs(_last_calibration_freq - tune_freq) > AD9361_CAL_VALID_WINDOW) { + /* + * Only run the following calibrations if we are more than 100MHz away + * from the previous Tx or Rx calibration point. Leave out single shot + * Rx quadrature unless Rx quad-cal is disabled. + */ + if (std::abs(last_cal_freq - tune_freq) > AD9361_CAL_VALID_WINDOW) { /* Run the calibration algorithms. */ - _calibrate_rf_dc_offset(); - _calibrate_tx_quadrature(); + if (direction == RX) { + _calibrate_rf_dc_offset(); + if (!_use_iq_balance_tracking) + _calibrate_rx_quadrature(); + if (_use_dc_offset_tracking) + _configure_bb_dc_tracking(); + + _last_rx_cal_freq = tune_freq; + } else { + _calibrate_tx_quadrature(); + _last_tx_cal_freq = tune_freq; + } - if (_use_dc_offset_tracking) - _configure_bb_dc_tracking(); + /* Rx IQ tracking can be disabled on Rx or Tx re-calibration */ if (_use_iq_balance_tracking) _configure_rx_iq_tracking(); - else - _calibrate_rx_quadrature(); - - _last_calibration_freq = tune_freq; } /* If we were in the FDD state, return it now. */ diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index f9bcd3a5e..efd0f017c 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -157,6 +157,8 @@ public: static const double AD9361_MAX_CLOCK_RATE; static const double AD9361_CAL_VALID_WINDOW; static const double AD9361_RECOMMENDED_MAX_BANDWIDTH; + static const double DEFAULT_RX_FREQ; + static const double DEFAULT_TX_FREQ; private: //Methods void _program_fir_filter(direction_t direction, int num_taps, boost::uint16_t *coeffs); @@ -236,7 +238,7 @@ private: //Members ad9361_io::sptr _io_iface; //Intermediate state double _rx_freq, _tx_freq, _req_rx_freq, _req_tx_freq; - double _last_calibration_freq; + double _last_rx_cal_freq, _last_tx_cal_freq; double _rx_analog_bw, _tx_analog_bw, _rx_bb_lp_bw, _tx_bb_lp_bw; double _rx_tia_lp_bw, _tx_sec_lp_bw; //! Current baseband sampling rate (this is the actual rate the device is -- cgit v1.2.3