aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/convert/convert_impl.cpp1
-rw-r--r--host/lib/transport/nirio/nifpga_lvbitx.cpp16
-rw-r--r--host/lib/transport/nirio_zero_copy.cpp35
-rw-r--r--host/lib/types/CMakeLists.txt1
-rw-r--r--host/lib/types/metadata.cpp92
-rw-r--r--host/lib/usrp/b100/b100_impl.cpp8
-rw-r--r--host/lib/usrp/b100/b100_impl.hpp1
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp12
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp4
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_3000.cpp6
-rw-r--r--host/lib/usrp/dboard/db_tvrx2.cpp6
-rw-r--r--host/lib/usrp/multi_usrp.cpp41
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp9
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.hpp1
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp7
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp9
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp13
-rw-r--r--host/lib/usrp/x300/x300_io_impl.cpp59
18 files changed, 255 insertions, 66 deletions
diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp
index dc7f8f9dc..c7907ed83 100644
--- a/host/lib/convert/convert_impl.cpp
+++ b/host/lib/convert/convert_impl.cpp
@@ -134,6 +134,7 @@ UHD_STATIC_BLOCK(convert_register_item_sizes){
convert::register_bytes_per_item("sc64", sizeof(std::complex<boost::int64_t>));
convert::register_bytes_per_item("sc32", sizeof(std::complex<boost::int32_t>));
convert::register_bytes_per_item("sc16", sizeof(std::complex<boost::int16_t>));
+ convert::register_bytes_per_item("sc12", 3 * sizeof(std::complex<boost::int8_t>));
convert::register_bytes_per_item("sc8", sizeof(std::complex<boost::int8_t>));
//register standard real types
diff --git a/host/lib/transport/nirio/nifpga_lvbitx.cpp b/host/lib/transport/nirio/nifpga_lvbitx.cpp
index 289a44d4a..b87d87a8d 100644
--- a/host/lib/transport/nirio/nifpga_lvbitx.cpp
+++ b/host/lib/transport/nirio/nifpga_lvbitx.cpp
@@ -16,6 +16,7 @@
//
#include <uhd/transport/nirio/nifpga_lvbitx.h>
+#include <cstdlib>
#include <string>
#include <iostream>
#include <fstream>
@@ -109,6 +110,21 @@ std::string nifpga_lvbitx::_get_fpga_images_dir(const std::string search_paths)
std::vector<std::string> search_path_vtr;
boost::split(search_path_vtr, search_paths, boost::is_any_of(","));
+ //
+ // Add the value of the UHD_IMAGES_DIR environment variable to the list of
+ // directories searched for a LVBITX image.
+ //
+ char* uhd_images_dir;
+#ifdef UHD_PLATFORM_WIN32
+ size_t len;
+ errno_t err = _dupenv_s(&uhd_images_dir, &len, "UHD_IMAGES_DIR");
+ if(not err and uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir));
+ free(uhd_images_dir);
+#else
+ uhd_images_dir = getenv("UHD_IMAGES_DIR");
+ if(uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir));
+#endif
+
std::string lvbitx_dir;
//Traverse through the list of search paths. Priority: lexical
BOOST_FOREACH(std::string& search_path, search_path_vtr) {
diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp
index 7b1e32fe0..c3c8a9368 100644
--- a/host/lib/transport/nirio_zero_copy.cpp
+++ b/host/lib/transport/nirio_zero_copy.cpp
@@ -18,7 +18,6 @@
#include <uhd/transport/nirio_zero_copy.hpp>
#include <stdio.h>
#include <uhd/transport/nirio/nirio_fifo.h>
-#include <uhd/transport/nirio/nirio_fifo.h>
#include <uhd/transport/buffer_pool.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/utils/log.hpp>
@@ -261,19 +260,27 @@ private:
UHD_INLINE void _flush_rx_buff()
{
- nirio_status flush_status = 0;
- while (nirio_status_not_fatal(flush_status)) {
- static const size_t NUM_ELEMS_TO_FLUSH = 1;
- static const uint32_t FLUSH_TIMEOUT_IN_MS = 0;
-
- fifo_data_t* flush_data_ptr = NULL;
- size_t flush_elems_acquired = 0, flush_elems_remaining = 0;
- flush_status = _recv_fifo->acquire(
- flush_data_ptr, NUM_ELEMS_TO_FLUSH, FLUSH_TIMEOUT_IN_MS,
- flush_elems_acquired, flush_elems_remaining);
- if (nirio_status_not_fatal(flush_status)) {
- _recv_fifo->release(flush_elems_acquired);
- }
+ // acquire is called with 0 elements requested first to
+ // get the number of elements in the buffer and then
+ // repeatedly with the number of remaining elements
+ // until the buffer is empty
+ fifo_data_t* elems_buffer;
+ for (size_t num_elems_requested = 0,
+ num_elems_acquired = 0,
+ num_elems_remaining = 1;
+ num_elems_remaining;
+ num_elems_requested = num_elems_remaining)
+ {
+ nirio_status status = _recv_fifo->acquire(
+ elems_buffer,
+ num_elems_requested,
+ 0, // timeout
+ num_elems_acquired,
+ num_elems_remaining);
+ // throw excetption if status is fatal
+ nirio_status_to_exception(status,
+ "NI-RIO PCIe data transfer failed during flush.");
+ _recv_fifo->release(num_elems_acquired);
}
}
diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt
index b69c8e487..7fc6bdd94 100644
--- a/host/lib/types/CMakeLists.txt
+++ b/host/lib/types/CMakeLists.txt
@@ -82,6 +82,7 @@ SET_SOURCE_FILES_PROPERTIES(
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/device_addr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mac_addr.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/metadata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sensors.cpp
${CMAKE_CURRENT_SOURCE_DIR}/serial.cpp
diff --git a/host/lib/types/metadata.cpp b/host/lib/types/metadata.cpp
new file mode 100644
index 000000000..fec2ac564
--- /dev/null
+++ b/host/lib/types/metadata.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright 2014 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
+// 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 <string>
+#include <sstream>
+#include <boost/format.hpp>
+#include <uhd/exception.hpp>
+#include <uhd/types/metadata.hpp>
+#include <uhd/types/time_spec.hpp>
+
+using namespace uhd;
+
+std::string rx_metadata_t::to_pp_string(bool compact) const
+{
+ std::stringstream ss;
+
+ if (compact) {
+ if (has_time_spec) {
+ ss << "Time: " << time_spec.get_real_secs() << " s\n";
+ }
+ if (more_fragments) {
+ ss << "Fragmentation offset: " << fragment_offset << "\n";
+ }
+ if (start_of_burst) {
+ ss << "Start of burst.\n" << fragment_offset;
+ }
+ if (end_of_burst) {
+ ss << "End of burst.\n" << fragment_offset;
+ }
+ if (error_code != ERROR_CODE_NONE) {
+ ss << strerror() << "\n";
+ }
+ } else {
+ ss << "Has timespec: " << (has_time_spec ? "Yes" : "No")
+ << "\tTime of first sample: " << time_spec.get_real_secs()
+ << "\nFragmented: " << (more_fragments ? "Yes" : "No")
+ << " Fragmentation offset: " << fragment_offset
+ << "\nStart of burst: " << (start_of_burst ? "Yes" : "No")
+ << "\tEnd of burst: " << (end_of_burst ? "Yes" : "No")
+ << "\nError Code: " << strerror()
+ << "\tOut of sequence: " << (out_of_sequence ? "Yes" : "No");
+ }
+
+ return ss.str();
+}
+
+std::string rx_metadata_t::strerror() const
+{
+ std::string errstr = "";
+ switch(this->error_code) {
+ case ERROR_CODE_NONE:
+ errstr = "ERROR_CODE_NONE";
+ break;
+ case ERROR_CODE_TIMEOUT:
+ errstr = "ERROR_CODE_TIMEOUT";
+ break;
+ case ERROR_CODE_LATE_COMMAND:
+ errstr = "ERROR_CODE_LATE_COMMAND";
+ break;
+ case ERROR_CODE_BROKEN_CHAIN:
+ errstr = "ERROR_CODE_BROKEN_CHAIN (Expected another stream command)";
+ break;
+ case ERROR_CODE_OVERFLOW:
+ errstr = "ERROR_CODE_OVERFLOW ";
+ errstr += (this->out_of_sequence ? "(Out of sequence error)" : "(Overflow)");
+ break;
+ case ERROR_CODE_ALIGNMENT:
+ errstr = "ERROR_CODE_ALIGNMENT (Multi-channel alignment failed)";
+ break;
+ case ERROR_CODE_BAD_PACKET:
+ errstr = "ERROR_CODE_BAD_PACKET";
+ break;
+ default:
+ errstr = std::string(str(boost::format("Unknown error code: 0x%x") % error_code));
+ }
+
+ return errstr;
+}
diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp
index a47856b07..baf2b6ae3 100644
--- a/host/lib/usrp/b100/b100_impl.cpp
+++ b/host/lib/usrp/b100/b100_impl.cpp
@@ -20,6 +20,7 @@
#include "b100_regs.hpp"
#include <uhd/transport/usb_control.hpp>
#include <uhd/utils/msg.hpp>
+#include <uhd/utils/cast.hpp>
#include <uhd/exception.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/images.hpp>
@@ -56,11 +57,11 @@ static device_addrs_t b100_find(const device_addr_t &hint)
//since an address and resource is intended for a different, non-USB, device.
if (hint.has_key("addr") || hint.has_key("resource")) return b100_addrs;
- unsigned int vid, pid;
+ boost::uint16_t vid, pid;
if(hint.has_key("vid") && hint.has_key("pid") && hint.has_key("type") && hint["type"] == "b100") {
- sscanf(hint.get("vid").c_str(), "%x", &vid);
- sscanf(hint.get("pid").c_str(), "%x", &pid);
+ vid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("vid"));
+ pid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("pid"));
} else {
vid = B100_VENDOR_ID;
pid = B100_PRODUCT_ID;
@@ -515,6 +516,7 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
_tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/tx_frontends").at(0)));
_tree->access<std::string>(mb_path / "clock_source/value").set("internal");
_tree->access<std::string>(mb_path / "time_source/value").set("none");
+ _tree->create<double>(mb_path / "link_max_rate").set(B100_MAX_RATE_USB2);
}
b100_impl::~b100_impl(void){
diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp
index 7d71d5ec3..b6752681e 100644
--- a/host/lib/usrp/b100/b100_impl.hpp
+++ b/host/lib/usrp/b100/b100_impl.hpp
@@ -54,6 +54,7 @@ static const boost::uint32_t B100_CTRL_MSG_SID = 20;
static const double B100_DEFAULT_TICK_RATE = 64e6;
static const size_t B100_MAX_PKT_BYTE_LIMIT = 2048;
static const std::string B100_EEPROM_MAP_KEY = "B100";
+static const size_t B100_MAX_RATE_USB2 = 32000000; // bytes/s
#define I2C_ADDR_TX_A (I2C_DEV_EEPROM | 0x4)
#define I2C_ADDR_RX_A (I2C_DEV_EEPROM | 0x5)
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 9dd3a424d..98141dbaa 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -19,6 +19,7 @@
#include "b200_regs.hpp"
#include <uhd/transport/usb_control.hpp>
#include <uhd/utils/msg.hpp>
+#include <uhd/utils/cast.hpp>
#include <uhd/exception.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/images.hpp>
@@ -58,11 +59,11 @@ static device_addrs_t b200_find(const device_addr_t &hint)
//since an address and resource is intended for a different, non-USB, device.
if (hint.has_key("addr") || hint.has_key("resource")) return b200_addrs;
- unsigned int vid, pid;
+ boost::uint16_t vid, pid;
if(hint.has_key("vid") && hint.has_key("pid") && hint.has_key("type") && hint["type"] == "b200") {
- sscanf(hint.get("vid").c_str(), "%x", &vid);
- sscanf(hint.get("pid").c_str(), "%x", &pid);
+ vid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("vid"));
+ pid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("pid"));
} else {
vid = B200_VENDOR_ID;
pid = B200_PRODUCT_ID;
@@ -160,9 +161,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
boost::uint16_t vid = B200_VENDOR_ID;
boost::uint16_t pid = B200_PRODUCT_ID;
if (device_addr.has_key("vid"))
- sscanf(device_addr.get("vid").c_str(), "%hx", &vid);
+ vid = uhd::cast::hexstr_cast<boost::uint16_t>(device_addr.get("vid"));
if (device_addr.has_key("pid"))
- sscanf(device_addr.get("pid").c_str(), "%hx", &pid);
+ pid = uhd::cast::hexstr_cast<boost::uint16_t>(device_addr.get("pid"));
std::vector<usb_device_handle::sptr> device_list =
usb_device_handle::get_device_list(vid, pid);
@@ -250,6 +251,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
ctrl_xport_args
);
while (_ctrl_transport->get_recv_buff(0.0)){} //flush ctrl xport
+ _tree->create<double>(mb_path / "link_max_rate").set((usb_speed == 3) ? B200_MAX_RATE_USB3 : B200_MAX_RATE_USB2);
////////////////////////////////////////////////////////////////////
// Async task structure
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index 7d98a8f8d..c3508c550 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -47,11 +47,13 @@
static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x04;
static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0x00;
static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x03;
-static const double B200_LINK_RATE_BPS = (5e9)/8; //practical link rate (5 Gbps)
static const double B200_BUS_CLOCK_RATE = 100e6;
static const double B200_DEFAULT_TICK_RATE = 32e6;
static const boost::uint32_t B200_GPSDO_ST_NONE = 0x83;
+static const size_t B200_MAX_RATE_USB2 = 32000000; // bytes/s
+static const size_t B200_MAX_RATE_USB3 = 500000000; // bytes/s
+
#define FLIP_SID(sid) (((sid)<<16)|((sid)>>16))
static const boost::uint32_t B200_CTRL0_MSG_SID = 0x00000010;
diff --git a/host/lib/usrp/cores/rx_dsp_core_3000.cpp b/host/lib/usrp/cores/rx_dsp_core_3000.cpp
index 86846667f..02c24b4bb 100644
--- a/host/lib/usrp/cores/rx_dsp_core_3000.cpp
+++ b/host/lib/usrp/cores/rx_dsp_core_3000.cpp
@@ -91,8 +91,10 @@ public:
uhd::meta_range_t get_host_rates(void){
meta_range_t range;
- for (int rate = 1024; rate > 512; rate -= 8){
- range.push_back(range_t(_tick_rate/rate));
+ if (!_is_b200) {
+ for (int rate = 1024; rate > 512; rate -= 8){
+ range.push_back(range_t(_tick_rate/rate));
+ }
}
for (int rate = 512; rate > 256; rate -= 4){
range.push_back(range_t(_tick_rate/rate));
diff --git a/host/lib/usrp/dboard/db_tvrx2.cpp b/host/lib/usrp/dboard/db_tvrx2.cpp
index c593c5437..c74c64471 100644
--- a/host/lib/usrp/dboard/db_tvrx2.cpp
+++ b/host/lib/usrp/dboard/db_tvrx2.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010,2012-2013 Ettus Research LLC
+// Copyright 2010,2012-2014 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
@@ -1005,8 +1005,8 @@ tvrx2::tvrx2(ctor_args_t args) : rx_dboard_base(args){
_freq_scalar = (4*16.0e6)/(this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX));
} else if (ref_clock == 100e6) {
-
- this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, REFCLOCK_DIV8);
+
+ this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, REFCLOCK_DIV6);
UHD_LOGV(often) << boost::format(
"TVRX2 (%s): Dividing Refclock by 6"
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index f08709669..4883b2410 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -24,6 +24,7 @@
#include <uhd/usrp/dboard_id.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
#include <uhd/usrp/dboard_eeprom.hpp>
+#include <uhd/convert.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
@@ -103,6 +104,8 @@ static meta_range_t make_overall_tune_range(
return range;
}
+
+
/***********************************************************************
* Gain helper functions
**********************************************************************/
@@ -589,6 +592,11 @@ public:
/*******************************************************************
* RX methods
******************************************************************/
+ rx_streamer::sptr get_rx_stream(const stream_args_t &args) {
+ _check_link_rate(args, false);
+ return this->get_device()->get_rx_stream(args);
+ }
+
void set_rx_subdev_spec(const subdev_spec_t &spec, size_t mboard){
if (mboard != ALL_MBOARDS){
_tree->access<subdev_spec_t>(mb_root(mboard) / "rx_subdev_spec").set(spec);
@@ -770,6 +778,11 @@ public:
/*******************************************************************
* TX methods
******************************************************************/
+ tx_streamer::sptr get_tx_stream(const stream_args_t &args) {
+ _check_link_rate(args, true);
+ return this->get_device()->get_tx_stream(args);
+ }
+
void set_tx_subdev_spec(const subdev_spec_t &spec, size_t mboard){
if (mboard != ALL_MBOARDS){
_tree->access<subdev_spec_t>(mb_root(mboard) / "tx_subdev_spec").set(spec);
@@ -1178,6 +1191,34 @@ private:
}
return gg;
}
+
+ //! \param is_tx True for tx
+ // Assumption is that all mboards use the same link
+ bool _check_link_rate(const stream_args_t &args, bool is_tx) {
+ bool link_rate_is_ok = true;
+ size_t bytes_per_sample = convert::get_bytes_per_item(args.otw_format);
+ double max_link_rate = 0;
+ double sum_rate = 0;
+ BOOST_FOREACH(const size_t chan, args.channels) {
+ mboard_chan_pair mcp = is_tx ? tx_chan_to_mcp(chan) : rx_chan_to_mcp(chan);
+ if (_tree->exists(mb_root(mcp.mboard) / "link_max_rate")) {
+ max_link_rate = std::max(
+ max_link_rate,
+ _tree->access<double>(mb_root(mcp.mboard) / "link_max_rate").get()
+ );
+ }
+ sum_rate += is_tx ? get_tx_rate(chan) : get_rx_rate(chan);
+ }
+ if (max_link_rate > 0 and (max_link_rate / bytes_per_sample) < sum_rate) {
+ UHD_MSG(warning) << boost::format(
+ "The total sum of rates (%f MSps on %u channels) exceeds the maximum capacity of the connection.\n"
+ "This can cause %s."
+ ) % (sum_rate/1e6) % args.channels.size() % (is_tx ? "underruns (U)" : "overflows (O)") << std::endl;
+ link_rate_is_ok = false;
+ }
+
+ return link_rate_is_ok;
+ }
};
/***********************************************************************
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 3b902b343..0ba2e1e4a 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -20,6 +20,7 @@
#include <uhd/utils/safe_call.hpp>
#include <uhd/transport/usb_control.hpp>
#include <uhd/utils/msg.hpp>
+#include <uhd/utils/cast.hpp>
#include <uhd/exception.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/images.hpp>
@@ -59,11 +60,11 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
//since an address and resource is intended for a different, non-USB, device.
if (hint.has_key("addr") || hint.has_key("resource")) return usrp1_addrs;
- unsigned int vid, pid;
+ boost::uint16_t vid, pid;
if(hint.has_key("vid") && hint.has_key("pid") && hint.has_key("type") && hint["type"] == "usrp1") {
- sscanf(hint.get("vid").c_str(), "%x", &vid);
- sscanf(hint.get("pid").c_str(), "%x", &pid);
+ vid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("vid"));
+ pid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("pid"));
} else {
vid = USRP1_VENDOR_ID;
pid = USRP1_PRODUCT_ID;
@@ -409,7 +410,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){
_tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(_rx_subdev_spec);
if (_tree->list(mb_path / "tx_dsps").size() > 0)
_tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(_tx_subdev_spec);
-
+ _tree->create<double>(mb_path / "link_max_rate").set(USRP1_MAX_RATE_USB2);
}
usrp1_impl::~usrp1_impl(void){
diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp
index da9fe8b16..012bc0794 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.hpp
@@ -39,6 +39,7 @@
#define INCLUDED_USRP1_IMPL_HPP
static const std::string USRP1_EEPROM_MAP_KEY = "B000";
+static const size_t USRP1_MAX_RATE_USB2 = 32000000; // bytes/s
#define FR_RB_CAPS 3
#define FR_MODE 13
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 16d9b9a54..918f3e892 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -442,6 +442,7 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
_mbc[mb].spiface = _mbc[mb].iface;
break;
}
+ _tree->create<double>(mb_path / "link_max_rate").set(USRP2_LINK_RATE_BPS);
////////////////////////////////////////////////////////////////
// setup the mboard eeprom
@@ -655,12 +656,14 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
.subscribe(boost::bind(&time64_core_200::set_time_next_pps, _mbc[mb].time64, _1));
//setup time source props
_tree->create<std::string>(mb_path / "time_source/value")
- .subscribe(boost::bind(&time64_core_200::set_time_source, _mbc[mb].time64, _1));
+ .subscribe(boost::bind(&time64_core_200::set_time_source, _mbc[mb].time64, _1))
+ .set("none");
_tree->create<std::vector<std::string> >(mb_path / "time_source/options")
.publish(boost::bind(&time64_core_200::get_time_sources, _mbc[mb].time64));
//setup reference source props
_tree->create<std::string>(mb_path / "clock_source/value")
- .subscribe(boost::bind(&usrp2_impl::update_clock_source, this, mb, _1));
+ .subscribe(boost::bind(&usrp2_impl::update_clock_source, this, mb, _1))
+ .set("internal");
std::vector<std::string> clock_sources = boost::assign::list_of("internal")("external")("mimo");
if (_mbc[mb].gps and _mbc[mb].gps->gps_detected()) clock_sources.push_back("gpsdo");
_tree->create<std::vector<std::string> >(mb_path / "clock_source/options").set(clock_sources);
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index e492b2238..f5e53678c 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -392,6 +392,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
//Tell the quirks object which FIFOs carry TX stream data
const uint32_t tx_data_fifos[2] = {X300_RADIO_DEST_PREFIX_TX, X300_RADIO_DEST_PREFIX_TX + 3};
mb.rio_fpga_interface->get_kernel_proxy().get_rio_quirks().register_tx_streams(tx_data_fifos);
+
+ _tree->create<double>(mb_path / "link_max_rate").set(X300_MAX_RATE_PCIE);
}
BOOST_FOREACH(const std::string &key, dev_addr.keys())
@@ -456,6 +458,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
<< "UHD will use the auto-detected max frame size for this connection."
<< std::endl;
}
+
+ _tree->create<double>(mb_path / "link_max_rate").set(X300_MAX_RATE_10GIGE);
}
//create basic communication
@@ -1133,11 +1137,14 @@ x300_impl::both_xports_t x300_impl::make_transport(
if (mb.loaded_fpga_image == "HGS") {
if (mb.router_dst_here == X300_XB_DST_E0) {
eth_data_rec_frame_size = X300_1GE_DATA_FRAME_MAX_SIZE;
+ _tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_1GIGE);
} else if (mb.router_dst_here == X300_XB_DST_E1) {
eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
+ _tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_10GIGE);
}
} else if (mb.loaded_fpga_image == "XGS") {
- eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
+ eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
+ _tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_10GIGE);
}
if (eth_data_rec_frame_size == 0) {
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 259ea253d..4b3efc845 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -76,6 +76,19 @@ static const size_t X300_ETH_MSG_NUM_FRAMES = 32;
static const size_t X300_ETH_DATA_NUM_FRAMES = 32;
static const double X300_DEFAULT_SYSREF_RATE = 10e6;
+static const size_t X300_TX_MAX_HDR_LEN = // bytes
+ sizeof(boost::uint32_t) // Header
+ + sizeof(uhd::transport::vrt::if_packet_info_t().sid) // SID
+ + sizeof(uhd::transport::vrt::if_packet_info_t().tsf); // Timestamp
+static const size_t X300_RX_MAX_HDR_LEN = // bytes
+ sizeof(boost::uint32_t) // Header
+ + sizeof(uhd::transport::vrt::if_packet_info_t().sid) // SID
+ + sizeof(uhd::transport::vrt::if_packet_info_t().tsf); // Timestamp
+
+static const size_t X300_MAX_RATE_PCIE = 800000000; // bytes/s
+static const size_t X300_MAX_RATE_10GIGE = 800000000; // bytes/s
+static const size_t X300_MAX_RATE_1GIGE = 100000000; // bytes/s
+
#define X300_RADIO_DEST_PREFIX_TX 0
#define X300_RADIO_DEST_PREFIX_CTRL 1
#define X300_RADIO_DEST_PREFIX_RX 2
diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp
index 85de34a54..9263c9b44 100644
--- a/host/lib/usrp/x300/x300_io_impl.cpp
+++ b/host/lib/usrp/x300/x300_io_impl.cpp
@@ -242,6 +242,8 @@ struct x300_tx_fc_guts_t
boost::shared_ptr<x300_impl::async_md_type> old_async_queue;
};
+#define X300_ASYNC_EVENT_CODE_FLOW_CTRL 0
+
static size_t get_tx_flow_control_window(size_t frame_size, const device_addr_t& tx_args)
{
double hw_buff_size = tx_args.cast<double>("send_buff_size", X300_TX_HW_BUFF_SIZE);
@@ -283,23 +285,28 @@ static void handle_tx_async_msgs(boost::shared_ptr<x300_tx_fc_guts_t> guts, zero
return;
}
- //catch the flow control packets and react
- if (endian_conv(packet_buff[if_packet_info.num_header_words32+0]) == 0)
- {
- const size_t seq = endian_conv(packet_buff[if_packet_info.num_header_words32+1]);
- guts->seq_queue.push_with_haste(seq);
- return;
- }
-
//fill in the async metadata
async_metadata_t metadata;
load_metadata_from_buff(
endian_conv, metadata, if_packet_info, packet_buff,
clock->get_master_clock_rate(), guts->stream_channel);
- guts->async_queue->push_with_pop_on_full(metadata);
- metadata.channel = guts->device_channel;
- guts->old_async_queue->push_with_pop_on_full(metadata);
- standard_async_msg_prints(metadata);
+
+ //The FC response and the burst ack are two indicators that the radio
+ //consumed packets. Use them to update the FC metadata
+ if (metadata.event_code == X300_ASYNC_EVENT_CODE_FLOW_CTRL or
+ metadata.event_code == async_metadata_t::EVENT_CODE_BURST_ACK
+ ) {
+ const size_t seq = metadata.user_payload[0];
+ guts->seq_queue.push_with_pop_on_full(seq);
+ }
+
+ //FC responses don't propagate up to the user so filter them here
+ if (metadata.event_code != X300_ASYNC_EVENT_CODE_FLOW_CTRL) {
+ guts->async_queue->push_with_pop_on_full(metadata);
+ metadata.channel = guts->device_channel;
+ guts->old_async_queue->push_with_pop_on_full(metadata);
+ standard_async_msg_prints(metadata);
+ }
}
static managed_send_buffer::sptr get_tx_buff_with_flowctrl(
@@ -319,7 +326,9 @@ static managed_send_buffer::sptr get_tx_buff_with_flowctrl(
}
managed_send_buffer::sptr buff = xport->get_send_buff(timeout);
- if (buff) guts->last_seq_out++; //update seq, this will actually be a send
+ if (buff) {
+ guts->last_seq_out++; //update seq, this will actually be a send
+ }
return buff;
}
@@ -399,15 +408,9 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)
both_xports_t xport = this->make_transport(mb_index, dest, X300_RADIO_DEST_PREFIX_RX, device_addr, data_sid);
UHD_LOG << boost::format("data_sid = 0x%08x, actual recv_buff_size = %d\n") % data_sid % xport.recv_buff_size << std::endl;
- //calculate packet size
- static const size_t hdr_size = 0
- + vrt::num_vrl_words32*sizeof(boost::uint32_t)
- + vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- - sizeof(vrt::if_packet_info_t().cid) //no class id ever used
- - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
- ;
- const size_t bpp = xport.recv->get_recv_frame_size() - hdr_size; // bytes per packet
+ // To calculate the max number of samples per packet, we assume the maximum header length
+ // to avoid fragmentation should the entire header be used.
+ const size_t bpp = xport.recv->get_recv_frame_size() - X300_RX_MAX_HDR_LEN; // bytes per packet
const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item
const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); // samples per packet
@@ -568,15 +571,9 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_)
both_xports_t xport = this->make_transport(mb_index, dest, X300_RADIO_DEST_PREFIX_TX, device_addr, data_sid);
UHD_LOG << boost::format("data_sid = 0x%08x\n") % data_sid << std::endl;
- //calculate packet size
- static const size_t hdr_size = 0
- + vrt::num_vrl_words32*sizeof(boost::uint32_t)
- + vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- //+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- - sizeof(vrt::if_packet_info_t().cid) //no class id ever used
- - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
- ;
- const size_t bpp = xport.send->get_send_frame_size() - hdr_size;
+ // To calculate the max number of samples per packet, we assume the maximum header length
+ // to avoid fragmentation should the entire header be used.
+ const size_t bpp = xport.send->get_send_frame_size() - X300_TX_MAX_HDR_LEN;
const size_t bpi = convert::get_bytes_per_item(args.otw_format);
const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi));