uhd/host/lib/usrp/dboard/db_basic_and_lf.cpp
Martin Braun 307e6c5eab basic/lf: Add IDs for calibration purpose
This adds a property tree node "id" next to the "name" node. It is
always either basicrx/lfrx/basixtx/lftx based on the daughterboard. The
x300_radio_control uses this to help distinguish daughterboards for
calibration's sake, where length strings, potentially with special
characters, are too unwieldy.
2020-05-19 13:30:36 -05:00

283 lines
12 KiB
C++

//
// Copyright 2010-2012 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include "db_basic_and_lf.hpp"
#include <uhd/types/dict.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <uhd/utils/assert_has.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/utils/static.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
using namespace uhd;
using namespace uhd::usrp;
using namespace uhd::usrp::dboard::basic_and_lf;
/***********************************************************************
* The basic and lf boards:
* They share a common class because only the frequency bounds differ.
**********************************************************************/
class basic_rx : public rx_dboard_base
{
public:
basic_rx(ctor_args_t args, double max_freq);
virtual ~basic_rx(void);
private:
double _max_freq;
};
class basic_tx : public tx_dboard_base
{
public:
basic_tx(ctor_args_t args, double max_freq);
virtual ~basic_tx(void);
private:
double _max_freq;
};
/***********************************************************************
* Register the basic and LF dboards
**********************************************************************/
static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t args)
{
return dboard_base::sptr(new basic_rx(args, BASIC_MAX_BANDWIDTH));
}
static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t args)
{
return dboard_base::sptr(new basic_tx(args, BASIC_MAX_BANDWIDTH));
}
static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t args)
{
return dboard_base::sptr(new basic_rx(args, LF_MAX_BANDWIDTH));
}
static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t args)
{
return dboard_base::sptr(new basic_tx(args, LF_MAX_BANDWIDTH));
}
UHD_STATIC_BLOCK(reg_basic_and_lf_dboards)
{
dboard_manager::register_dboard(
BASIC_TX_PID, &make_basic_tx, "Basic TX", antenna_mode_to_conn.keys());
dboard_manager::register_dboard(
BASIC_RX_PID, &make_basic_rx, "Basic RX", antenna_mode_to_conn.keys());
dboard_manager::register_dboard(
LF_TX_PID, &make_lf_tx, "LF TX", antenna_mode_to_conn.keys());
dboard_manager::register_dboard(
LF_RX_PID, &make_lf_rx, "LF RX", antenna_mode_to_conn.keys());
dboard_manager::register_dboard(
BASIC_TX_RFNOC_PID, &make_basic_tx, "Basic TX", tx_frontends);
dboard_manager::register_dboard(
BASIC_RX_RFNOC_PID, &make_basic_rx, "Basic RX", rx_frontends);
dboard_manager::register_dboard(
LF_TX_RFNOC_PID, &make_lf_tx, "LF TX", tx_frontends);
dboard_manager::register_dboard(
LF_RX_RFNOC_PID, &make_lf_rx, "LF RX", rx_frontends);
}
/***********************************************************************
* Basic and LF RX dboard
**********************************************************************/
basic_rx::basic_rx(ctor_args_t args, double max_freq)
: rx_dboard_base(args), _max_freq(max_freq)
{
// Examine the frontend to use the RFNoC or the N210 implementation
// (preserves legacy behavior)
const std::string fe_name(get_subdev_name());
const bool is_rfnoc_dev = std::find(rx_frontends.begin(), rx_frontends.end(), fe_name)
!= rx_frontends.end();
const std::string ant_mode(is_rfnoc_dev ? "AB" : fe_name);
const std::string fe_conn(antenna_mode_to_conn[ant_mode]);
const std::string db_name([this]() {
switch (get_rx_id().to_uint16()) {
case BASIC_RX_PID:
case BASIC_RX_RFNOC_PID:
return str(boost::format("%s (%s)") % "BasicRX" % get_subdev_name());
case LF_RX_PID:
case LF_RX_RFNOC_PID:
return str(boost::format("%s (%s)") % "LFRX" % get_subdev_name());
default:
UHD_THROW_INVALID_CODE_PATH();
}
}());
UHD_LOG_TRACE("BASICRX",
"Initializing driver for: " << db_name << " IQ connection type: " << ant_mode);
UHD_LOG_TRACE("BASICRX", "Is RFNoC Device: " << (is_rfnoc_dev ? "Yes" : "No"));
std::vector<std::string> antenna_options = antenna_mode_to_conn.keys();
////////////////////////////////////////////////////////////////////
// Register properties
////////////////////////////////////////////////////////////////////
this->get_rx_subtree()->create<std::string>("name").set(db_name);
this->get_rx_subtree()->create<std::string>("id").set(
(get_rx_id().to_uint16() & 0xFF) == BASIC_RX_PID ? "basicrx" : "lfrx");
this->get_rx_subtree()->create<int>("gains"); // phony property so this dir exists
this->get_rx_subtree()->create<double>("freq/value").set_publisher([]() {
return 0.0;
});
this->get_rx_subtree()
->create<meta_range_t>("freq/range")
.set(freq_range_t(-_max_freq, +_max_freq));
this->get_rx_subtree()
->create<std::string>("antenna/value")
.set(is_rfnoc_dev ? ant_mode : "");
this->get_rx_subtree()
->create<std::vector<std::string>>("antenna/options")
.set(is_rfnoc_dev ? antenna_options : std::vector<std::string>(1, ""));
this->get_rx_subtree()->create<int>("sensors"); // phony property so this dir exists
this->get_rx_subtree()
->create<std::string>("connection")
.set(antenna_mode_to_conn[ant_mode]);
this->get_rx_subtree()->create<bool>("enabled").set(true); // always enabled
this->get_rx_subtree()->create<bool>("use_lo_offset").set(false);
this->get_rx_subtree()
->create<double>("bandwidth/value")
.set(antenna_mode_bandwidth_scalar.at(ant_mode) * _max_freq);
this->get_rx_subtree()
->create<meta_range_t>("bandwidth/range")
.set(freq_range_t(antenna_mode_bandwidth_scalar.at(ant_mode) * _max_freq,
antenna_mode_bandwidth_scalar.at(ant_mode) * _max_freq));
if (is_rfnoc_dev) {
this->get_rx_subtree()
->access<std::string>("antenna/value")
.add_coerced_subscriber([this](const std::string& ant) {
this->get_rx_subtree()
->access<std::string>("connection")
.set(antenna_mode_to_conn[ant]);
this->get_rx_subtree()
->access<double>("bandwidth/value")
.set(antenna_mode_bandwidth_scalar.at(ant) * _max_freq);
this->get_rx_subtree()
->access<meta_range_t>("bandwidth/range")
.set(freq_range_t(antenna_mode_bandwidth_scalar.at(ant) * _max_freq,
antenna_mode_bandwidth_scalar.at(ant) * _max_freq));
UHD_LOG_TRACE("BASICRX",
"Changing antenna mode on channel: " << get_subdev_name()
<< " IQ connection type: "
<< antenna_mode_to_conn[ant]);
});
}
// disable RX dboard clock by default
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, false);
// set GPIOs to output 0x0000 to decrease noise pickup
this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0000);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0xFFFF);
this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0x0000);
}
basic_rx::~basic_rx(void)
{
/* NOP */
}
/***********************************************************************
* Basic and LF TX dboard
**********************************************************************/
basic_tx::basic_tx(ctor_args_t args, double max_freq) : tx_dboard_base(args)
{
// Examine the frontend to use the RFNoC or the N210 implementation
// (preserves legacy behavior)
const std::string fe_name(get_subdev_name());
const bool is_rfnoc_dev = std::find(tx_frontends.begin(), tx_frontends.end(), fe_name)
!= tx_frontends.end();
const std::string ant_mode(is_rfnoc_dev ? "AB" : fe_name);
_max_freq = max_freq;
const std::string db_name([this]() {
switch (get_tx_id().to_uint16()) {
case BASIC_TX_PID:
case BASIC_TX_RFNOC_PID:
return str(boost::format("%s (%s)") % "BasicTX" % get_subdev_name());
case LF_TX_PID:
case LF_TX_RFNOC_PID:
return str(boost::format("%s (%s)") % "LFTX" % get_subdev_name());
default:
UHD_THROW_INVALID_CODE_PATH();
}
}());
UHD_LOG_TRACE("BASICTX",
"Initializing driver for: " << db_name << " IQ connection type: " << ant_mode);
UHD_LOG_TRACE("BASICTX", "Is RFNoC Device: " << (is_rfnoc_dev ? "Yes" : "No"));
std::vector<std::string> antenna_options = antenna_mode_to_conn.keys();
////////////////////////////////////////////////////////////////////
// Register properties
////////////////////////////////////////////////////////////////////
this->get_tx_subtree()->create<std::string>("name").set(db_name);
this->get_tx_subtree()->create<std::string>("id").set(
(get_tx_id().to_uint16() & 0xFF) == BASIC_TX_PID ? "basicrx" : "lfrx");
this->get_tx_subtree()->create<int>("gains"); // phony property so this dir exists
this->get_tx_subtree()->create<double>("freq/value").set_publisher([]() {
return 0.0;
});
this->get_tx_subtree()
->create<meta_range_t>("freq/range")
.set(freq_range_t(-_max_freq, +_max_freq));
this->get_tx_subtree()
->create<std::string>("antenna/value")
.set(is_rfnoc_dev ? ant_mode : "");
this->get_tx_subtree()
->create<std::vector<std::string>>("antenna/options")
.set(is_rfnoc_dev ? antenna_options : std::vector<std::string>(1, ""));
this->get_tx_subtree()->create<int>("sensors"); // phony property so this dir exists
this->get_tx_subtree()
->create<std::string>("connection")
.set(antenna_mode_to_conn[ant_mode]);
this->get_tx_subtree()->create<bool>("enabled").set(true); // always enabled
this->get_tx_subtree()->create<bool>("use_lo_offset").set(false);
this->get_tx_subtree()
->create<double>("bandwidth/value")
.set(antenna_mode_bandwidth_scalar.at(ant_mode) * _max_freq);
this->get_tx_subtree()
->create<meta_range_t>("bandwidth/range")
.set(freq_range_t(antenna_mode_bandwidth_scalar.at(ant_mode) * _max_freq,
antenna_mode_bandwidth_scalar.at(ant_mode) * _max_freq));
if (is_rfnoc_dev) {
this->get_tx_subtree()
->access<std::string>("antenna/value")
.add_coerced_subscriber([this](const std::string& ant) {
this->get_tx_subtree()
->access<std::string>("connection")
.set(antenna_mode_to_conn[ant]);
this->get_tx_subtree()
->access<double>("bandwidth/value")
.set(antenna_mode_bandwidth_scalar.at(ant) * _max_freq);
this->get_tx_subtree()
->access<meta_range_t>("bandwidth/range")
.set(freq_range_t(antenna_mode_bandwidth_scalar.at(ant) * _max_freq,
antenna_mode_bandwidth_scalar.at(ant) * _max_freq));
UHD_LOG_TRACE("BASICTX",
"Changing antenna mode for channel: " << get_subdev_name()
<< " IQ connection type: "
<< antenna_mode_to_conn[ant]);
});
}
// disable TX dboard clock by default
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, false);
// set GPIOs to output 0x0000 to decrease noise pickup
this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, 0x0000);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, 0xFFFF);
this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0x0000);
}
basic_tx::~basic_tx(void)
{
/* NOP */
}