aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/multi_usrp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/multi_usrp.cpp')
-rw-r--r--host/lib/usrp/multi_usrp.cpp237
1 files changed, 224 insertions, 13 deletions
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 396237e24..7905a6d32 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2013 Ettus Research LLC
+// Copyright 2010-2016 Ettus Research LLC
//
// 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
@@ -27,6 +27,7 @@
#include <uhd/usrp/dboard_eeprom.hpp>
#include <uhd/convert.hpp>
#include <uhd/utils/soft_register.hpp>
+#include "legacy_compat.hpp"
#include <boost/assign/list_of.hpp>
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
@@ -39,6 +40,7 @@ using namespace uhd;
using namespace uhd::usrp;
const std::string multi_usrp::ALL_GAINS = "";
+const std::string multi_usrp::ALL_LOS = "all";
UHD_INLINE std::string string_vector_to_string(std::vector<std::string> values, std::string delimiter = std::string(" "))
{
@@ -389,12 +391,28 @@ public:
multi_usrp_impl(const device_addr_t &addr){
_dev = device::make(addr, device::USRP);
_tree = _dev->get_tree();
+ _is_device3 = bool(boost::dynamic_pointer_cast<uhd::device3>(_dev));
+
+ if (is_device3()) {
+ _legacy_compat = rfnoc::legacy_compat::make(get_device3(), addr);
+ }
}
device::sptr get_device(void){
return _dev;
}
+ bool is_device3(void) {
+ return _is_device3;
+ }
+
+ device3::sptr get_device3(void) {
+ if (not is_device3()) {
+ throw uhd::type_error("Cannot call get_device3() on a non-generation 3 device.");
+ }
+ return boost::dynamic_pointer_cast<uhd::device3>(_dev);
+ }
+
dict<std::string, std::string> get_usrp_rx_info(size_t chan){
mboard_chan_pair mcp = rx_chan_to_mcp(chan);
dict<std::string, std::string> usrp_info;
@@ -438,8 +456,10 @@ public:
******************************************************************/
void set_master_clock_rate(double rate, size_t mboard){
if (mboard != ALL_MBOARDS){
- if (_tree->exists(mb_root(mboard) / "auto_tick_rate")) {
+ if (_tree->exists(mb_root(mboard) / "auto_tick_rate")
+ and _tree->access<bool>(mb_root(mboard) / "auto_tick_rate").get()) {
_tree->access<bool>(mb_root(mboard) / "auto_tick_rate").set(false);
+ UHD_MSG(status) << "Setting master clock rate selection to 'manual'." << std::endl;
}
_tree->access<double>(mb_root(mboard) / "tick_rate").set(rate);
return;
@@ -605,7 +625,12 @@ public:
void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan){
if (chan != ALL_CHANS){
- _tree->access<stream_cmd_t>(rx_dsp_root(chan) / "stream_cmd").set(stream_cmd);
+ if (is_device3()) {
+ mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ _legacy_compat->issue_stream_cmd(stream_cmd, mcp.mboard, mcp.chan);
+ } else {
+ _tree->access<stream_cmd_t>(rx_dsp_root(chan) / "stream_cmd").set(stream_cmd);
+ }
return;
}
for (size_t c = 0; c < get_rx_num_channels(); c++){
@@ -740,6 +765,9 @@ public:
******************************************************************/
rx_streamer::sptr get_rx_stream(const stream_args_t &args) {
_check_link_rate(args, false);
+ if (is_device3()) {
+ return _legacy_compat->get_rx_stream(args);
+ }
return this->get_device()->get_rx_stream(args);
}
@@ -830,6 +858,171 @@ public:
return _tree->access<meta_range_t>(rx_rf_fe_root(chan) / "freq" / "range").get();
}
+ std::vector<std::string> get_rx_lo_names(size_t chan = 0){
+ std::vector<std::string> lo_names;
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ BOOST_FOREACH(const std::string &name, _tree->list(rx_rf_fe_root(chan) / "los")) {
+ lo_names.push_back(name);
+ }
+ }
+ return lo_names;
+ }
+
+ void set_rx_lo_source(const std::string &src, const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "source" / "value").set(src);
+ } else {
+ BOOST_FOREACH(const std::string &n, _tree->list(rx_rf_fe_root(chan) / "los")) {
+ this->set_rx_lo_source(src, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / name / "source" / "value").set(src);
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ const std::string get_rx_lo_source(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "source" / "value").get();
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / name / "source" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // If the daughterboard doesn't expose it's LO(s) then it can only be internal
+ return "internal";
+ }
+ }
+
+ std::vector<std::string> get_rx_lo_sources(const std::string &name = ALL_LOS, size_t chan = 0) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access< std::vector<std::string> >(rx_rf_fe_root(chan) / "los" / ALL_LOS / "source" / "options").get();
+ } else {
+ return std::vector<std::string>();
+ }
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access< std::vector<std::string> >(rx_rf_fe_root(chan) / "los" / name / "source" / "options").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // If the daughterboard doesn't expose it's LO(s) then it can only be internal
+ return std::vector<std::string>(1, "internal");
+ }
+ }
+
+ void set_rx_lo_export_enabled(bool enabled, const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ _tree->access<bool>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "export").set(enabled);
+ } else {
+ BOOST_FOREACH(const std::string &n, _tree->list(rx_rf_fe_root(chan) / "los")) {
+ this->set_rx_lo_export_enabled(enabled, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ _tree->access<bool>(rx_rf_fe_root(chan) / "los" / name / "export").set(enabled);
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ bool get_rx_lo_export_enabled(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access<bool>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "export").get();
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<bool>(rx_rf_fe_root(chan) / "los" / name / "export").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // If the daughterboard doesn't expose it's LO(s), assume it cannot export
+ return false;
+ }
+ }
+
+ double set_rx_lo_freq(double freq, const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency must be set for each stage individually");
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ _tree->access<double>(rx_rf_fe_root(chan) / "los" / name / "freq" / "value").set(freq);
+ return _tree->access<double>(rx_rf_fe_root(chan) / "los" / name / "freq" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ double get_rx_lo_freq(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency must be retrieved for each stage individually");
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<double>(rx_rf_fe_root(chan) / "los" / name / "freq" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // Return actual RF frequency if the daughterboard doesn't expose it's LO(s)
+ return _tree->access<double>(rx_rf_fe_root(chan) / "freq" /" value").get();
+ }
+ }
+
+ freq_range_t get_rx_lo_freq_range(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency range must be retrieved for each stage individually");
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<freq_range_t>(rx_rf_fe_root(chan) / "los" / name / "freq" / "range").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // Return the actual RF range if the daughterboard doesn't expose it's LO(s)
+ return _tree->access<meta_range_t>(rx_rf_fe_root(chan) / "freq" / "range").get();
+ }
+ }
+
void set_rx_gain(double gain, const std::string &name, size_t chan){
/* Check if any AGC mode is enable and if so warn the user */
if (chan != ALL_CHANS) {
@@ -1100,6 +1293,9 @@ public:
******************************************************************/
tx_streamer::sptr get_tx_stream(const stream_args_t &args) {
_check_link_rate(args, true);
+ if (is_device3()) {
+ return _legacy_compat->get_tx_stream(args);
+ }
return this->get_device()->get_tx_stream(args);
}
@@ -1346,10 +1542,10 @@ public:
if (attr == "CTRL") iface->set_pin_ctrl(unit, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "DDR") iface->set_gpio_ddr(unit, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "OUT") iface->set_gpio_out(unit, boost::uint16_t(value), boost::uint16_t(mask));
- if (attr == "ATR_0X") iface->set_atr_reg(unit, dboard_iface::ATR_REG_IDLE, boost::uint16_t(value), boost::uint16_t(mask));
- if (attr == "ATR_RX") iface->set_atr_reg(unit, dboard_iface::ATR_REG_RX_ONLY, boost::uint16_t(value), boost::uint16_t(mask));
- if (attr == "ATR_TX") iface->set_atr_reg(unit, dboard_iface::ATR_REG_TX_ONLY, boost::uint16_t(value), boost::uint16_t(mask));
- if (attr == "ATR_XX") iface->set_atr_reg(unit, dboard_iface::ATR_REG_FULL_DUPLEX, boost::uint16_t(value), boost::uint16_t(mask));
+ if (attr == "ATR_0X") iface->set_atr_reg(unit, gpio_atr::ATR_REG_IDLE, boost::uint16_t(value), boost::uint16_t(mask));
+ if (attr == "ATR_RX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY, boost::uint16_t(value), boost::uint16_t(mask));
+ if (attr == "ATR_TX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY, boost::uint16_t(value), boost::uint16_t(mask));
+ if (attr == "ATR_XX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX, boost::uint16_t(value), boost::uint16_t(mask));
}
}
@@ -1367,10 +1563,10 @@ public:
if (attr == "CTRL") return iface->get_pin_ctrl(unit);
if (attr == "DDR") return iface->get_gpio_ddr(unit);
if (attr == "OUT") return iface->get_gpio_out(unit);
- if (attr == "ATR_0X") return iface->get_atr_reg(unit, dboard_iface::ATR_REG_IDLE);
- if (attr == "ATR_RX") return iface->get_atr_reg(unit, dboard_iface::ATR_REG_RX_ONLY);
- if (attr == "ATR_TX") return iface->get_atr_reg(unit, dboard_iface::ATR_REG_TX_ONLY);
- if (attr == "ATR_XX") return iface->get_atr_reg(unit, dboard_iface::ATR_REG_FULL_DUPLEX);
+ if (attr == "ATR_0X") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_IDLE);
+ if (attr == "ATR_RX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY);
+ if (attr == "ATR_TX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY);
+ if (attr == "ATR_XX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX);
if (attr == "READBACK") return iface->read_gpio(unit);
}
return 0;
@@ -1456,9 +1652,8 @@ public:
default:
throw uhd::assertion_error("multi_usrp::read_register - register has invalid bitwidth: " + path);
}
- } else {
- throw uhd::not_implemented_error("multi_usrp::read_register - register IO not supported for this device");
}
+ throw uhd::not_implemented_error("multi_usrp::read_register - register IO not supported for this device");
}
std::vector<std::string> enumerate_registers(const size_t mboard)
@@ -1494,6 +1689,8 @@ public:
private:
device::sptr _dev;
property_tree::sptr _tree;
+ bool _is_device3;
+ uhd::rfnoc::legacy_compat::sptr _legacy_compat;
struct mboard_chan_pair{
size_t mboard, chan;
@@ -1546,6 +1743,10 @@ private:
fs_path rx_dsp_root(const size_t chan)
{
mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ if (is_device3()) {
+ return _legacy_compat->rx_dsp_root(mcp.mboard, mcp.chan);
+ }
+
if (_tree->exists(mb_root(mcp.mboard) / "rx_chan_dsp_mapping")) {
std::vector<size_t> map = _tree->access<std::vector<size_t> >(mb_root(mcp.mboard) / "rx_chan_dsp_mapping").get();
UHD_ASSERT_THROW(map.size() > mcp.chan);
@@ -1566,6 +1767,10 @@ private:
fs_path tx_dsp_root(const size_t chan)
{
mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ if (is_device3()) {
+ return _legacy_compat->tx_dsp_root(mcp.mboard, mcp.chan);
+ }
+
if (_tree->exists(mb_root(mcp.mboard) / "tx_chan_dsp_mapping")) {
std::vector<size_t> map = _tree->access<std::vector<size_t> >(mb_root(mcp.mboard) / "tx_chan_dsp_mapping").get();
UHD_ASSERT_THROW(map.size() > mcp.chan);
@@ -1585,6 +1790,9 @@ private:
fs_path rx_fe_root(const size_t chan)
{
mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ if (is_device3()) {
+ return _legacy_compat->rx_fe_root(mcp.mboard, mcp.chan);
+ }
try
{
const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan);
@@ -1599,6 +1807,9 @@ private:
fs_path tx_fe_root(const size_t chan)
{
mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ if (is_device3()) {
+ return _legacy_compat->tx_fe_root(mcp.mboard, mcp.chan);
+ }
try
{
const subdev_spec_pair_t spec = get_tx_subdev_spec(mcp.mboard).at(mcp.chan);