summaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp23
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp6
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp96
3 files changed, 93 insertions, 32 deletions
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 6f1184ad7..766ea993c 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -97,16 +97,19 @@ usrp2_mboard_impl::usrp2_mboard_impl(
_iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID);
_iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET);
- //setting the cycles per update
- const double ups_per_sec = flow_control_hints.cast<double>("ups_per_sec", 100);
- const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec);
- _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up);
- _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, 0); //cycles per update is disabled
-
- //setting the packets per update
- const double ups_per_fifo = flow_control_hints.cast<double>("ups_per_fifo", 8);
- const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size());
- _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up);
+ //setting the cycles per update (disabled by default)
+ const double ups_per_sec = flow_control_hints.cast<double>("ups_per_sec", 0.0);
+ if (ups_per_sec > 0.0){
+ const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec);
+ _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up);
+ }
+
+ //setting the packets per update (enabled by default)
+ const double ups_per_fifo = flow_control_hints.cast<double>("ups_per_fifo", 8.0);
+ if (ups_per_fifo > 0.0){
+ const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size());
+ _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up);
+ }
//init the ddc
init_ddc_config();
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 257c1daa9..ffbe8eedb 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -33,6 +33,8 @@ using namespace uhd;
using namespace uhd::usrp;
using namespace uhd::transport;
+static const double CTRL_RECV_TIMEOUT = 1.0;
+
class usrp2_iface_impl : public usrp2_iface{
public:
/***********************************************************************
@@ -247,7 +249,7 @@ public:
boost::uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; //allocate max bytes for recv
const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem);
while(true){
- size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem));
+ size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem), CTRL_RECV_TIMEOUT);
if(len >= sizeof(boost::uint32_t) and ntohl(ctrl_data_in->proto_ver) != USRP2_FW_COMPAT_NUM){
throw std::runtime_error(str(boost::format(
"Expected protocol compatibility number %d, but got %d:\n"
@@ -260,7 +262,7 @@ public:
if (len == 0) break; //timeout
//didnt get seq or bad packet, continue looking...
}
- throw std::runtime_error(this->get_cname() + ": no control response");
+ throw std::runtime_error("no control response");
}
rev_type get_rev(void){
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 610e2f404..c3bbe4d65 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -27,6 +27,7 @@
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/regex.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp> //htonl and ntohl
#include <iostream>
@@ -43,10 +44,76 @@ template <class T> std::string num2str(T num){
return boost::lexical_cast<std::string>(num);
}
+//! separate indexed device addresses into a vector of device addresses
+device_addrs_t sep_indexed_dev_addrs(const device_addr_t &dev_addr){
+ //------------ support old deprecated way and print warning --------
+ if (dev_addr.has_key("addr")){
+ std::vector<std::string> addrs = std::split_string(dev_addr["addr"]);
+ if (addrs.size() > 1){
+ device_addr_t fixed_dev_addr = dev_addr;
+ fixed_dev_addr.pop("addr");
+ for (size_t i = 0; i < addrs.size(); i++){
+ fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i];
+ }
+ uhd::warning::post(
+ "addr = <space separated list of ip addresses> is deprecated.\n"
+ "To address a multi-device, use multiple <key><index> = <val>.\n"
+ "See the USRP-NXXX application notes. Two device example:\n"
+ " addr0 = 192.168.10.2\n"
+ " addr1 = 192.168.10.3\n"
+ );
+ return sep_indexed_dev_addrs(fixed_dev_addr);
+ }
+ }
+ //------------------------------------------------------------------
+ device_addrs_t dev_addrs;
+ BOOST_FOREACH(const std::string &key, dev_addr.keys()){
+ boost::cmatch matches;
+ if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){
+ throw std::runtime_error("unknown key format: " + key);
+ }
+ std::string key_part(matches[1].first, matches[1].second);
+ std::string num_part(matches[2].first, matches[2].second);
+ size_t num = (num_part.empty())? 0 : boost::lexical_cast<size_t>(num_part);
+ dev_addrs.resize(std::max(num+1, dev_addrs.size()));
+ dev_addrs[num][key_part] = dev_addr[key];
+ }
+ return dev_addrs;
+}
+
+//! combine a vector in device addresses into an indexed device address
+device_addr_t combine_dev_addr_vector(const device_addrs_t &dev_addrs){
+ device_addr_t dev_addr;
+ for (size_t i = 0; i < dev_addrs.size(); i++){
+ BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){
+ dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key];
+ }
+ }
+ return dev_addr;
+}
+
/***********************************************************************
* Discovery over the udp transport
**********************************************************************/
-static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
+static device_addrs_t usrp2_find(const device_addr_t &hint_){
+ //handle the multi-device discovery
+ device_addrs_t hints = sep_indexed_dev_addrs(hint_);
+ if (hints.size() > 1){
+ device_addrs_t found_devices;
+ BOOST_FOREACH(const device_addr_t &hint_i, hints){
+ device_addrs_t found_devices_i = usrp2_find(hint_i);
+ if (found_devices_i.size() != 1) throw std::runtime_error(str(boost::format(
+ "Could not resolve device hint \"%s\" to a single device."
+ ) % hint_i.to_string()));
+ found_devices.push_back(found_devices_i[0]);
+ }
+ return device_addrs_t(1, combine_dev_addr_vector(found_devices));
+ }
+
+ //initialize the hint for a single device case
+ UHD_ASSERT_THROW(hints.size() <= 1);
+ hints.resize(1); //in case it was empty
+ device_addr_t hint = hints[0];
device_addrs_t usrp2_addrs;
//return an empty list of addresses when type is set to non-usrp2
@@ -71,16 +138,6 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
return usrp2_addrs;
}
- //if there are multiple addresses, just return good, dont test
- std::vector<std::string> addrs = std::split_string(hint["addr"]);
- if (addrs.size() > 1){
- device_addr_t new_addr;
- new_addr["type"] = "usrp2";
- new_addr["addr"] = hint["addr"];
- usrp2_addrs.push_back(new_addr);
- return usrp2_addrs;
- }
-
//create a udp transport to communicate
std::string ctrl_port = boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT);
udp_simple::sptr udp_transport = udp_simple::make_broadcast(
@@ -106,9 +163,8 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
new_addr["type"] = "usrp2";
new_addr["addr"] = ip_addr.to_string();
//Attempt to read the name from the EEPROM and perform filtering.
- //This operation can throw due to COMPAT mismatch. That is OK.
- //We will allow the device to be found and the COMPAT mismatch
- //will be thrown as an exception in the factory function.
+ //This operation can throw due to compatibility mismatch.
+ //In this case, the discovered device will be ignored.
try{
mboard_eeprom_t mb_eeprom = usrp2_iface::make(
udp_simple::make_connected(new_addr["addr"], num2str(USRP2_UDP_CTRL_PORT))
@@ -141,17 +197,17 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
* Make
**********************************************************************/
static device::sptr usrp2_make(const device_addr_t &device_addr){
-
+sep_indexed_dev_addrs(device_addr);
//create a ctrl and data transport for each address
std::vector<udp_simple::sptr> ctrl_transports;
std::vector<zero_copy_if::sptr> data_transports;
- BOOST_FOREACH(const std::string &addr, std::split_string(device_addr["addr"])){
+ BOOST_FOREACH(const device_addr_t &dev_addr_i, sep_indexed_dev_addrs(device_addr)){
ctrl_transports.push_back(udp_simple::make_connected(
- addr, num2str(USRP2_UDP_CTRL_PORT)
+ dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT)
));
data_transports.push_back(udp_zero_copy::make(
- addr, num2str(USRP2_UDP_DATA_PORT), device_addr
+ dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), device_addr
));
}
@@ -217,8 +273,8 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<device_prop_t>()){
case DEVICE_PROP_NAME:
- if (_mboards.size() > 1) val = std::string("USRP-NXXX mimo device");
- else val = std::string("USRP-NXXX device");
+ if (_mboards.size() > 1) val = std::string("USRP2/N Series multi-device");
+ else val = std::string("USRP2/N Series device");
return;
case DEVICE_PROP_MBOARD: