mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
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.
283 lines
12 KiB
C++
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 */
|
|
}
|