aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp')
-rw-r--r--host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp770
1 files changed, 0 insertions, 770 deletions
diff --git a/host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp b/host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp
deleted file mode 100644
index 787faf6df..000000000
--- a/host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp
+++ /dev/null
@@ -1,770 +0,0 @@
-//
-// Copyright 2015-2016 Ettus Research
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include "e3xx_radio_ctrl_impl.hpp"
-#include "e300_defaults.hpp"
-#include "e300_regs.hpp"
-#include <boost/make_shared.hpp>
-#include <uhd/usrp/dboard_iface.hpp>
-#include <uhd/rfnoc/node_ctrl_base.hpp>
-#include <uhd/utils/log.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/make_shared.hpp>
-
-using namespace uhd;
-using namespace uhd::rfnoc;
-using namespace uhd::usrp::e300;
-using uhd::usrp::dboard_iface;
-
-//! mapping of frontend to radio perif index
-static const size_t FE0 = 1;
-static const size_t FE1 = 0;
-
-/****************************************************************************
- * Structors
- ***************************************************************************/
-UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(e3xx_radio_ctrl)
-{
- UHD_RFNOC_BLOCK_TRACE() << "e3xx_radio_ctrl_impl::ctor() " << std::endl;
-
- ////////////////////////////////////////////////////////////////////
- // Set up peripherals
- ////////////////////////////////////////////////////////////////////
- for (size_t i = 0; i < _get_num_radios(); i++) {
- if (i == 0) {
- _spi = spi_core_3000::make(_get_ctrl(i), regs::sr_addr(regs::SPI), regs::RB_SPI);
- _spi->set_divider(6);
- }
- _e3xx_perifs[i].atr = usrp::gpio_atr::gpio_atr_3000::make_write_only(_get_ctrl(i), regs::sr_addr(regs::GPIO));
- _e3xx_perifs[i].leds = usrp::gpio_atr::gpio_atr_3000::make_write_only(_get_ctrl(i), regs::sr_addr(regs::LEDS));
- _e3xx_perifs[i].leds->set_atr_mode(usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL);
- }
-
- ////////////////////////////////////////////////////////////////////
- // Time source
- ////////////////////////////////////////////////////////////////////
- _tree->create<std::string>("time_source/value")
- .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::_update_time_source, this, _1))
- .set(DEFAULT_TIME_SRC);
-#ifdef E300_GPSD
- static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external")("gpsdo");
-#else
- static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external");
-#endif
- _tree->create<std::vector<std::string> >("time_source/options").set(time_sources);
-
- ////////////////////////////////////////////////////////////////////
- // create RF frontend interfacing
- ////////////////////////////////////////////////////////////////////
- {
- const fs_path codec_path = fs_path("rx_codecs") / "A";
- _tree->create<std::string>(codec_path / "name").set("E3x0 RX dual ADC");
- _tree->create<int>(codec_path / "gains"); //empty cuz gains are in frontend
- }
- {
- const fs_path codec_path = fs_path("tx_codecs") / "A";
- _tree->create<std::string>(codec_path / "name").set("E3x0 TX dual DAC");
- _tree->create<int>(codec_path / "gains"); //empty cuz gains are in frontend
- }
-
- ////////////////////////////////////////////////////////////////////
- // internal gpios
- ////////////////////////////////////////////////////////////////////
- UHD_RFNOC_BLOCK_TRACE() << " Creating internal GPIOs..." << std::endl;
-
- usrp::gpio_atr::gpio_atr_3000::sptr fp_gpio = usrp::gpio_atr::gpio_atr_3000::make(
- get_ctrl_iface(0),
- regs::sr_addr(regs::FP_GPIO),
- regs::RB_FP_GPIO
- );
- for (const auto& attr : usrp::gpio_atr::gpio_attr_map) {
- switch (attr.first) {
- case usrp::gpio_atr::GPIO_SRC:
- _tree->create<std::vector<std::string>>(fs_path("gpio") / "INT0" / attr.second)
- .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first)))
- .add_coerced_subscriber([this](const std::vector<std::string>&){
- throw uhd::runtime_error("This device does not support setting the GPIO_SRC attribute.");
- });
- break;
- case usrp::gpio_atr::GPIO_CTRL:
- case usrp::gpio_atr::GPIO_DDR:
- _tree->create<std::vector<std::string>>(fs_path("gpio") / "INT0" / attr.second)
- .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first)))
- .add_coerced_subscriber([this, fp_gpio, attr](const std::vector<std::string> str_val){
- uint32_t val = 0;
- for(size_t i = 0 ; i < str_val.size() ; i++){
- val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i;
- }
- fp_gpio->set_gpio_attr(attr.first, val);
- });
- break;
- case usrp::gpio_atr::GPIO_READBACK:
- _tree->create<uint8_t>(fs_path("gpio") / "INT0" / "READBACK")
- .set_publisher([this, fp_gpio](){
- return fp_gpio->read_gpio();
- });
- break;
- default:
- _tree->create<uint32_t>(fs_path("gpio") / "INT0" / attr.second)
- .set(0)
- .add_coerced_subscriber([this, fp_gpio, attr](const uint32_t val){
- fp_gpio->set_gpio_attr(attr.first, val);
- });
- }
- }
-
- ////////////////////////////////////////////////////////////////////
- // Tick rate
- ////////////////////////////////////////////////////////////////////
- UHD_RFNOC_BLOCK_TRACE() << " Setting tick rate..." << std::endl;
- _tree->access<double>("tick_rate")
- .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rate, this, _1))
- .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::get_rate, this))
- ;
-}
-
-e3xx_radio_ctrl_impl::~e3xx_radio_ctrl_impl()
-{
- const std::string _radio_slot = "A";
- // Tear down our part of the tree:
- _tree->remove(fs_path("rx_codecs" / _radio_slot));
- _tree->remove(fs_path("tx_codecs" / _radio_slot));
- for (size_t i = 0; i < _get_num_radios(); i++) {
- if (_tree->exists(fs_path("tx_dsps") / i)) {
- _tree->remove(fs_path("tx_dsps") / i);
- }
- if (_tree->exists(fs_path("rx_dsps") / i)) {
- _tree->remove(fs_path("rx_dsps") / i);
- }
- }
- for (const auto attr : usrp::gpio_atr::gpio_attr_map) {
- const auto gpio_fs_path = fs_path("gpio") / "INT0" / attr.second;
- if (_tree->exists(gpio_fs_path)) {
- _tree->remove(gpio_fs_path);
- }
- }
-}
-
-/****************************************************************************
- * API calls
- ***************************************************************************/
-double e3xx_radio_ctrl_impl::set_rate(double rate)
-{
- //UHD_LOGGER_DEBUG("E300") << "Setting SPI divider to " << ceil(rate/AD9361_SPI_RATE) << "\n";
- //_spi->set_divider(ceil(rate/AD9361_SPI_RATE)); // ceil() to prevent less than 1 rounding to 0
- UHD_LOGGER_DEBUG("E300") << "Asking for clock rate " << rate/1e6 << " MHz\n";
- double actual_tick_rate = _codec_ctrl->set_clock_rate(rate);
- UHD_LOGGER_DEBUG("E300") << "Actually got clock rate " << actual_tick_rate/1e6 << " MHz\n";
-
- actual_tick_rate = radio_ctrl_impl::set_rate(actual_tick_rate);
-
- if (not check_radio_config()) {
- throw std::runtime_error(str(
- boost::format("[%s]: Invalid radio configuration.")
- % unique_id()
- ));
- }
-
- return actual_tick_rate;
-}
-
-/*! Select TX antenna \p for channel \p chan.
- */
-void e3xx_radio_ctrl_impl::set_tx_antenna(const std::string &ant, const size_t chan)
-{
- std::lock_guard<std::mutex> lock(_mutex);
- if (ant != "TX/RX")
- throw uhd::value_error("Unknown TX antenna option: " + ant);
-
- radio_ctrl_impl::set_tx_antenna(ant, chan);
-}
-
-/*! Select RX antenna \p for channel \p chan.
- */
-void e3xx_radio_ctrl_impl::set_rx_antenna(const std::string &ant, const size_t chan)
-{
- std::lock_guard<std::mutex> lock(_mutex);
- if (ant != "TX/RX" and ant != "RX2")
- throw uhd::value_error("Unknown RX antenna option: " + ant);
-
- radio_ctrl_impl::set_rx_antenna(ant, chan);
- this->_update_atrs();
- this->_update_atr_leds(_e3xx_perifs[chan].leds, ant);
-}
-
-double e3xx_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t)
-{
- return _tree->access<double>(fs_path("dboards/A/tx_frontends/A/freq/value")).set(freq).get();
-}
-
-double e3xx_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t)
-{
- return _tree->access<double>(fs_path("dboards/A/rx_frontends/A/freq/value")).set(freq).get();
-}
-
-double e3xx_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan)
-{
- const std::string fe_side = (chan == 0) ? "A" : "B";
- double new_gain = _tree->access<double>(fs_path("dboards/A/tx_frontends/" + fe_side + "/gains/PGA/value")).set(gain).get();
- return radio_ctrl_impl::set_tx_gain(new_gain, chan);
-}
-
-double e3xx_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan)
-{
- const std::string fe_side = (chan == 0) ? "A" : "B";
- double new_gain = _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/gains/PGA/value")).set(gain).get();
- return radio_ctrl_impl::set_rx_gain(new_gain, chan);
-}
-
-double e3xx_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan)
-{
- const std::string fe_side = (chan == 0) ? "A" : "B";
- double new_bw = _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/bandwidth/value")).set(bandwidth).get();
- return radio_ctrl_impl::set_rx_bandwidth(new_bw, chan);
-}
-
-double e3xx_radio_ctrl_impl::get_tx_gain(const size_t chan)
-{
- const std::string fe_side = (chan == 0) ? "A" : "B";
- return _tree->access<double>(fs_path("dboards/A/tx_frontends/" + fe_side + "/gains/PGA/value")).get();
-}
-
-double e3xx_radio_ctrl_impl::get_rx_gain(const size_t chan)
-{
- const std::string fe_side = (chan == 0) ? "A" : "B";
- return _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/gains/PGA/value")).get();
-}
-
-double e3xx_radio_ctrl_impl::get_rx_bandwidth(const size_t chan)
-{
- const std::string fe_side = (chan == 0) ? "A" : "B";
- return _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/bandwidth/value")).get();
-}
-
-std::vector<std::string> e3xx_radio_ctrl_impl::get_gpio_banks() const
-{
- std::vector<std::string> banks = boost::assign::list_of("INT0");
- return banks;
-}
-
-void e3xx_radio_ctrl_impl::set_gpio_attr(
- const std::string &bank,
- const std::string &attr,
- const uint32_t value,
- const uint32_t mask
-) {
- if (bank == "INT0") {
- const uint32_t current = _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get();
- const uint32_t new_value = (current & ~mask) | (value & mask);
- _tree->access<uint32_t>(fs_path("gpio") / bank / attr).set(new_value);
- return;
- }
-}
-
-uint32_t e3xx_radio_ctrl_impl::get_gpio_attr(
- const std::string &bank,
- const std::string &attr
-) {
- if (bank == "INT0") {
- return uint32_t(_tree->access<uint64_t>(fs_path("gpio") / bank / attr).get());
- }
- return 0;
-}
-
-size_t e3xx_radio_ctrl_impl::get_chan_from_dboard_fe(const std::string &fe, const direction_t)
-{
- return (fe == "A") ? 0 : 1;
-}
-
-std::string e3xx_radio_ctrl_impl::get_dboard_fe_from_chan(const size_t chan, const direction_t)
-{
- return (chan == 0) ? "A" : "B";
-}
-
-/****************************************************************************
- * Radio control and setup
- ***************************************************************************/
-void e3xx_radio_ctrl_impl::setup_radio(uhd::usrp::ad9361_ctrl::sptr safe_codec_ctrl)
-{
- {
- std::lock_guard<std::mutex> lock(_mutex);
- if (_codec_ctrl) {
- throw std::runtime_error("Attempting to set up radio twice!");
- }
- }
-
- ////////////////////////////////////////////////////////////////////
- // Create timed interface
- ////////////////////////////////////////////////////////////////////
- _codec_ctrl = safe_codec_ctrl;
- _codec_mgr = uhd::usrp::ad936x_manager::make(_codec_ctrl, _get_num_radios());
-
- ////////////////////////////////////////////////////////////////////
- // setup radios
- ////////////////////////////////////////////////////////////////////
- for (size_t chan = 0; chan < _get_num_radios(); chan++) {
- _setup_radio_channel(chan);
- }
- // Loopback test
- for (size_t chan = 0; chan < _get_num_radios(); chan++) {
- _codec_mgr->loopback_self_test(
- [this, chan](const uint32_t value){
- this->sr_write(regs::CODEC_IDLE, value, chan);
- },
- [this, chan](){
- return this->user_reg_read64(regs::RB_CODEC_READBACK, chan);
- }
- );
- }
-
- this->_update_enables();
-}
-
-void e3xx_radio_ctrl_impl::_setup_radio_channel(const size_t chan)
-{
- const fs_path rx_dsp_path = fs_path("rx_dsps") / chan;
- _tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd")
- .add_coerced_subscriber(boost::bind(&radio_ctrl_impl::issue_stream_cmd, this, _1, chan));
-
- ////////////////////////////////////////////////////////////////////
- // add some dummy nodes on the prop tree (FIXME remove these)
- ////////////////////////////////////////////////////////////////////
- const fs_path tx_dsp_path = fs_path("tx_dsps") / chan;
- _tree->create<double>(tx_dsp_path / "freq/value").set(0.0);
- _tree->create<meta_range_t>(tx_dsp_path / "freq/range").set(meta_range_t(0.0, 0.0, 0.0));
- _tree->create<double>(rx_dsp_path / "freq/value").set(0.0);
- _tree->create<meta_range_t>(rx_dsp_path / "freq/range").set(meta_range_t(0.0, 0.0, 0.0));
- _tree->create<double>(tx_dsp_path / "rate/value")
- .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rate, this, _1))
- .set_publisher(boost::bind(&radio_ctrl_impl::get_rate, this))
- ;
- _tree->create<double>(rx_dsp_path / "rate/value")
- .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rate, this, _1))
- .set_publisher(boost::bind(&radio_ctrl_impl::get_rate, this))
- ;
-
- ////////////////////////////////////////////////////////////////////
- // create RF frontend interfacing
- ////////////////////////////////////////////////////////////////////
- static const std::vector<direction_t> dirs = boost::assign::list_of(RX_DIRECTION)(TX_DIRECTION);
- BOOST_FOREACH(direction_t dir, dirs) {
- const std::string x = (dir == RX_DIRECTION) ? "rx" : "tx";
- const std::string key = boost::to_upper_copy(x) + std::string(((chan == FE0)? "1" : "2"));
- const fs_path rf_fe_path
- = fs_path("dboards") / "A" / (x + "_frontends") / ((chan == 0) ? "A" : "B");
-
- // This will connect all the AD936x-specific items
- _codec_mgr->populate_frontend_subtree(
- _tree->subtree(rf_fe_path), key, dir
- );
-
- // This will connect all the e3xx_radio_ctrl-specific items
- _tree->create<sensor_value_t>(rf_fe_path / "sensors" / "lo_locked")
- .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::_get_fe_pll_lock, this, dir == TX_DIRECTION))
- ;
- const double freq = _tree->access<double>(rf_fe_path / "freq" / "value")
- .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::_update_fe_lo_freq, this, key, _1)).get()
- ;
- // Set frequency in parent (to be used to update ATR values later)
- if (dir == RX_DIRECTION) {
- radio_ctrl_impl::set_rx_frequency(freq, chan);
- } else {
- radio_ctrl_impl::set_tx_frequency(freq, chan);
- }
-
- // Antenna Setup
- if (dir == RX_DIRECTION) {
- static const std::vector<std::string> ants = boost::assign::list_of("TX/RX")("RX2");
- _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options").set(ants);
- _tree->create<std::string>(rf_fe_path / "antenna" / "value")
- .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rx_antenna, this, _1, chan))
- .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::get_rx_antenna, this, chan));
- // Set default in parent (to be used to update ATR values later)
- radio_ctrl_impl::set_rx_antenna("RX2", chan);
- // Set up LEDs for default antenna
- _update_atr_leds(_e3xx_perifs[chan].leds, "RX2");
- }
- else if (dir == TX_DIRECTION) {
- static const std::vector<std::string> ants(1, "TX/RX");
- _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options").set(ants);
- _tree->create<std::string>(rf_fe_path / "antenna" / "value")
- .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_tx_antenna, this, _1, chan))
- .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::get_tx_antenna, this, chan))
- .set("TX/RX");
- }
- }
-}
-
-void e3xx_radio_ctrl_impl::_reset_radio(void)
-{
- std::lock_guard<std::mutex> lock(_mutex);
- _misc.radio_rst = 1;
- _update_gpio_state();
- boost::this_thread::sleep(boost::posix_time::milliseconds(10));
- _misc.radio_rst = 0;
- _update_gpio_state();
- boost::this_thread::sleep(boost::posix_time::milliseconds(10));
-}
-
-/****************************************************************************
- * Helpers
- ***************************************************************************/
-bool e3xx_radio_ctrl_impl::check_radio_config()
-{
- const size_t num_rx = _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1);
- const size_t num_tx = _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1);
- _enforce_tick_rate_limits(
- std::max(num_rx, num_tx),
- get_tick_rate()
- );
-
- this->_update_enables();
- return true;
-}
-
-void e3xx_radio_ctrl_impl::_enforce_tick_rate_limits(
- const size_t chan_count,
- const double tick_rate
-) {
- const size_t max_chans = 2;
- if (chan_count > max_chans) {
- throw uhd::value_error(boost::str(
- boost::format("cannot not setup %d channels per direction (maximum is %d)")
- % chan_count
- % max_chans
- ));
- } else {
- const double max_tick_rate = uhd::usrp::ad9361_device_t::AD9361_MAX_CLOCK_RATE / ((chan_count <= 1) ? 1 : 2);
- if (tick_rate - max_tick_rate >= 1.0)
- {
- throw uhd::value_error(boost::str(
- boost::format("current master clock rate (%.6f MHz) exceeds maximum possible master clock rate (%.6f MHz) when using %d channels")
- % (tick_rate/1e6)
- % (max_tick_rate/1e6)
- % chan_count
- ));
- }
- // TODO minimum rate check
- }
-}
-
-/****************************************************************************
- * Peripheral controls
- ***************************************************************************/
-void e3xx_radio_ctrl_impl::_update_fe_lo_freq(const std::string &fe, const double freq)
-{
- if (fe[0] == 'R') {
- for (size_t i = 0; i < _get_num_radios(); i++) {
- radio_ctrl_impl::set_rx_frequency(freq, i);
- }
- }
- if (fe[0] == 'T') {
- for (size_t i = 0; i < _get_num_radios(); i++) {
- radio_ctrl_impl::set_tx_frequency(freq, i);
- }
- }
- this->_update_atrs();
-}
-
-void e3xx_radio_ctrl_impl::_update_atrs(void)
-{
- for (size_t instance = 0; instance < _get_num_radios(); instance++)
- {
- // if we're not ready, no point ...
- if (not _e3xx_perifs[instance].atr)
- return;
-
- const bool rx_ant_rx2 = get_rx_antenna(instance) == "RX2";
- const double rx_freq = get_rx_frequency(instance);
- const double tx_freq = get_tx_frequency(instance);
- const bool rx_low_band = rx_freq < 2.6e9;
- const bool tx_low_band = tx_freq < 2940.0e6;
-
- // VCRX
- uint32_t vcrx_v1_rxing = 1;
- uint32_t vcrx_v2_rxing = 0;
- uint32_t vcrx_v1_txing = 1;
- uint32_t vcrx_v2_txing = 0;
-
- if (rx_low_band) {
- vcrx_v1_rxing = rx_ant_rx2 ? 0 : 1;
- vcrx_v2_rxing = rx_ant_rx2 ? 1 : 0;
- vcrx_v1_txing = 0;
- vcrx_v2_txing = 1;
- } else {
- vcrx_v1_rxing = rx_ant_rx2 ? 1 : 0;
- vcrx_v2_rxing = rx_ant_rx2 ? 0 : 1;
- vcrx_v1_txing = 1;
- vcrx_v2_txing = 0;
- }
-
- // VCTX
- uint32_t vctxrx_v1_rxing = 0;
- uint32_t vctxrx_v2_rxing = 1;
- uint32_t vctxrx_v1_txing = 0;
- uint32_t vctxrx_v2_txing = 1;
-
- if (tx_low_band) {
- vctxrx_v1_rxing = rx_ant_rx2 ? 1 : 0;
- vctxrx_v2_rxing = rx_ant_rx2 ? 0 : 1;
- vctxrx_v1_txing = 1;
- vctxrx_v2_txing = 0;
- } else {
- vctxrx_v1_rxing = rx_ant_rx2 ? 1 : 0;
- vctxrx_v2_rxing = rx_ant_rx2 ? 0 : 1;
- vctxrx_v1_txing = 1;
- vctxrx_v2_txing = 1;
- }
-
- //swapped for routing reasons, reswap it here
- if (instance == 1) {
- std::swap(vctxrx_v1_rxing, vctxrx_v2_rxing);
- std::swap(vctxrx_v1_txing, vctxrx_v2_txing);
- }
-
- uint32_t tx_enable_a = (!tx_low_band) ? 1 : 0;
- uint32_t tx_enable_b = (tx_low_band) ? 1 : 0;
-
- /* Set RX / TX band selects */
- uint32_t rx_band_select_a = 0;
- uint32_t rx_band_select_b = 0;
- uint32_t rx_band_select_c = 0;
- uint32_t tx_band_select = 0;
-
- if (instance == 0) {
- // RX
- if (rx_freq < 450e6) {
- rx_band_select_a = 5; // 3'b101
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 1; // 2'b01
- } else if (rx_freq < 700e6) {
- rx_band_select_a = 3; // 3'b011
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 3; // 2'b11
- } else if (rx_freq < 1200e6) {
- rx_band_select_a = 1; // 3'b001
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 2; // 2'b10
- } else if (rx_freq < 1800e6) {
- rx_band_select_a = 0; // 3'b000
- rx_band_select_b = 1; // 2'b01
- rx_band_select_c = 0; // 2'bXX -- Don't care
- } else if (rx_freq < 2350e6){
- rx_band_select_a = 2; // 3'b010
- rx_band_select_b = 3; // 2'b11
- rx_band_select_c = 0; // 2'bXX -- Don't care
- } else if (rx_freq < 2600e6){
- rx_band_select_a = 4; // 3'b100
- rx_band_select_b = 2; // 2'b10
- rx_band_select_c = 0; // 2'bXX -- Don't care
- } else { // >= 2600e6
- rx_band_select_a = 5; // 3'bXX -- Don't care
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 1; // 2'bXX -- Don't care
- }
- } else if (instance == 1) {
- if (rx_freq < 450e6) {
- rx_band_select_a = 4; // 3'b100
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 2; // 2'b10
- } else if (rx_freq < 700e6) {
- rx_band_select_a = 2; // 3'b010
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 3; // 2'b11
- } else if (rx_freq < 1200e6) {
- rx_band_select_a = 0; // 3'b000
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 1; // 2'b01
- } else if (rx_freq < 1800e6) {
- rx_band_select_a = 1; // 3'b001
- rx_band_select_b = 2; // 2'b10
- rx_band_select_c = 0; // 2'bXX -- Don't care
- } else if (rx_freq < 2350e6){
- rx_band_select_a = 3; // 3'b011
- rx_band_select_b = 3; // 2'b11
- rx_band_select_c = 0; // 2'bXX -- Don't care
- } else if (rx_freq < 2600e6){
- rx_band_select_a = 5; // 3'b101
- rx_band_select_b = 1; // 2'b01
- rx_band_select_c = 0; // 2'bXX -- Don't care
- } else { // >= 2600e6
- rx_band_select_a = 5; // 3'bXX -- Don't care
- rx_band_select_b = 0; // 2'bXX -- Don't care
- rx_band_select_c = 1; // 2'bXX -- Don't care
- }
- } else {
- UHD_THROW_INVALID_CODE_PATH();
- }
-
- // TX band selects are the same for both radio frontends
- if (tx_freq < 117.7e6)
- tx_band_select = 7; // 3'b111
- else if (tx_freq < 178.2e6)
- tx_band_select = 6; // 3'b110
- else if (tx_freq < 284.3e6)
- tx_band_select = 5; // 3'b101
- else if (tx_freq < 453.7e6)
- tx_band_select = 4; // 3'b100
- else if (tx_freq < 723.8e6)
- tx_band_select = 3; // 3'b011
- else if (tx_freq < 1154.9e6)
- tx_band_select = 2; // 3'b010
- else if (tx_freq < 1842.6e6)
- tx_band_select = 1; // 3'b001
- else if (tx_freq < 2940.0e6)
- tx_band_select = 0; // 3'b000
- else // > 2940.0e6
- tx_band_select = 7; // 3'bXXX -- Don't care, set to lowest band
-
- const uint32_t rx_selects = 0
- | (vcrx_v1_rxing << VCRX_V1)
- | (vcrx_v2_rxing << VCRX_V2)
- | (vctxrx_v1_rxing << VCTXRX_V1)
- | (vctxrx_v2_rxing << VCTXRX_V2)
- ;
- const uint32_t tx_selects = 0
- | (vcrx_v1_txing << VCRX_V1)
- | (vcrx_v2_txing << VCRX_V2)
- | (vctxrx_v1_txing << VCTXRX_V1)
- | (vctxrx_v2_txing << VCTXRX_V2)
- ;
- const uint32_t tx_enables = 0
- | (tx_enable_a << TX_ENABLEA)
- | (tx_enable_b << TX_ENABLEB)
- ;
- const uint32_t rxtx_band_selects = 0
- | (rx_band_select_a << RX_BANDSEL)
- | (rx_band_select_b << RXB_BANDSEL)
- | (rx_band_select_c << RXC_BANDSEL)
- | (tx_band_select << TX_BANDSEL)
- ;
-
- // Form register values;
- uint32_t oo_reg = rx_selects | rxtx_band_selects;
- uint32_t rx_reg = rx_selects | rxtx_band_selects;
- uint32_t tx_reg = tx_selects | tx_enables | rxtx_band_selects;
- uint32_t fd_reg = tx_selects | tx_enables | rxtx_band_selects; //tx selects dominate in fd mode
-
- //add tx enables based on fe enable
- tx_reg |= tx_enables;
- fd_reg |= tx_enables;
-
- usrp::gpio_atr::gpio_atr_3000::sptr atr = _e3xx_perifs[instance].atr;
- atr->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, oo_reg);
- atr->set_atr_reg(usrp::gpio_atr::ATR_REG_RX_ONLY, rx_reg);
- atr->set_atr_reg(usrp::gpio_atr::ATR_REG_TX_ONLY, tx_reg);
- atr->set_atr_reg(usrp::gpio_atr::ATR_REG_FULL_DUPLEX, fd_reg);
- }
-}
-
-void e3xx_radio_ctrl_impl::_update_atr_leds(usrp::gpio_atr::gpio_atr_3000::sptr leds, const std::string &rx_ant)
-{
- const bool is_txrx = (rx_ant == "TX/RX");
- const int rx_led = (1 << 2);
- const int tx_led = (1 << 1);
- const int txrx_led = (1 << 0);
- using namespace uhd::usrp::gpio_atr;
- leds->set_atr_reg(ATR_REG_IDLE, 0);
- leds->set_atr_reg(ATR_REG_RX_ONLY, is_txrx ? txrx_led : rx_led);
- leds->set_atr_reg(ATR_REG_TX_ONLY, tx_led);
- leds->set_atr_reg(ATR_REG_FULL_DUPLEX, rx_led | tx_led);
-}
-
-void e3xx_radio_ctrl_impl::_update_gpio_state(void)
-{
- UHD_RFNOC_BLOCK_TRACE() << "e3xx_radio_ctrl_impl::_update_gpio_state() " << std::endl;
- uint32_t misc_reg = 0
- | (_misc.pps_sel << gpio_t::PPS_SEL)
- | (_misc.mimo << gpio_t::MIMO)
- | (_misc.radio_rst << gpio_t::RADIO_RST);
- _tree->access<uint32_t>("global_regs/misc").set(misc_reg);
-}
-
-void e3xx_radio_ctrl_impl::_update_enables(void)
-{
- std::lock_guard<std::mutex> lock(_mutex);
- UHD_RFNOC_BLOCK_TRACE() << "e3xx_radio_ctrl_impl::_update_enables() " << std::endl;
- if (not _codec_ctrl) {
- UHD_LOGGER_WARNING("E300") << "Attempting to access CODEC controls before setting up the radios." << std::endl;
- return;
- }
-
- const size_t num_rx = _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1);
- const size_t num_tx = _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1);
-
- const bool mimo = (num_rx == 2) or (num_tx == 2);
-
- // This currently doesn't work with GNU Radio, so leave it uncommented
- //if ((num_tx + num_rx) == 3)
- // throw uhd::runtime_error("e300: 2 RX 1 TX and 1 RX 2 TX configurations not possible");
-
- //setup the active chains in the codec
- if ((num_rx + num_tx) == 0) {
- // Ensure at least one RX chain is enabled so AD9361 outputs a sample clock
- _codec_ctrl->set_active_chains(false, false, true, false);
- } else {
- _codec_ctrl->set_active_chains(
- _is_streamer_active(TX_DIRECTION, FE0),
- _is_streamer_active(TX_DIRECTION, FE1),
- _is_streamer_active(RX_DIRECTION, FE0),
- _is_streamer_active(RX_DIRECTION, FE1)
- );
- }
-
- // Set radio data direction register cleared due to reset
- for (size_t instance = 0; instance < _get_num_radios(); instance++)
- {
- _e3xx_perifs[instance].atr->set_gpio_ddr(usrp::gpio_atr::DDR_OUTPUT, 0xFFFFFFFF);
- }
-
- //figure out if mimo is enabled based on new state
- _misc.mimo = (mimo) ? 1 : 0;
- _update_gpio_state();
-
- //atrs change based on enables
- _update_atrs();
-}
-
-void e3xx_radio_ctrl_impl::_update_time_source(const std::string &source)
-{
- std::lock_guard<std::mutex> lock(_mutex);
- UHD_LOGGER_DEBUG("E300") << boost::format("Setting time source to %s") % source << std::endl;
- if (source == "none" or source == "internal") {
- _misc.pps_sel = global_regs::PPS_INT;
-#ifdef E300_GPSD
- } else if (source == "gpsdo") {
- _misc.pps_sel = global_regs::PPS_GPS;
-#endif
- } else if (source == "external") {
- _misc.pps_sel = global_regs::PPS_EXT;
- } else {
- throw uhd::key_error("update_time_source: unknown source: " + source);
- }
- _update_gpio_state();
-}
-
-uhd::sensor_value_t e3xx_radio_ctrl_impl::_get_fe_pll_lock(const bool is_tx)
-{
- const uint32_t st = _tree->access<uint32_t>("global_regs/pll").get();
- const bool locked = is_tx ? ((st & 0x1) > 0) : ((st & 0x2) > 0);
- return sensor_value_t("LO", locked, "locked", "unlocked");
-}
-
-/****************************************************************************
- * Register block
- ***************************************************************************/
-UHD_RFNOC_BLOCK_REGISTER(e3xx_radio_ctrl, "E3XXRadio");