UHD: Added custom DDC/DUC support

UHD: Aesthetic corrections

UHD: minor aesthetic changes
master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent e4a794fdbd
commit d9cb51d261

@ -31,14 +31,15 @@ MARK_AS_ADVANCED(UHD_LIBRARIES UHD_INCLUDE_DIRS)
include(CheckCXXSourceCompiles)
IF(UHD_FOUND)
# Checks whether the UHD driver supports X300 reset from srsLTE. This functionality requires changing the function
# `x300_make_ctrl_iface_enet` visibility in the file `uhd/host/lib/usrp/x300_fw_ctrl.cpp`. This can be accomplished
# adding the following line:
# `UHD_API wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors);`
set(_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
set(CMAKE_REQUIRED_LIBRARIES uhd boost_program_options boost_system)
# Checks whether the UHD driver supports X300 reset from srsLTE. This functionality requires changing the function
# `x300_make_ctrl_iface_enet` visibility in the file `uhd/host/lib/usrp/x300_fw_ctrl.cpp`. This can be accomplished
# adding the following line:
# `UHD_API wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors);`
check_cxx_source_compiles("#include <uhd.h>
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/transport/udp_simple.hpp>
@ -59,6 +60,26 @@ IF(UHD_FOUND)
return 0;
}" UHD_ENABLE_X300_FW_RESET)
# Checks whether the UHD driver supports X300 custom RF-NOC devices
check_cxx_source_compiles("#include <uhd.h>
#include <uhd/device3.hpp>
#include <uhd/rfnoc/ddc_ch2_block_ctrl.hpp>
static uhd::device3::sptr device3;
static uhd::rfnoc::ddc_ch2_block_ctrl::sptr ddc_ctrl;
uhd_error try_device3_ddc_ch2_ctrl()
{
ddc_ctrl = device3->get_block_ctrl<uhd::rfnoc::ddc_ch2_block_ctrl>(uhd::rfnoc::block_id_t(\"DDCch2_0\"));
return UHD_ERROR_NONE;
}
int main(int argc, char** argv)
{
try_device3_ddc_ch2_ctrl();
return 0;
}" UHD_ENABLE_CUSTOM_RFNOC)
set(CMAKE_REQUIRED_FLAGS ${_CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_LIBRARIES ${_CMAKE_REQUIRED_LIBRARIES})
ENDIF(UHD_FOUND)

@ -35,6 +35,9 @@ if(RF_FOUND)
if (UHD_ENABLE_X300_FW_RESET)
add_definitions(-DENABLE_UHD_X300_FW_RESET)
endif(UHD_ENABLE_X300_FW_RESET)
if (UHD_ENABLE_CUSTOM_RFNOC)
add_definitions(-DUHD_ENABLE_CUSTOM_RFNOC)
endif(UHD_ENABLE_CUSTOM_RFNOC)
endif (UHD_FOUND)
if (BLADERF_FOUND)

@ -26,6 +26,17 @@
class rf_uhd_generic : public rf_uhd_safe_interface
{
private:
uhd::usrp::multi_usrp::sptr usrp = nullptr;
uhd_error usrp_make_internal(const uhd::device_addr_t& dev_addr) override
{
// Destroy any previous USRP instance
usrp = nullptr;
UHD_SAFE_C_SAVE_ERROR(this, usrp = uhd::usrp::multi_usrp::make(dev_addr);)
}
public:
uhd_error usrp_make(const uhd::device_addr_t& dev_addr) override { return usrp_multi_make(dev_addr); }
@ -37,13 +48,29 @@ public:
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_subdev_spec(string);)
}
uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override
uhd_error get_mboard_name(std::string& mboard_name) override
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_time_unknown_pps(timespec);)
UHD_SAFE_C_SAVE_ERROR(this, mboard_name = usrp->get_mboard_name();)
}
uhd_error set_time_now(const uhd::time_spec_t& timespec) override
uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_time_now(timespec);)
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_mboard_sensor_names();)
}
uhd_error get_rx_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_rx_sensor_names();)
}
uhd_error get_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_mboard_sensor(sensor_name);)
}
uhd_error get_rx_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_rx_sensor(sensor_name);)
}
uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_time_unknown_pps(timespec);)
}
uhd_error get_time_now(uhd::time_spec_t& timespec) override
{
@ -57,6 +84,10 @@ public:
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_sync_source(source, source);)
#endif
}
uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) override
{
UHD_SAFE_C_SAVE_ERROR(this, tx_gain_range = usrp->get_tx_gain_range(); rx_gain_range = usrp->get_rx_gain_range();)
}
uhd_error set_master_clock_rate(double rate) override
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_master_clock_rate(rate);)

@ -100,7 +100,7 @@ static const uint32_t RF_UHD_IMP_MAX_RX_TRIALS = 100;
struct rf_uhd_handler_t {
std::string devname;
rf_uhd_safe_interface* uhd = nullptr;
std::shared_ptr<rf_uhd_safe_interface> uhd = nullptr;
srslte_rf_info_t info;
size_t rx_nof_samples = 0;
@ -677,13 +677,13 @@ int rf_uhd_open_multi(char* args, void** h, uint32_t nof_channels)
// If RFNOC is accessible
#ifdef SRSLTE_RF_UHD_RFNOC_H
if (rf_uhd_rfnoc::is_required(device_addr)) {
handler->uhd = new rf_uhd_rfnoc;
handler->uhd = std::make_shared<rf_uhd_rfnoc>();
}
#endif // SRSLTE_RF_UHD_RFNOC_H
// If UHD was not instanced, instance generic
if (handler->uhd == nullptr) {
handler->uhd = new rf_uhd_generic;
handler->uhd = std::make_shared<rf_uhd_generic>();
}
// Make USRP

@ -22,7 +22,7 @@
#include <uhd/version.hpp>
// RF-NOC is only available for UHD 3.15 LTS
#if UHD_VERSION == 3150000
#if UHD_VERSION >= 3150000 && UHD_VERSION < 3160000
#ifndef SRSLTE_RF_UHD_RFNOC_H
#define SRSLTE_RF_UHD_RFNOC_H
@ -37,16 +37,20 @@
#include <uhd/device3.hpp>
#include <uhd/error.h>
#include <uhd/rfnoc/block_ctrl.hpp>
#include <uhd/rfnoc/ddc_block_ctrl.hpp>
#include <uhd/rfnoc/dma_fifo_block_ctrl.hpp>
#include <uhd/rfnoc/duc_block_ctrl.hpp>
#include <uhd/rfnoc/graph.hpp>
#include <uhd/rfnoc/radio_ctrl.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/log.hpp>
#define Debug(message) UHD_LOG_DEBUG("UHD RF", message)
// Load custom RFNOC blocks if available
#ifdef UHD_ENABLE_CUSTOM_RFNOC
#include <uhd/rfnoc/ddc_ch2_block_ctrl.hpp>
#include <uhd/rfnoc/duc_ch2_block_ctrl.hpp>
#else // UHD_ENABLE_CUSTOM_RFNOC
#include <uhd/rfnoc/ddc_block_ctrl.hpp>
#include <uhd/rfnoc/duc_block_ctrl.hpp>
#endif // UHD_ENABLE_CUSTOM_RFNOC
#include "rf_uhd_safe.h"
@ -59,10 +63,22 @@ private:
// Constant parameters
const std::string RADIO_BLOCK_NAME = "Radio";
#ifdef UHD_ENABLE_CUSTOM_RFNOC
const std::string DDC_BLOCK_NAME = "DDCch2";
const std::string DUC_BLOCK_NAME = "DUCch2";
typedef uhd::rfnoc::ddc_ch2_block_ctrl ddc_ctrl_t;
typedef uhd::rfnoc::duc_ch2_block_ctrl duc_ctrl_t;
#else // UHD_ENABLE_CUSTOM_RFNOC
const std::string DDC_BLOCK_NAME = "DDC";
const std::string DUC_BLOCK_NAME = "DUC";
typedef uhd::rfnoc::ddc_block_ctrl::sptr ddc_ctrl_t;
typedef uhd::rfnoc::duc_block_ctrl::sptr duc_ctrl_t;
#endif // UHD_ENABLE_CUSTOM_RFNOC
const std::string DMA_FIFO_BLOCK_NAME = "DmaFIFO";
const double SETUP_TIME_S = 1;
const double SETUP_TIME_S = 1.0;
const uhd::fs_path TREE_MBOARD_SENSORS = "/mboards/0/sensors";
const uhd::fs_path TREE_RX_SENSORS = "/mboards/0/dboards/A/rx_frontends/0/sensors";
// Primary parameters
double master_clock_rate = 184.32e6;
@ -75,22 +91,32 @@ private:
std::vector<double> rx_freq_hz;
std::vector<double> tx_freq_hz;
std::string sync_source = "internal";
size_t nof_samples_per_packet = 0;
size_t dma_fifo_depth = 8192UL * 4096UL;
// Radio control
std::vector<uhd::rfnoc::radio_ctrl::sptr> radio_ctrl = {};
std::vector<uhd::rfnoc::block_id_t> radio_ctrl_id = {};
std::vector<uhd::rfnoc::block_id_t> radio_id = {};
// DDC Control
std::vector<uhd::rfnoc::ddc_block_ctrl::sptr> ddc_ctrl = {};
std::vector<uhd::rfnoc::block_id_t> ddc_ctrl_id = {};
std::vector<ddc_ctrl_t::sptr> ddc_ctrl = {};
std::vector<uhd::rfnoc::block_id_t> ddc_id = {};
// DUC Control
std::vector<uhd::rfnoc::duc_block_ctrl::sptr> duc_ctrl = {};
std::vector<uhd::rfnoc::block_id_t> duc_ctrl_id = {};
std::vector<duc_ctrl_t::sptr> duc_ctrl = {};
std::vector<uhd::rfnoc::block_id_t> duc_id = {};
// DMA FIFO Control
uhd::rfnoc::dma_fifo_block_ctrl::sptr dma_fifo_ctrl = {};
uhd::rfnoc::block_id_t dma_fifo_ctrl_id = {};
uhd::rfnoc::dma_fifo_block_ctrl::sptr dma_ctrl = {};
uhd::rfnoc::block_id_t dma_id = {};
uhd_error usrp_make_internal(const uhd::device_addr_t& dev_addr) override
{
// Destroy any previous USRP instance
device3 = nullptr;
UHD_SAFE_C_SAVE_ERROR(this, device3 = uhd::device3::make(dev_addr);)
}
template <class T>
uhd_error parse_param(uhd::device_addr_t& args, const std::string& param, T& value)
@ -172,34 +198,34 @@ private:
this,
// Create Radio control
radio_ctrl.resize(nof_radios);
radio_ctrl_id.resize(nof_radios);
radio_id.resize(nof_radios);
for (size_t i = 0; i < nof_radios; i++) {
// Create handle for radio object
radio_ctrl_id[i] = uhd::rfnoc::block_id_t(0, RADIO_BLOCK_NAME, i);
radio_id[i] = uhd::rfnoc::block_id_t(0, RADIO_BLOCK_NAME, i);
// This next line will fail if the radio is not actually available
radio_ctrl[i] = device3->get_block_ctrl<uhd::rfnoc::radio_ctrl>(radio_ctrl_id[i]);
radio_ctrl[i] = device3->get_block_ctrl<uhd::rfnoc::radio_ctrl>(radio_id[i]);
Debug("Using radio " << i);
}
// Create DDC control
ddc_ctrl.resize(nof_radios);
ddc_ctrl_id.resize(nof_radios);
ddc_id.resize(nof_radios);
for (size_t i = 0; i < nof_radios; i++) {
ddc_ctrl_id[i] = uhd::rfnoc::block_id_t(0, DDC_BLOCK_NAME, i);
ddc_ctrl[i] = device3->get_block_ctrl<uhd::rfnoc::ddc_block_ctrl>(ddc_ctrl_id[i]);
ddc_id[i] = uhd::rfnoc::block_id_t(0, DDC_BLOCK_NAME, i);
ddc_ctrl[i] = device3->get_block_ctrl<ddc_ctrl_t>(ddc_id[i]);
}
// Create DUC control
duc_ctrl.resize(nof_radios);
duc_ctrl_id.resize(nof_radios);
duc_id.resize(nof_radios);
for (size_t i = 0; i < nof_radios; i++) {
duc_ctrl_id[i] = uhd::rfnoc::block_id_t(0, DUC_BLOCK_NAME, i);
duc_ctrl[i] = device3->get_block_ctrl<uhd::rfnoc::duc_block_ctrl>(duc_ctrl_id[i]);
duc_id[i] = uhd::rfnoc::block_id_t(0, DUC_BLOCK_NAME, i);
duc_ctrl[i] = device3->get_block_ctrl<duc_ctrl_t>(duc_id[i]);
}
// Create DMA FIFO control
dma_fifo_ctrl_id = uhd::rfnoc::block_id_t(0, DMA_FIFO_BLOCK_NAME);
dma_fifo_ctrl = device3->get_block_ctrl<uhd::rfnoc::dma_fifo_block_ctrl>(dma_fifo_ctrl_id);)
dma_id = uhd::rfnoc::block_id_t(0, DMA_FIFO_BLOCK_NAME);
dma_ctrl = device3->get_block_ctrl<uhd::rfnoc::dma_fifo_block_ctrl>(dma_id);)
}
uhd_error configure()
@ -223,37 +249,37 @@ private:
// Configure radios
for (size_t i = 0; i < nof_radios; ++i) {
Debug(boost::format("Setting radio %i...") % i);
Debug("Setting radio " << i << "...");
// Lock mboard clocks
Debug("Setting sync source to " << sync_source) radio_ctrl[i]->set_clock_source(sync_source);
radio_ctrl[i]->set_time_source(sync_source);
// Set sample rate
Debug(boost::format("Setting TX/RX Rate: %f Msps...") % (master_clock_rate / 1e6));
Debug("Setting TX/RX Rate: " << master_clock_rate / 1e6 << " Msps...");
radio_ctrl[i]->set_rate(master_clock_rate);
Debug(boost::format("Actual TX/RX Rate: %f Msps...") % (radio_ctrl[i]->get_rate() / 1e6));
Debug("Actual TX/RX Rate:" << radio_ctrl[i]->get_rate() / 1e6 << " Msps...");
// Set tx freq
Debug(boost::format("Setting TX Freq: %f MHz...") % (tx_center_freq_hz[i] / 1e6));
Debug("Setting TX Freq: " << tx_center_freq_hz[i] / 1e6 << " MHz...");
radio_ctrl[i]->set_tx_frequency(tx_center_freq_hz[i], 0);
tx_center_freq_hz[i] = radio_ctrl[i]->get_tx_frequency(0);
Debug(boost::format("Actual TX Freq: %f MHz...") % (tx_center_freq_hz[i] / 1e6));
Debug("Actual TX Freq: " << tx_center_freq_hz[i] / 1e6 << " MHz...");
// Set rx freq
Debug(boost::format("Setting RX Freq: %f MHz...") % (rx_center_freq_hz[i] / 1e6));
Debug("Setting RX Freq: " << rx_center_freq_hz[i] / 1e6 << " MHz...");
radio_ctrl[i]->set_rx_frequency(rx_center_freq_hz[i], 0);
rx_center_freq_hz[i] = radio_ctrl[i]->get_rx_frequency(0);
Debug(boost::format("Actual RX Freq: %f MHz...") % (rx_center_freq_hz[i] / 1e6));
Debug("Actual RX Freq: " << rx_center_freq_hz[i] / 1e6 << " MHz...");
// set the IF filter bandwidth
Debug(boost::format("Setting RX Bandwidth: %f MHz...") % (bw_hz / 1e6));
Debug("Setting RX Bandwidth: " << bw_hz / 1e6 << " MHz...");
radio_ctrl[i]->set_rx_bandwidth(bw_hz, 0);
Debug(boost::format("Actual RX Bandwidth: %f MHz...") % (radio_ctrl[i]->get_rx_bandwidth(0) / 1e6));
Debug("Actual RX Bandwidth: " << radio_ctrl[i]->get_rx_bandwidth(0) / 1e6 << " MHz...");
// set the rf gain
Debug(boost::format("Setting RX Gain: %f dB...") % (rx_gain_db));
Debug("Setting RX Gain: " << rx_gain_db << " dB...");
radio_ctrl[i]->set_rx_gain(rx_gain_db, 0);
Debug(boost::format("Actual RX Gain: %f dB...") % (radio_ctrl[i]->get_rx_gain(0)));
Debug("Actual RX Gain: " << radio_ctrl[i]->get_rx_gain(0) << " dB...");
// set the antenna
radio_ctrl[i]->set_rx_antenna("TX/RX", 0);
@ -265,36 +291,43 @@ private:
// Setup DDCs and DUCs
for (size_t radio_idx = 0; radio_idx < nof_radios; radio_idx++) {
for (size_t channel_idx = 0; channel_idx < nof_channels; channel_idx++) {
size_t rf_channel_idx = nof_channels * radio_idx + channel_idx;
{ // Setup DDC
uhd::device_addr_t ddc_args;
ddc_args.set("output_rate", std::to_string(srate_hz));
ddc_args.set("input_rate", std::to_string(master_clock_rate));
ddc_args.set(
"freq",
std::to_string(rx_freq_hz[nof_channels * radio_idx + channel_idx] - rx_center_freq_hz[radio_idx]));
ddc_args.set("freq", std::to_string(rx_freq_hz[rf_channel_idx] - rx_center_freq_hz[radio_idx]));
ddc_args.set("fullscale", "1.0");
ddc_args.set("output_rate", std::to_string(srate_hz));
Debug("Configure " << ddc_ctrl_id[radio_idx] << ":" << channel_idx << "with args " << ddc_args.to_string());
Debug("Configure " << ddc_id[radio_idx] << ":" << channel_idx << " with args " << ddc_args.to_string());
ddc_ctrl[radio_idx]->set_args(ddc_args, channel_idx);
}
{ // Setup DUC
uhd::device_addr_t duc_args;
duc_args.set("output_rate", std::to_string(master_clock_rate));
duc_args.set("input_rate", std::to_string(srate_hz));
duc_args.set(
"freq",
std::to_string(tx_freq_hz[nof_channels * radio_idx + channel_idx] - tx_center_freq_hz[radio_idx]));
duc_args.set("freq", std::to_string(tx_freq_hz[rf_channel_idx] - tx_center_freq_hz[radio_idx]));
duc_args.set("fullscale", "1.0");
duc_args.set("output_rate", std::to_string(master_clock_rate));
Debug("Configure " << duc_ctrl_id[radio_idx] << ":" << channel_idx << "with args " << duc_args.to_string());
Debug("Configure " << duc_id[radio_idx] << ":" << channel_idx << " with args " << duc_args.to_string());
duc_ctrl[radio_idx]->set_args(duc_args, channel_idx);
}
// Setup DMA FIFO
{ // Setup DMA FIFO
uhd::device_addr_t dma_fifo_args;
Debug("Configure " << dma_fifo_ctrl_id << ":" << nof_channels * radio_idx + channel_idx << " with args "
<< dma_fifo_args.to_string());
dma_fifo_args.set("base_addr", std::to_string(dma_fifo_depth * rf_channel_idx));
dma_fifo_args.set("depth", std::to_string(dma_fifo_depth));
dma_fifo_ctrl->set_args(dma_fifo_args, nof_channels * radio_idx + channel_idx);
Debug("Configure " << dma_id << ":" << rf_channel_idx << " with args " << dma_fifo_args.to_string());
dma_ctrl->set_args(dma_fifo_args, rf_channel_idx);
}
}
Debug("Configuration done!")
})
}
@ -302,19 +335,18 @@ private:
{
UHD_SAFE_C_SAVE_ERROR(this, for (size_t radio_idx = 0; radio_idx < nof_radios; radio_idx++) {
// Radio -> DDC
Debug("Connecting " << radio_ctrl_id[radio_idx] << " -> " << ddc_ctrl_id[radio_idx]);
rx_graph->connect(radio_ctrl_id[radio_idx], 0, ddc_ctrl_id[radio_idx], 0);
Debug("Connecting " << radio_id[radio_idx] << ":0 -> " << ddc_id[radio_idx] << ":0");
rx_graph->connect(radio_id[radio_idx], 0, ddc_id[radio_idx], 0, nof_samples_per_packet);
// DUC -> Radio
Debug("Connecting " << duc_ctrl_id[radio_idx] << " -> " << radio_ctrl_id[radio_idx]);
tx_graph->connect(duc_ctrl_id[radio_idx], 0, radio_ctrl_id[radio_idx], 0);
Debug("Connecting " << duc_id[radio_idx] << ":0 -> " << radio_id[radio_idx] << ":0");
tx_graph->connect(duc_id[radio_idx], 0, radio_id[radio_idx], 0, nof_samples_per_packet);
// DMA FIFO -> DUC
for (size_t channel_idx = 0; channel_idx < nof_channels; channel_idx++) {
Debug("Connecting " << dma_fifo_ctrl_id << ":" << radio_idx * nof_channels + channel_idx << " -> "
<< radio_ctrl_id[radio_idx] << ":" << channel_idx);
tx_graph->connect(
dma_fifo_ctrl_id, radio_idx * nof_channels + channel_idx, duc_ctrl_id[radio_idx], channel_idx);
size_t dma_port = radio_idx * nof_channels + channel_idx;
Debug("Connecting " << dma_id << ":" << dma_port << " -> " << duc_id[radio_idx] << ":" << channel_idx);
tx_graph->connect(dma_id, dma_port, duc_id[radio_idx], channel_idx, nof_samples_per_packet);
}
})
}
@ -343,21 +375,11 @@ private:
}
}
Debug("Getting Tx Stream with arguments " << tx_stream_args.args.to_pp_string());
tx_stream = device3->get_tx_stream(tx_stream_args);
rx_stream = device3->get_rx_stream(rx_stream_args);)
}
uhd_error usrp_get_device3()
{
UHD_SAFE_C_SAVE_ERROR(this,
// Check if device is RF-NOC compatible
if (not usrp->is_device3()) {
last_error = "The selected device is not compatible with RF-NOC";
return UHD_ERROR_INVALID_DEVICE;
}
// Get device 3 shared pointer
device3 = usrp->get_device3();)
Debug("Getting Rx Stream with arguments " << rx_stream_args.args.to_pp_string());
rx_stream = device3->get_rx_stream(rx_stream_args);)
}
public:
@ -394,11 +416,6 @@ public:
return err;
}
err = usrp_get_device3();
if (err != UHD_ERROR_NONE) {
return err;
}
// Reset blocks after a stream
device3->clear();
@ -413,14 +430,54 @@ public:
uhd_error set_tx_subdev(const std::string& string) override { return UHD_ERROR_NONE; }
uhd_error set_rx_subdev(const std::string& string) override { return UHD_ERROR_NONE; }
uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override { return UHD_ERROR_NONE; }
uhd_error set_time_now(const uhd::time_spec_t& timespec) override { return UHD_ERROR_NONE; }
uhd_error get_time_now(uhd::time_spec_t& timespec) override { return UHD_ERROR_NONE; }
uhd_error get_mboard_name(std::string& mboard_name) override
{
mboard_name = "X300";
return UHD_ERROR_NONE;
};
uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(this, if (device3->get_tree()->exists(TREE_MBOARD_SENSORS)) {
sensors = device3->get_tree()->list(TREE_MBOARD_SENSORS);
})
}
uhd_error get_rx_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(this, if (device3->get_tree()->exists(TREE_RX_SENSORS)) {
sensors = device3->get_tree()->list(TREE_RX_SENSORS);
})
}
uhd_error get_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(
this, sensor_value = device3->get_tree()->access<uhd::sensor_value_t>(TREE_MBOARD_SENSORS / sensor_name).get();)
}
uhd_error get_rx_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(
this, sensor_value = device3->get_tree()->access<uhd::sensor_value_t>(TREE_RX_SENSORS / sensor_name).get();)
}
uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override
{
UHD_SAFE_C_SAVE_ERROR(this,
for (size_t i = 0; i < nof_radios; i++) { radio_ctrl[i]->set_time_next_pps(timespec); });
}
uhd_error get_time_now(uhd::time_spec_t& timespec) override
{
UHD_SAFE_C_SAVE_ERROR(this, timespec = radio_ctrl[0]->get_time_now(););
}
uhd_error set_sync_source(const std::string& source) override
{
sync_source = source;
return UHD_ERROR_NONE;
}
uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) override
{
// Hard coded for X300
tx_gain_range = uhd::gain_range_t(.0, 30.0, .5);
rx_gain_range = uhd::gain_range_t(.0, 30.0, .5);
return UHD_ERROR_NONE;
}
uhd_error set_master_clock_rate(double rate) override { return UHD_ERROR_NONE; }
uhd_error set_rx_rate(double rate) override { return UHD_ERROR_NONE; }
uhd_error set_tx_rate(double rate) override { return UHD_ERROR_NONE; }

@ -21,6 +21,12 @@
#ifndef SRSLTE_RF_UHD_SAFE_H
#define SRSLTE_RF_UHD_SAFE_H
#include <uhd/utils/log.hpp>
#define Warning(message) UHD_LOG_WARNING("UHD RF", message)
#define Info(message) UHD_LOG_INFO("UHD RF", message)
#define Debug(message) UHD_LOG_DEBUG("UHD RF", message)
#define Trace(message) UHD_LOG_TRACE("UHD RF", message)
#ifdef ENABLE_UHD_X300_FW_RESET
#include <uhd/transport/udp_simple.hpp>
@ -29,12 +35,48 @@ uhd::wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr u
class rf_uhd_safe_interface
{
private:
#ifdef ENABLE_UHD_X300_FW_RESET
const double X300_SLEEP_TIME_S = 5.0;
#endif /* ENABLE_UHD_X300_FW_RESET */
virtual uhd_error usrp_make_internal(const uhd::device_addr_t& dev_addr) = 0;
#ifdef ENABLE_UHD_X300_FW_RESET
uhd_error try_usrp_x300_reset(const uhd::device_addr_t& dev_addr)
{
UHD_SAFE_C_SAVE_ERROR(
this,
// It is not possible to reset device if IP address is not provided
if (not dev_addr.has_key("addr")) { return UHD_ERROR_NONE; }
Warning("Reseting X300 in address " << dev_addr["addr"]);
{ // Reset Scope
// Create UDP connection
uhd::transport::udp_simple::sptr udp_simple =
uhd::transport::udp_simple::make_connected(dev_addr["addr"], "49152");
// Create X300 control
uhd::wb_iface::sptr x300_ctrl = x300_make_ctrl_iface_enet(udp_simple, true);
// Reset FPGA firmware
x300_ctrl->poke32(0x100058, 1);
Info("Reset Done!");
x300_ctrl = nullptr;
udp_simple = nullptr;
}
return UHD_ERROR_NONE;)
}
#endif /* ENABLE_UHD_X300_FW_RESET */
protected:
// List of errors that can happen in the USRP make that need to restart the device
const std::set<uhd_error> USRP_MAKE_RESET_ERR = {UHD_ERROR_IO};
// UHD pointers
uhd::usrp::multi_usrp::sptr usrp = nullptr;
uhd::rx_streamer::sptr rx_stream = nullptr;
uhd::tx_streamer::sptr tx_stream = nullptr;
@ -55,7 +97,9 @@ protected:
return err;
}
sleep(5);
// Sleep for some time
Info("Wait " << std::to_string(X300_SLEEP_TIME_S) << " seconds");
std::this_thread::sleep_for(std::chrono::milliseconds(int64_t(1000 * X300_SLEEP_TIME_S)));
// Try opening the device one more time
return usrp_make_internal(dev_addr);
@ -64,110 +108,56 @@ protected:
#endif /* ENABLE_UHD_X300_FW_RESET */
}
private:
uhd_error usrp_make_internal(const uhd::device_addr_t& dev_addr)
{
// Destroy any previous USRP instance
usrp = nullptr;
UHD_SAFE_C_SAVE_ERROR(this, usrp = uhd::usrp::multi_usrp::make(dev_addr);)
}
#ifdef ENABLE_UHD_X300_FW_RESET
uhd_error try_usrp_x300_reset(const uhd::device_addr_t& dev_addr)
{
UHD_SAFE_C_SAVE_ERROR(this,
// Destroy any previous USRP instance
usrp = nullptr;
// It is not possible to reset device if IP address is not provided
if (not dev_addr.has_key("addr")) { return UHD_ERROR_NONE; }
printf("Reseting X300 in address %s\n", dev_addr["addr"].c_str());
{ // Reset Scope
// Create UDP connection
uhd::transport::udp_simple::sptr udp_simple =
uhd::transport::udp_simple::make_connected(dev_addr["addr"], "49152");
// Create X300 control
uhd::wb_iface::sptr x300_ctrl = x300_make_ctrl_iface_enet(udp_simple, true);
// Reset FPGA firmware
x300_ctrl->poke32(0x100058, 1);
printf("Reset Done!\n");
x300_ctrl = nullptr;
udp_simple = nullptr;
}
return UHD_ERROR_NONE;)
}
#endif /* ENABLE_UHD_X300_FW_RESET */
public:
std::string last_error;
virtual uhd_error usrp_make(const uhd::device_addr_t& dev_addr) = 0;
virtual uhd_error set_tx_subdev(const std::string& string) = 0;
virtual uhd_error set_rx_subdev(const std::string& string) = 0;
inline uhd_error get_mboard_name(std::string& mboard_name)
{
UHD_SAFE_C_SAVE_ERROR(this, mboard_name = usrp->get_mboard_name();)
}
inline uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors)
{
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_mboard_sensor_names();)
}
inline uhd_error get_rx_sensor_names(std::vector<std::string>& sensors)
{
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_rx_sensor_names();)
}
inline uhd_error get_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value)
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_mboard_sensor(sensor_name);)
}
inline uhd_error get_rx_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value)
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_rx_sensor(sensor_name);)
}
virtual uhd_error get_mboard_name(std::string& mboard_name) = 0;
virtual uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors) = 0;
virtual uhd_error get_rx_sensor_names(std::vector<std::string>& sensors) = 0;
virtual uhd_error get_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value) = 0;
virtual uhd_error get_rx_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value) = 0;
virtual uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) = 0;
virtual uhd_error set_time_now(const uhd::time_spec_t& timespec) = 0;
virtual uhd_error get_time_now(uhd::time_spec_t& timespec) = 0;
inline uhd_error start_rx_stream(double delay)
virtual uhd_error start_rx_stream(double delay)
{
uhd::time_spec_t time_spec;
uhd_error err = get_time_now(time_spec);
if (err != UHD_ERROR_NONE) {
return err;
}
UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd.time_spec = usrp->get_time_now();
stream_cmd.time_spec = time_spec;
stream_cmd.time_spec += 0.1;
stream_cmd.stream_now = false;
rx_stream->issue_stream_cmd(stream_cmd);)
}
inline uhd_error stop_rx_stream()
virtual uhd_error stop_rx_stream()
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
rx_stream->issue_stream_cmd(stream_cmd);)
}
virtual uhd_error set_sync_source(const std::string& source) = 0;
uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range)
{
UHD_SAFE_C_SAVE_ERROR(this, tx_gain_range = usrp->get_tx_gain_range(); rx_gain_range = usrp->get_rx_gain_range();)
}
virtual uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) = 0;
virtual uhd_error set_master_clock_rate(double rate) = 0;
virtual uhd_error set_rx_rate(double rate) = 0;
virtual uhd_error set_tx_rate(double rate) = 0;
virtual uhd_error set_command_time(const uhd::time_spec_t& timespec) = 0;
virtual uhd_error get_rx_stream(const uhd::stream_args_t& args, size_t& max_num_samps) = 0;
inline uhd_error destroy_rx_stream() { UHD_SAFE_C_SAVE_ERROR(this, rx_stream = nullptr;) }
virtual uhd_error destroy_rx_stream() { UHD_SAFE_C_SAVE_ERROR(this, rx_stream = nullptr;) }
virtual uhd_error get_tx_stream(const uhd::stream_args_t& args, size_t& max_num_samps) = 0;
inline uhd_error destroy_tx_stream() { UHD_SAFE_C_SAVE_ERROR(this, rx_stream = nullptr;) }
virtual uhd_error destroy_tx_stream() { UHD_SAFE_C_SAVE_ERROR(this, rx_stream = nullptr;) }
virtual uhd_error set_tx_gain(size_t ch, double gain) = 0;
virtual uhd_error set_rx_gain(size_t ch, double gain) = 0;
virtual uhd_error get_rx_gain(double& gain) = 0;
virtual uhd_error get_tx_gain(double& gain) = 0;
virtual uhd_error set_tx_freq(uint32_t ch, double target_freq, double& actual_freq) = 0;
virtual uhd_error set_rx_freq(uint32_t ch, double target_freq, double& actual_freq) = 0;
inline uhd_error receive(void** buffs,
virtual uhd_error receive(void** buffs,
const size_t nsamps_per_buff,
uhd::rx_metadata_t& metadata,
const double timeout,
@ -177,13 +167,11 @@ public:
UHD_SAFE_C_SAVE_ERROR(this, uhd::rx_streamer::buffs_type buffs_cpp(buffs, rx_stream->get_num_channels());
nof_rxd_samples = rx_stream->recv(buffs_cpp, nsamps_per_buff, metadata, timeout, one_packet);)
}
inline uhd_error recv_async_msg(uhd::async_metadata_t& async_metadata, double timeout, bool& valid)
virtual uhd_error recv_async_msg(uhd::async_metadata_t& async_metadata, double timeout, bool& valid)
{
UHD_SAFE_C_SAVE_ERROR(this, valid = tx_stream->recv_async_msg(async_metadata, timeout); if (valid) {
return UHD_ERROR_NONE;
} valid = usrp.get()->get_device()->recv_async_msg(async_metadata);)
UHD_SAFE_C_SAVE_ERROR(this, valid = tx_stream->recv_async_msg(async_metadata, timeout);)
}
inline uhd_error send(void** buffs,
virtual uhd_error send(void** buffs,
const size_t nsamps_per_buff,
const uhd::tx_metadata_t& metadata,
const double timeout,
@ -192,8 +180,8 @@ public:
UHD_SAFE_C_SAVE_ERROR(this, uhd::tx_streamer::buffs_type buffs_cpp(buffs, tx_stream->get_num_channels());
nof_txd_samples = tx_stream->send(buffs_cpp, nsamps_per_buff, metadata, timeout);)
}
inline bool is_rx_ready() { return rx_stream != nullptr; }
inline bool is_tx_ready() { return tx_stream != nullptr; }
virtual bool is_rx_ready() { return rx_stream != nullptr; }
virtual bool is_tx_ready() { return tx_stream != nullptr; }
};
#endif // SRSLTE_RF_UHD_SAFE_H

Loading…
Cancel
Save