diff options
author | Lars Amsel <lars.amsel@ni.com> | 2021-06-04 08:27:50 +0200 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-06-10 12:01:53 -0500 |
commit | 2a575bf9b5a4942f60e979161764b9e942699e1e (patch) | |
tree | 2f0535625c30025559ebd7494a4b9e7122550a73 /host/lib/usrp/dboard/zbx/zbx_lo_ctrl.cpp | |
parent | e17916220cc955fa219ae37f607626ba88c4afe3 (diff) | |
download | uhd-2a575bf9b5a4942f60e979161764b9e942699e1e.tar.gz uhd-2a575bf9b5a4942f60e979161764b9e942699e1e.tar.bz2 uhd-2a575bf9b5a4942f60e979161764b9e942699e1e.zip |
uhd: Add support for the USRP X410
Co-authored-by: Lars Amsel <lars.amsel@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Cristina Fuentes <cristina.fuentes-curiel@ni.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>
Co-authored-by: Virendra Kakade <virendra.kakade@ni.com>
Co-authored-by: Lane Kolbly <lane.kolbly@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Andrew Lynch <andrew.lynch@ni.com>
Co-authored-by: Grant Meyerhoff <grant.meyerhoff@ni.com>
Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Co-authored-by: Thomas Vogel <thomas.vogel@ni.com>
Diffstat (limited to 'host/lib/usrp/dboard/zbx/zbx_lo_ctrl.cpp')
-rw-r--r-- | host/lib/usrp/dboard/zbx/zbx_lo_ctrl.cpp | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/host/lib/usrp/dboard/zbx/zbx_lo_ctrl.cpp b/host/lib/usrp/dboard/zbx/zbx_lo_ctrl.cpp new file mode 100644 index 000000000..1af665207 --- /dev/null +++ b/host/lib/usrp/dboard/zbx/zbx_lo_ctrl.cpp @@ -0,0 +1,162 @@ +// +// Copyright 2020 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include <uhd/exception.hpp> +#include <uhd/utils/log.hpp> +#include <uhdlib/usrp/dboard/zbx/zbx_lo_ctrl.hpp> +#include <thread> + +namespace uhd { namespace usrp { namespace zbx { + +zbx_lo_ctrl::zbx_lo_ctrl(zbx_lo_t lo, + lmx2572_iface::write_fn_t&& poke16, + lmx2572_iface::read_fn_t&& peek16, + lmx2572_iface::sleep_fn_t&& sleep, + const double default_frequency, + const double db_prc_rate, + const bool testing_mode_enabled) + : _lo(lo) + , _log_id(ZBX_LO_LOG_ID.at(lo)) + , _freq(default_frequency) + , _db_prc_rate(db_prc_rate) + , _testing_mode_enabled(testing_mode_enabled) +{ + _lmx = lmx2572_iface::make(std::move(poke16), std::move(peek16), std::move(sleep)); + UHD_ASSERT_THROW(_lmx); + UHD_LOG_TRACE(_log_id, "LO initialized..."); + _lmx->reset(); + + set_lo_port_enabled(true); + // In ZBX, we always run the LOs in sync mode. It is theoretically possible + // to not do so, but we gain nothing by doing that. + _lmx->set_sync_mode(true); + set_lo_freq(LMX2572_DEFAULT_FREQ); + wait_for_lo_lock(); +} + +double zbx_lo_ctrl::set_lo_freq(const double freq) +{ + UHD_ASSERT_THROW(_lmx); + UHD_LOG_TRACE(_log_id, "Setting LO frequency " << freq / 1e6 << " MHz"); + + _freq = _lmx->set_frequency(freq, + _db_prc_rate, + false /*TODO: get_spur_dodging()*/); + _lmx->commit(); + return _freq; +} + +double zbx_lo_ctrl::get_lo_freq() +{ + return _freq; +} + +void zbx_lo_ctrl::wait_for_lo_lock() +{ + UHD_LOG_TRACE(_log_id, "Waiting for LO lock, " << ZBX_LO_LOCK_TIMEOUT_MS << " ms"); + const auto timeout = std::chrono::steady_clock::now() + + std::chrono::milliseconds(ZBX_LO_LOCK_TIMEOUT_MS); + while (std::chrono::steady_clock::now() < timeout && !get_lock_status()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + if (!get_lock_status()) { + // If we can't lock our LO, this could be a lot of possible issues + throw uhd::runtime_error(_log_id + " has failed to lock!"); + } +} + +bool zbx_lo_ctrl::get_lock_status() +{ + return _lmx->get_lock_status(); +} + +void zbx_lo_ctrl::set_lo_port_enabled(bool enable) +{ + UHD_LOG_TRACE(_log_id, + "Enabling LO " << (_testing_mode_enabled ? "test" : "output") << " port"); + + // We want to set the output port regardless of test mode being enabled + _lmx->set_output_enable(_get_output_port(false), enable); + + if (_testing_mode_enabled && enable) { + // If testing mode is enabled, also set the test port + _lmx->set_output_enable(_get_output_port(true), true); + } else { + // If testing mode is disabled, test port should be disabled + _lmx->set_output_enable(_get_output_port(true), false); + _lmx->set_mux_input( + _get_output_port(true), lmx2572_iface::mux_in_t::HIGH_IMPEDANCE); + } + + _lmx->set_enabled(enable); + _lmx->commit(); +} + +bool zbx_lo_ctrl::get_lo_port_enabled() +{ + return _lmx->get_enabled(); +} + +void zbx_lo_ctrl::set_lo_test_mode_enabled(bool enable) +{ + _testing_mode_enabled = enable; + set_lo_port_enabled(get_lo_port_enabled()); +} + +bool zbx_lo_ctrl::get_lo_test_mode_enabled() +{ + return _testing_mode_enabled; +} + +zbx_lo_t zbx_lo_ctrl::lo_string_to_enum( + const uhd::direction_t trx, const size_t channel, const std::string name) +{ + if (trx == TX_DIRECTION) { + if (channel == 0) { + if (name == ZBX_LO1) { + return zbx_lo_t::TX0_LO1; + } else if (name == ZBX_LO2) { + return zbx_lo_t::TX0_LO2; + } + } else if (channel == 1) { + if (name == ZBX_LO1) { + return zbx_lo_t::TX1_LO1; + } else if (name == ZBX_LO2) { + return zbx_lo_t::TX1_LO2; + } + } + } else { + if (channel == 0) { + if (name == ZBX_LO1) { + return zbx_lo_t::RX0_LO1; + } else if (name == ZBX_LO2) { + return zbx_lo_t::RX0_LO2; + } + } else if (channel == 1) { + if (name == ZBX_LO1) { + return zbx_lo_t::RX1_LO1; + } else if (name == ZBX_LO2) { + return zbx_lo_t::RX1_LO2; + } + } + } + UHD_THROW_INVALID_CODE_PATH(); +} + +lmx2572_iface::output_t zbx_lo_ctrl::_get_output_port(bool testing_mode) +{ + // Note: The LO output ports here are dependent to the LO and zbx hardware + // configuration, in no particular order (zbx radio configuration output vs. + // test port output) + if (!testing_mode) { + // Rev B has all LO outputs on Port A + return lmx2572_iface::output_t::RF_OUTPUT_A; + } else { + return lmx2572_iface::output_t::RF_OUTPUT_B; + } +} + +}}} // namespace uhd::usrp::zbx |