aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-03-30 13:32:52 +0000
committerJosh Blum <josh@joshknows.com>2010-03-30 13:32:52 +0000
commitf94fa1e464c9e2a87274c991dc6461f7f4c956d8 (patch)
tree1b88020a0dece1ae509cf3fb219b7cce487dc198 /host/lib
parent29e88b3478aad89ff76363029395200a8601e667 (diff)
parent281307833c8275031bd2469e6aef3f472490749a (diff)
downloaduhd-f94fa1e464c9e2a87274c991dc6461f7f4c956d8.tar.gz
uhd-f94fa1e464c9e2a87274c991dc6461f7f4c956d8.tar.bz2
uhd-f94fa1e464c9e2a87274c991dc6461f7f4c956d8.zip
Merge branch 'master' of git@ettus.sourcerepo.com:ettus/uhd into usrp_e
Conflicts: host/include/uhd/usrp/dboard_id.hpp host/lib/usrp/usrp2/usrp2_impl.cpp
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/CMakeLists.txt39
-rw-r--r--host/lib/device.cpp29
-rw-r--r--host/lib/device_addr.cpp86
-rw-r--r--host/lib/gain_handler.cpp28
-rw-r--r--host/lib/load_modules.cpp8
-rw-r--r--host/lib/metadata.cpp37
-rw-r--r--host/lib/simple_device.cpp140
-rw-r--r--host/lib/time_spec.cpp40
-rwxr-xr-xhost/lib/transport/gen_vrt.py206
-rw-r--r--host/lib/transport/if_addrs.cpp109
-rw-r--r--host/lib/transport/udp_simple.cpp1
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp3
-rw-r--r--host/lib/transport/vrt.cpp550
-rw-r--r--host/lib/tune_helper.cpp125
-rw-r--r--host/lib/types.cpp206
-rw-r--r--host/lib/usrp/dboard/basic.cpp35
-rw-r--r--host/lib/usrp/dboard_base.cpp16
-rw-r--r--host/lib/usrp/dboard_manager.cpp23
-rw-r--r--host/lib/usrp/usrp1e/usrp1e_none.cpp2
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp3
-rw-r--r--host/lib/usrp/usrp2/dboard_interface.cpp2
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp68
-rw-r--r--host/lib/usrp/usrp2/fw_common.h16
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp121
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp88
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp29
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp24
27 files changed, 1442 insertions, 592 deletions
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 46cce729e..323b69b14 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -20,14 +20,13 @@
########################################################################
SET(libuhd_sources
device.cpp
- device_addr.cpp
gain_handler.cpp
load_modules.cpp
- metadata.cpp
simple_device.cpp
- time_spec.cpp
+ tune_helper.cpp
types.cpp
wax.cpp
+ transport/if_addrs.cpp
transport/udp_simple.cpp
transport/vrt.cpp
usrp/dboard/basic.cpp
@@ -83,22 +82,42 @@ ENDIF(HAS_USRP1E_REQUIRED_HEADERS)
########################################################################
# Setup defines for module loading
########################################################################
-INCLUDE(CheckIncludeFileCXX)
+MESSAGE(STATUS "Configuring module loading...")
+INCLUDE(CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H)
-CHECK_INCLUDE_FILE_CXX(Winbase.h HAVE_WINBASE_H)
+CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H)
IF(HAVE_DLFCN_H)
- MESSAGE(STATUS "Module loading supported through dlopen...")
+ MESSAGE(STATUS " Module loading supported through dlopen.")
ADD_DEFINITIONS(-DHAVE_DLFCN_H)
-ELSEIF(HAVE_WINBASE_H)
- MESSAGE(STATUS "Module loading supported through LoadLibrary...")
- ADD_DEFINITIONS(-DHAVE_WINBASE_H)
+ELSEIF(HAVE_WINDOWS_H)
+ MESSAGE(STATUS " Module loading supported through LoadLibrary.")
+ ADD_DEFINITIONS(-DHAVE_WINDOWS_H)
ELSE(HAVE_DLFCN_H)
- MESSAGE(STATUS "Module loading not supported...")
+ MESSAGE(STATUS " Module loading not supported.")
ENDIF(HAVE_DLFCN_H)
########################################################################
+# Setup defines for interface address discovery
+########################################################################
+MESSAGE(STATUS "Configuring interface address discovery...")
+
+INCLUDE(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H)
+CHECK_INCLUDE_FILE_CXX(winsock2.h HAVE_WINSOCK2_H)
+
+IF(HAVE_IFADDRS_H)
+ MESSAGE(STATUS " Interface address discovery supported through getifaddrs.")
+ ADD_DEFINITIONS(-DHAVE_IFADDRS_H)
+ELSEIF(HAVE_WINSOCK2_H)
+ MESSAGE(STATUS " Interface address discovery supported through SIO_GET_INTERFACE_LIST.")
+ ADD_DEFINITIONS(-DHAVE_WINSOCK2_H)
+ELSE(HAVE_IFADDRS_H)
+ MESSAGE(STATUS " Interface address discovery not supported.")
+ENDIF(HAVE_IFADDRS_H)
+
+########################################################################
# Setup libuhd library
########################################################################
ADD_LIBRARY(uhd SHARED ${libuhd_sources})
diff --git a/host/lib/device.cpp b/host/lib/device.cpp
index cd8a01ab4..27a365d34 100644
--- a/host/lib/device.cpp
+++ b/host/lib/device.cpp
@@ -16,8 +16,9 @@
//
#include <uhd/device.hpp>
-#include <uhd/dict.hpp>
-#include <uhd/utils.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/weak_ptr.hpp>
@@ -46,7 +47,7 @@ static size_t hash_device_addr(
//combine the hashes of sorted keys/value pairs
size_t hash = 0;
- BOOST_FOREACH(std::string key, keys){
+ BOOST_FOREACH(const std::string &key, keys){
boost::hash_combine(hash, key);
boost::hash_combine(hash, dev_addr[key]);
}
@@ -56,26 +57,26 @@ static size_t hash_device_addr(
/***********************************************************************
* Registration
**********************************************************************/
-typedef boost::tuple<device::discover_t, device::make_t> dev_fcn_reg_t;
+typedef boost::tuple<device::find_t, device::make_t> dev_fcn_reg_t;
// instantiate the device function registry container
-STATIC_INSTANCE(std::vector<dev_fcn_reg_t>, get_dev_fcn_regs)
+UHD_SINGLETON_FCN(std::vector<dev_fcn_reg_t>, get_dev_fcn_regs)
void device::register_device(
- const discover_t &discover,
+ const find_t &find,
const make_t &make
){
//std::cout << "registering device" << std::endl;
- get_dev_fcn_regs().push_back(dev_fcn_reg_t(discover, make));
+ get_dev_fcn_regs().push_back(dev_fcn_reg_t(find, make));
}
/***********************************************************************
* Discover
**********************************************************************/
-device_addrs_t device::discover(const device_addr_t &hint){
+device_addrs_t device::find(const device_addr_t &hint){
device_addrs_t device_addrs;
- BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){
+ BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){
device_addrs_t discovered_addrs = fcn.get<0>()(hint);
device_addrs.insert(
device_addrs.begin(),
@@ -94,11 +95,11 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
typedef boost::tuple<device_addr_t, make_t> dev_addr_make_t;
std::vector<dev_addr_make_t> dev_addr_makers;
- BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){
+ BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){
BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){
//copy keys that were in hint but not in dev_addr
//this way, we can pass additional transport arguments
- BOOST_FOREACH(std::string key, hint.get_keys()){
+ BOOST_FOREACH(const std::string &key, hint.get_keys()){
if (not dev_addr.has_key(key)) dev_addr[key] = hint[key];
}
//append the discovered address and its factory function
@@ -109,14 +110,14 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
//check that we found any devices
if (dev_addr_makers.size() == 0){
throw std::runtime_error(str(
- boost::format("No devices found for ----->\n%s") % device_addr::to_string(hint)
+ boost::format("No devices found for ----->\n%s") % hint.to_string()
));
}
//check that the which index is valid
if (dev_addr_makers.size() <= which){
throw std::runtime_error(str(
- boost::format("No device at index %d for ----->\n%s") % which % device_addr::to_string(hint)
+ boost::format("No device at index %d for ----->\n%s") % which % hint.to_string()
));
}
@@ -136,7 +137,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
return hash_to_device[dev_hash].lock();
}
//create and register a new device
- catch(const std::assert_error &){
+ catch(const uhd::assert_error &){
device::sptr dev = maker(dev_addr);
hash_to_device[dev_hash] = dev;
return dev;
diff --git a/host/lib/device_addr.cpp b/host/lib/device_addr.cpp
deleted file mode 100644
index d26bb4b9d..000000000
--- a/host/lib/device_addr.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Copyright 2010 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 <uhd/device_addr.hpp>
-#include <sstream>
-#include <cstring>
-#include <stdexcept>
-#include <boost/format.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/foreach.hpp>
-
-//----------------------- u2 mac addr wrapper ------------------------//
-uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){
- std::string mac_addr_str = (mac_addr_str_ == "")? "ff:ff:ff:ff:ff:ff" : mac_addr_str_;
-
- //ether_aton_r(str.c_str(), &mac_addr);
- boost::uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB
-
- try{
- //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx
- //the IAB above will fill in for the shorter pattern
- if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17)
- throw std::runtime_error("expected exactly 5 or 17 characters");
-
- //split the mac addr hex string at the colons
- std::vector<std::string> hex_strs;
- boost::split(hex_strs, mac_addr_str, boost::is_any_of(":"));
- for (size_t i = 0; i < hex_strs.size(); i++){
- int hex_num;
- std::istringstream iss(hex_strs[i]);
- iss >> std::hex >> hex_num;
- p[i] = boost::uint8_t(hex_num);
- }
-
- }
- catch(std::exception const& e){
- throw std::runtime_error(str(
- boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what()
- ));
- }
-
- memcpy(&mac_addr, p, sizeof(mac_addr));
-}
-
-std::string uhd::mac_addr_t::to_string(void) const{
- //ether_ntoa_r(&mac_addr, addr_buf);
- const boost::uint8_t *p = reinterpret_cast<const boost::uint8_t *>(&mac_addr);
- return str(
- boost::format("%02x:%02x:%02x:%02x:%02x:%02x")
- % int(p[0]) % int(p[1]) % int(p[2])
- % int(p[3]) % int(p[4]) % int(p[5])
- );
-}
-
-std::ostream& operator<<(std::ostream &os, const uhd::mac_addr_t &x){
- os << x.to_string();
- return os;
-}
-
-//----------------------- usrp device_addr_t wrapper -------------------------//
-std::string uhd::device_addr::to_string(const uhd::device_addr_t &device_addr){
- std::stringstream ss;
- BOOST_FOREACH(std::string key, device_addr.get_keys()){
- ss << boost::format("%s: %s") % key % device_addr[key] << std::endl;
- }
- return ss.str();
-}
-
-std::ostream& operator<<(std::ostream &os, const uhd::device_addr_t &device_addr){
- os << uhd::device_addr::to_string(device_addr);
- return os;
-}
diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp
index 7dd1547cb..daf629f0b 100644
--- a/host/lib/gain_handler.cpp
+++ b/host/lib/gain_handler.cpp
@@ -15,9 +15,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/gain_handler.hpp>
-#include <uhd/utils.hpp>
-#include <uhd/types.hpp>
+#include <uhd/utils/gain_handler.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/ranges.hpp>
#include <uhd/props.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
@@ -47,7 +47,7 @@ private:
is_equal_t _is_equal;
prop_names_t get_gain_names(void);
- gain_t get_overall_gain_val(void);
+ float get_overall_gain_val(void);
gain_range_t get_overall_gain_range(void);
template <class T> T get_named_prop(const wax::obj &prop, const std::string &name){
return _link[named_prop_t(prop, name)].as<T>();
@@ -90,21 +90,21 @@ prop_names_t gain_handler_impl::get_gain_names(void){
return _link[_props.names].as<prop_names_t>();
}
-gain_t gain_handler_impl::get_overall_gain_val(void){
- gain_t gain_val = 0;
+float gain_handler_impl::get_overall_gain_val(void){
+ float gain_val = 0;
BOOST_FOREACH(std::string name, get_gain_names()){
- gain_val += get_named_prop<gain_t>(_props.value, name);
+ gain_val += get_named_prop<float>(_props.value, name);
}
return gain_val;
}
gain_range_t gain_handler_impl::get_overall_gain_range(void){
- gain_t gain_min = 0, gain_max = 0, gain_step = 0;
+ float gain_min = 0, gain_max = 0, gain_step = 0;
BOOST_FOREACH(std::string name, get_gain_names()){
- gain_range_t gain_tmp = get_named_prop<gain_range_t>(_props.range, name);
- gain_min += gain_tmp.min;
- gain_max += gain_tmp.max;
- gain_step = std::max(gain_step, gain_tmp.step);
+ gain_range_t floatmp = get_named_prop<gain_range_t>(_props.range, name);
+ gain_min += floatmp.min;
+ gain_max += floatmp.max;
+ gain_step = std::max(gain_step, floatmp.step);
}
return gain_range_t(gain_min, gain_max, gain_step);
}
@@ -145,7 +145,7 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val)
//not a gain value key... dont handle
if (not _is_equal(key, _props.value)) return false;
- gain_t gain_val = val.as<gain_t>();
+ float gain_val = val.as<float>();
//not a wildcard... dont handle (but check name and range)
if (name != ""){
@@ -164,7 +164,7 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val)
gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name);
//clip g to be within the allowed range
- gain_t g = std::min(std::max(gain_val, gain.min), gain.max);
+ float g = std::min(std::max(gain_val, gain.min), gain.max);
//set g to be a multiple of the step size
g -= std::fmod(g, gain.step);
//set g to be the new gain
diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp
index 700afcd3f..babff1ca5 100644
--- a/host/lib/load_modules.cpp
+++ b/host/lib/load_modules.cpp
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/static.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
@@ -40,8 +40,8 @@ static void load_module(const std::string &file_name){
}
}
-#elif HAVE_WINBASE_H
-#include <Winbase.h>
+#elif HAVE_WINDOWS_H
+#include <windows.h>
static void load_module(const std::string &file_name){
if (LoadLibrary(file_name.c_str()) == NULL){
@@ -101,7 +101,7 @@ static void load_path(const fs::path &path){
* Load all the modules given by the module path enviroment variable.
* The path variable may be several paths split by path separators.
*/
-STATIC_BLOCK(load_modules){
+UHD_STATIC_BLOCK(load_modules){
//get the environment variable module path
char *env_module_path = std::getenv("UHD_MODULE_PATH");
if (env_module_path == NULL) return;
diff --git a/host/lib/metadata.cpp b/host/lib/metadata.cpp
deleted file mode 100644
index 40fdb7c73..000000000
--- a/host/lib/metadata.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright 2010 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 <uhd/metadata.hpp>
-
-using namespace uhd;
-
-rx_metadata_t::rx_metadata_t(void){
- stream_id = 0;
- has_stream_id = false;
- time_spec = time_spec_t();
- has_time_spec = false;
- is_fragment = false;
-}
-
-tx_metadata_t::tx_metadata_t(void){
- stream_id = 0;
- has_stream_id = false;
- time_spec = time_spec_t();
- has_time_spec = false;
- start_of_burst = false;
- end_of_burst = false;
-}
diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp
index ba1966e0d..25beb45a9 100644
--- a/host/lib/simple_device.cpp
+++ b/host/lib/simple_device.cpp
@@ -16,11 +16,9 @@
//
#include <uhd/simple_device.hpp>
-#include <uhd/device.hpp>
-#include <uhd/utils.hpp>
+#include <uhd/utils/tune_helper.hpp>
+#include <uhd/utils/assert.hpp>
#include <uhd/props.hpp>
-#include <uhd/types.hpp>
-#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <stdexcept>
@@ -28,89 +26,8 @@
using namespace uhd;
/***********************************************************************
- * Tune Helper Function
- **********************************************************************/
-static tune_result_t tune(
- double target_freq,
- double lo_offset,
- wax::obj subdev,
- wax::obj dxc,
- bool is_tx
-){
- wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
- bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
- bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>();
- wax::obj dxc_freq_proxy = dxc[std::string("freq")];
- double dxc_sample_rate = dxc[std::string("rate")].as<double>();
-
- // Ask the d'board to tune as closely as it can to target_freq+lo_offset
- double target_inter_freq = target_freq + lo_offset;
- subdev_freq_proxy = target_inter_freq;
- double actual_inter_freq = subdev_freq_proxy.as<double>();
-
- // Calculate the DDC setting that will downconvert the baseband from the
- // daughterboard to our target frequency.
- double delta_freq = target_freq - actual_inter_freq;
- double delta_sign = std::signum(delta_freq);
- delta_freq *= delta_sign;
- delta_freq = fmod(delta_freq, dxc_sample_rate);
- bool inverted = delta_freq > dxc_sample_rate/2.0;
- double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq);
- target_dxc_freq *= delta_sign;
-
- // If the spectrum is inverted, and the daughterboard doesn't do
- // quadrature downconversion, we can fix the inversion by flipping the
- // sign of the dxc_freq... (This only happens using the basic_rx board)
- if (subdev_spectrum_inverted){
- inverted = not inverted;
- }
- if (inverted and not subdev_quadrature){
- target_dxc_freq *= -1.0;
- inverted = not inverted;
- }
- // down conversion versus up conversion, fight!
- // your mother is ugly and your going down...
- target_dxc_freq *= (is_tx)? -1.0 : +1.0;
-
- dxc_freq_proxy = target_dxc_freq;
- double actual_dxc_freq = dxc_freq_proxy.as<double>();
-
- //return some kind of tune result tuple/struct
- tune_result_t tune_result;
- tune_result.target_inter_freq = target_inter_freq;
- tune_result.actual_inter_freq = actual_inter_freq;
- tune_result.target_dxc_freq = target_dxc_freq;
- tune_result.actual_dxc_freq = actual_dxc_freq;
- tune_result.spectrum_inverted = inverted;
- return tune_result;
-}
-
-/***********************************************************************
* Helper Functions
**********************************************************************/
-static std::string trim(const std::string &in){
- return boost::algorithm::trim_copy(in);
-}
-
-device_addr_t args_to_device_addr(const std::string &args){
- device_addr_t addr;
-
- //split the args at the semi-colons
- std::vector<std::string> pairs;
- boost::split(pairs, args, boost::is_any_of(";"));
- BOOST_FOREACH(std::string pair, pairs){
- if (trim(pair) == "") continue;
-
- //split the key value pairs at the equals
- std::vector<std::string> key_val;
- boost::split(key_val, pair, boost::is_any_of("="));
- if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args);
- addr[trim(key_val[0])] = trim(key_val[1]);
- }
-
- return addr;
-}
-
static std::vector<double> get_xx_rates(wax::obj decerps, wax::obj rate){
std::vector<double> rates;
BOOST_FOREACH(size_t decerp, decerps.as<std::vector<size_t> >()){
@@ -154,42 +71,42 @@ public:
}
/*******************************************************************
- * Streaming
+ * Timing
******************************************************************/
- void set_streaming(bool enb){
- _rx_ddc[std::string("enabled")] = enb;
+ void set_time_now(const time_spec_t &time_spec){
+ _mboard[MBOARD_PROP_TIME_NOW] = time_spec;
}
- bool get_streaming(void){
- return _rx_ddc[std::string("enabled")].as<bool>();
+ void set_time_next_pps(const time_spec_t &time_spec){
+ _mboard[MBOARD_PROP_TIME_NEXT_PPS] = time_spec;
+ }
+
+ /*******************************************************************
+ * Streaming
+ ******************************************************************/
+ void issue_stream_cmd(const stream_cmd_t &stream_cmd){
+ _rx_ddc[std::string("stream_cmd")] = stream_cmd;
}
/*******************************************************************
* RX methods
******************************************************************/
void set_rx_rate(double rate){
- double samp_rate = _rx_ddc[std::string("rate")].as<double>();
+ double samp_rate = _rx_ddc[std::string("if_rate")].as<double>();
assert_has(get_rx_rates(), rate, "simple device rx rate");
_rx_ddc[std::string("decim")] = size_t(samp_rate/rate);
}
double get_rx_rate(void){
- double samp_rate = _rx_ddc[std::string("rate")].as<double>();
- size_t decim = _rx_ddc[std::string("decim")].as<size_t>();
- return samp_rate/decim;
+ return _rx_ddc[std::string("bb_rate")].as<double>();
}
std::vector<double> get_rx_rates(void){
- return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("rate")]);
+ return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("if_rate")]);
}
tune_result_t set_rx_freq(double target_freq){
- double lo_offset = 0.0;
- //if the local oscillator will be in the passband, use an offset
- if (_rx_subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
- lo_offset = get_rx_rate()*2.0;
- }
- return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */);
+ return tune_rx_subdev_and_ddc(_rx_subdev, _rx_ddc, target_freq);
}
freq_range_t get_rx_freq_range(void){
@@ -201,7 +118,7 @@ public:
}
float get_rx_gain(void){
- return _rx_subdev[SUBDEV_PROP_GAIN].as<gain_t>();
+ return _rx_subdev[SUBDEV_PROP_GAIN].as<float>();
}
gain_range_t get_rx_gain_range(void){
@@ -224,28 +141,21 @@ public:
* TX methods
******************************************************************/
void set_tx_rate(double rate){
- double samp_rate = _tx_duc[std::string("rate")].as<double>();
+ double samp_rate = _tx_duc[std::string("if_rate")].as<double>();
assert_has(get_tx_rates(), rate, "simple device tx rate");
_tx_duc[std::string("interp")] = size_t(samp_rate/rate);
}
double get_tx_rate(void){
- double samp_rate = _tx_duc[std::string("rate")].as<double>();
- size_t interp = _tx_duc[std::string("interp")].as<size_t>();
- return samp_rate/interp;
+ return _tx_duc[std::string("bb_rate")].as<double>();
}
std::vector<double> get_tx_rates(void){
- return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("rate")]);
+ return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("if_rate")]);
}
tune_result_t set_tx_freq(double target_freq){
- double lo_offset = 0.0;
- //if the local oscillator will be in the passband, use an offset
- if (_tx_subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
- lo_offset = get_tx_rate()*2.0;
- }
- return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */);
+ return tune_tx_subdev_and_duc(_tx_subdev, _tx_duc, target_freq);
}
freq_range_t get_tx_freq_range(void){
@@ -257,7 +167,7 @@ public:
}
float get_tx_gain(void){
- return _tx_subdev[SUBDEV_PROP_GAIN].as<gain_t>();
+ return _tx_subdev[SUBDEV_PROP_GAIN].as<float>();
}
gain_range_t get_tx_gain_range(void){
@@ -289,5 +199,5 @@ private:
* The Make Function
**********************************************************************/
simple_device::sptr simple_device::make(const std::string &args){
- return sptr(new simple_device_impl(args_to_device_addr(args)));
+ return sptr(new simple_device_impl(device_addr_t::from_args_str(args)));
}
diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp
deleted file mode 100644
index 210010394..000000000
--- a/host/lib/time_spec.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright 2010 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 <uhd/time_spec.hpp>
-
-using namespace uhd;
-
-time_spec_t::time_spec_t(void){
- secs = ~0;
- ticks = ~0;
-}
-
-time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){
- secs = new_secs;
- ticks = new_ticks;
-}
-
-static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
-static double time_tick_rate = double(boost::posix_time::time_duration::ticks_per_second());
-
-time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){
- boost::posix_time::time_duration td = time - epoch;
- secs = boost::uint32_t(td.total_seconds());
- double time_ticks_per_device_ticks = time_tick_rate/tick_rate;
- ticks = boost::uint32_t(td.fractional_seconds()/time_ticks_per_device_ticks);
-}
diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py
new file mode 100755
index 000000000..918de3ad7
--- /dev/null
+++ b/host/lib/transport/gen_vrt.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 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/>.
+#
+
+"""
+The vrt packer/unpacker code generator:
+
+This script will generate the pack and unpack routines that convert
+metatdata into vrt headers and vrt headers into metadata.
+
+The generated code infers jump tables to speed-up the parsing time.
+"""
+
+TMPL_TEXT = """
+#import time
+
+########################################################################
+## setup predicates
+########################################################################
+#set $sid_p = 0b00001
+#set $cid_p = 0b00010
+#set $tsi_p = 0b00100
+#set $tsf_p = 0b01000
+#set $tlr_p = 0b10000
+
+/***********************************************************************
+ * This file was generated by $file on $time.strftime("%c")
+ **********************************************************************/
+
+\#include <uhd/transport/vrt.hpp>
+\#include <boost/asio.hpp> //endianness conversion
+\#include <stdexcept>
+
+using namespace uhd;
+using namespace uhd::transport;
+
+void vrt::pack(
+ const tx_metadata_t &metadata, //input
+ boost::uint32_t *header_buff, //output
+ size_t &num_header_words32, //output
+ size_t num_payload_words32, //input
+ size_t &num_packet_words32, //output
+ size_t packet_count //input
+){
+ boost::uint32_t vrt_hdr_flags;
+
+ boost::uint8_t pred = 0;
+ if (metadata.has_stream_id) pred |= $hex($sid_p);
+ if (metadata.has_time_spec) pred |= $hex($tsi_p | $tsf_p);
+
+ switch(pred){
+ #for $pred in range(2**5)
+ case $pred:
+ #set $num_header_words = 1
+ #set $flags = 0
+ ########## Stream ID ##########
+ #if $pred & $sid_p
+ header_buff[$num_header_words] = htonl(metadata.stream_id);
+ #set $num_header_words += 1
+ #set $flags |= (0x1 << 28);
+ #end if
+ ########## Class ID ##########
+ #if $pred & $cid_p
+ header_buff[$num_header_words] = htonl(0);
+ #set $num_header_words += 1
+ header_buff[$num_header_words] = htonl(0);
+ #set $num_header_words += 1
+ #set $flags |= (0x1 << 27);
+ #end if
+ ########## Integer Time ##########
+ #if $pred & $tsi_p
+ header_buff[$num_header_words] = htonl(metadata.time_spec.secs);
+ #set $num_header_words += 1
+ #set $flags |= (0x3 << 22);
+ #end if
+ ########## Fractional Time ##########
+ #if $pred & $tsf_p
+ header_buff[$num_header_words] = htonl(0);
+ #set $num_header_words += 1
+ header_buff[$num_header_words] = htonl(metadata.time_spec.ticks);
+ #set $num_header_words += 1
+ #set $flags |= (0x1 << 20);
+ #end if
+ ########## Trailer ##########
+ #if $pred & $tlr_p
+ #set $flags |= (0x1 << 26);
+ #set $num_trailer_words = 1;
+ #else
+ #set $num_trailer_words = 0;
+ #end if
+ ########## Variables ##########
+ num_header_words32 = $num_header_words;
+ num_packet_words32 = $($num_header_words + $num_trailer_words) + num_payload_words32;
+ vrt_hdr_flags = $hex($flags);
+ break;
+ #end for
+ }
+
+ //set the burst flags
+ if (metadata.start_of_burst) vrt_hdr_flags |= $hex(0x1 << 25);
+ if (metadata.end_of_burst) vrt_hdr_flags |= $hex(0x1 << 24);
+
+ //fill in complete header word
+ header_buff[0] = htonl(vrt_hdr_flags |
+ ((packet_count & 0xf) << 16) |
+ (num_packet_words32 & 0xffff)
+ );
+}
+
+void vrt::unpack(
+ rx_metadata_t &metadata, //output
+ const boost::uint32_t *header_buff, //input
+ size_t &num_header_words32, //output
+ size_t &num_payload_words32, //output
+ size_t num_packet_words32, //input
+ size_t &packet_count //output
+){
+ //clear the metadata
+ metadata = rx_metadata_t();
+
+ //extract vrt header
+ boost::uint32_t vrt_hdr_word = ntohl(header_buff[0]);
+ size_t packet_words32 = vrt_hdr_word & 0xffff;
+ packet_count = (vrt_hdr_word >> 16) & 0xf;
+
+ //failure cases
+ if (packet_words32 == 0 or num_packet_words32 < packet_words32)
+ throw std::runtime_error("bad vrt header or packet fragment");
+ if (vrt_hdr_word & (0x7 << 29))
+ throw std::runtime_error("unsupported vrt packet type");
+
+ boost::uint8_t pred = 0;
+ if(vrt_hdr_word & $hex(0x1 << 28)) pred |= $hex($sid_p);
+ if(vrt_hdr_word & $hex(0x1 << 27)) pred |= $hex($cid_p);
+ if(vrt_hdr_word & $hex(0x3 << 22)) pred |= $hex($tsi_p);
+ if(vrt_hdr_word & $hex(0x3 << 20)) pred |= $hex($tsf_p);
+ if(vrt_hdr_word & $hex(0x1 << 26)) pred |= $hex($tlr_p);
+
+ switch(pred){
+ #for $pred in range(2**5)
+ case $pred:
+ #set $set_has_time_spec = False
+ #set $num_header_words = 1
+ ########## Stream ID ##########
+ #if $pred & $sid_p
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[$num_header_words]);
+ #set $num_header_words += 1
+ #end if
+ ########## Class ID ##########
+ #if $pred & $cid_p
+ #set $num_header_words += 1
+ #set $num_header_words += 1
+ #end if
+ ########## Integer Time ##########
+ #if $pred & $tsi_p
+ metadata.has_time_spec = true;
+ #set $set_has_time_spec = True
+ metadata.time_spec.secs = ntohl(header_buff[$num_header_words]);
+ #set $num_header_words += 1
+ #end if
+ ########## Fractional Time ##########
+ #if $pred & $tsf_p
+ #if not $set_has_time_spec
+ metadata.has_time_spec = true;
+ #set $set_has_time_spec = True
+ #end if
+ #set $num_header_words += 1
+ metadata.time_spec.ticks = ntohl(header_buff[$num_header_words]);
+ #set $num_header_words += 1
+ #end if
+ ########## Trailer ##########
+ #if $pred & $tlr_p
+ #set $num_trailer_words = 1;
+ #else
+ #set $num_trailer_words = 0;
+ #end if
+ ########## Variables ##########
+ num_header_words32 = $num_header_words;
+ num_payload_words32 = packet_words32 - $($num_header_words + $num_trailer_words);
+ break;
+ #end for
+ }
+}
+"""
+
+from Cheetah import Template
+def parse_str(_tmpl_text, **kwargs): return str(Template.Template(_tmpl_text, kwargs))
+
+if __name__ == '__main__':
+ from Cheetah import Template
+ print parse_str(TMPL_TEXT, file=__file__)
diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp
new file mode 100644
index 000000000..5c8c8a176
--- /dev/null
+++ b/host/lib/transport/if_addrs.cpp
@@ -0,0 +1,109 @@
+//
+// Copyright 2010 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 <uhd/transport/if_addrs.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/cstdint.hpp>
+#include <iostream>
+
+uhd::transport::if_addrs_t::if_addrs_t(void){
+ /* NOP */
+}
+
+/***********************************************************************
+ * Interface address discovery through ifaddrs api
+ **********************************************************************/
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+
+static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){
+ return boost::asio::ip::address_v4(ntohl(
+ reinterpret_cast<sockaddr_in*>(addr)->sin_addr.s_addr
+ ));
+}
+
+std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
+ std::vector<if_addrs_t> if_addrs;
+ struct ifaddrs *ifap;
+ if (getifaddrs(&ifap) == 0){
+ for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next){
+ //ensure that the entries are valid
+ if (iter->ifa_addr->sa_family != AF_INET) continue;
+ if (iter->ifa_netmask->sa_family != AF_INET) continue;
+ if (iter->ifa_broadaddr->sa_family != AF_INET) continue;
+
+ //append a new set of interface addresses
+ if_addrs_t if_addr;
+ if_addr.inet = sockaddr_to_ip_addr(iter->ifa_addr).to_string();
+ if_addr.mask = sockaddr_to_ip_addr(iter->ifa_netmask).to_string();
+ if_addr.bcast = sockaddr_to_ip_addr(iter->ifa_broadaddr).to_string();
+ if_addrs.push_back(if_addr);
+ }
+ freeifaddrs(ifap);
+ }
+ return if_addrs;
+}
+
+/***********************************************************************
+ * Interface address discovery through windows api (TODO)
+ **********************************************************************/
+#elif HAVE_WINSOCK2_H
+#include <winsock2.h>
+
+std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
+ std::vector<if_addrs_t> if_addrs;
+ SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
+ if (sd == SOCKET_ERROR) {
+ std::cerr << "Failed to get a socket. Error " << WSAGetLastError() <<
+ std::endl; return if_addrs;
+ }
+
+ INTERFACE_INFO InterfaceList[20];
+ unsigned long nBytesReturned;
+ if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
+ sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) {
+ std::cerr << "Failed calling WSAIoctl: error " << WSAGetLastError() <<
+ std::endl;
+ return if_addrs;
+ }
+
+ int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
+ for (int i = 0; i < nNumInterfaces; ++i) {
+ boost::uint32_t iiAddress = ntohl(reinterpret_cast<sockaddr_in&>(InterfaceList[i].iiAddress).sin_addr.s_addr);
+ boost::uint32_t iiNetmask = ntohl(reinterpret_cast<sockaddr_in&>(InterfaceList[i].iiNetmask).sin_addr.s_addr);
+ boost::uint32_t iiBroadcastAddress = (iiAddress & iiNetmask) | ~iiNetmask;
+
+ if_addrs_t if_addr;
+ if_addr.inet = boost::asio::ip::address_v4(iiAddress).to_string();
+ if_addr.mask = boost::asio::ip::address_v4(iiNetmask).to_string();
+ if_addr.bcast = boost::asio::ip::address_v4(iiBroadcastAddress).to_string();
+ if_addrs.push_back(if_addr);
+ }
+
+ return if_addrs;
+}
+
+/***********************************************************************
+ * Interface address discovery not included
+ **********************************************************************/
+#else /* HAVE_IFADDRS_H */
+
+std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
+ return std::vector<if_addrs_t>();
+}
+
+#endif /* HAVE_IFADDRS_H */
diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp
index 3c8ecb70d..f339127ad 100644
--- a/host/lib/transport/udp_simple.cpp
+++ b/host/lib/transport/udp_simple.cpp
@@ -16,6 +16,7 @@
//
#include <uhd/transport/udp_simple.hpp>
+#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index 219ae8720..1fc8ce14a 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -17,6 +17,7 @@
#include <uhd/transport/udp_zero_copy.hpp>
#include <boost/cstdint.hpp>
+#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
@@ -115,7 +116,7 @@ smart_buffer::sptr udp_zero_copy_impl::recv(void){
//implement timeout through polling and sleeping
boost::asio::deadline_timer timer(_socket->get_io_service());
- timer.expires_from_now(boost::posix_time::milliseconds(50));
+ timer.expires_from_now(boost::posix_time::milliseconds(100));
while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp
index a06b5bf21..bebca5db9 100644
--- a/host/lib/transport/vrt.cpp
+++ b/host/lib/transport/vrt.cpp
@@ -1,19 +1,9 @@
-//
-// Copyright 2010 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/>.
-//
+
+
+
+/***********************************************************************
+ * This file was generated by ./gen_vrt.py on Fri Mar 26 15:33:00 2010
+ **********************************************************************/
#include <uhd/transport/vrt.hpp>
#include <boost/asio.hpp> //endianness conversion
@@ -30,26 +20,274 @@ void vrt::pack(
size_t &num_packet_words32, //output
size_t packet_count //input
){
- boost::uint32_t vrt_hdr_flags = 0;
- num_header_words32 = 1;
+ boost::uint32_t vrt_hdr_flags;
- //load the vrt header and flags
- if(metadata.has_stream_id){
- vrt_hdr_flags |= (0x1 << 28); //IF Data packet with Stream Identifier
- header_buff[num_header_words32++] = htonl(metadata.stream_id);
- }
+ boost::uint8_t pred = 0;
+ if (metadata.has_stream_id) pred |= 0x1;
+ if (metadata.has_time_spec) pred |= 0xc;
- if(metadata.has_time_spec){
- vrt_hdr_flags |= (0x3 << 22) | (0x1 << 20); //TSI: Other, TSF: Sample Count Timestamp
- header_buff[num_header_words32++] = htonl(metadata.time_spec.secs);
- header_buff[num_header_words32++] = htonl(metadata.time_spec.ticks);
- header_buff[num_header_words32++] = 0; //unused part of fractional seconds
+ switch(pred){
+ case 0:
+ num_header_words32 = 1;
+ num_packet_words32 = 1 + num_payload_words32;
+ vrt_hdr_flags = 0x0;
+ break;
+ case 1:
+ header_buff[1] = htonl(metadata.stream_id);
+ num_header_words32 = 2;
+ num_packet_words32 = 2 + num_payload_words32;
+ vrt_hdr_flags = 0x10000000;
+ break;
+ case 2:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ num_header_words32 = 3;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x8000000;
+ break;
+ case 3:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x18000000;
+ break;
+ case 4:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 2;
+ num_packet_words32 = 2 + num_payload_words32;
+ vrt_hdr_flags = 0xc00000;
+ break;
+ case 5:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 3;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x10c00000;
+ break;
+ case 6:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x8c00000;
+ break;
+ case 7:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 5;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x18c00000;
+ break;
+ case 8:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 3;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x100000;
+ break;
+ case 9:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x10100000;
+ break;
+ case 10:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x8100000;
+ break;
+ case 11:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x18100000;
+ break;
+ case 12:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0xd00000;
+ break;
+ case 13:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x10d00000;
+ break;
+ case 14:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x8d00000;
+ break;
+ case 15:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ header_buff[5] = htonl(0);
+ header_buff[6] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 7;
+ num_packet_words32 = 7 + num_payload_words32;
+ vrt_hdr_flags = 0x18d00000;
+ break;
+ case 16:
+ num_header_words32 = 1;
+ num_packet_words32 = 2 + num_payload_words32;
+ vrt_hdr_flags = 0x4000000;
+ break;
+ case 17:
+ header_buff[1] = htonl(metadata.stream_id);
+ num_header_words32 = 2;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x14000000;
+ break;
+ case 18:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ num_header_words32 = 3;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0xc000000;
+ break;
+ case 19:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x1c000000;
+ break;
+ case 20:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 2;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x4c00000;
+ break;
+ case 21:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 3;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x14c00000;
+ break;
+ case 22:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0xcc00000;
+ break;
+ case 23:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 5;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x1cc00000;
+ break;
+ case 24:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 3;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x4100000;
+ break;
+ case 25:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x14100000;
+ break;
+ case 26:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0xc100000;
+ break;
+ case 27:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 7 + num_payload_words32;
+ vrt_hdr_flags = 0x1c100000;
+ break;
+ case 28:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x4d00000;
+ break;
+ case 29:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x14d00000;
+ break;
+ case 30:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 7 + num_payload_words32;
+ vrt_hdr_flags = 0xcd00000;
+ break;
+ case 31:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ header_buff[5] = htonl(0);
+ header_buff[6] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 7;
+ num_packet_words32 = 8 + num_payload_words32;
+ vrt_hdr_flags = 0x1cd00000;
+ break;
}
- vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0;
- vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0;
-
- num_packet_words32 = num_header_words32 + num_payload_words32;
+ //set the burst flags
+ if (metadata.start_of_burst) vrt_hdr_flags |= 0x2000000;
+ if (metadata.end_of_burst) vrt_hdr_flags |= 0x1000000;
//fill in complete header word
header_buff[0] = htonl(vrt_hdr_flags |
@@ -80,30 +318,230 @@ void vrt::unpack(
if (vrt_hdr_word & (0x7 << 29))
throw std::runtime_error("unsupported vrt packet type");
- //parse the header flags
- num_header_words32 = 1;
-
- if (vrt_hdr_word & (0x1 << 28)){ //stream id
- metadata.has_stream_id = true;
- metadata.stream_id = ntohl(header_buff[num_header_words32++]);
- }
-
- if (vrt_hdr_word & (0x1 << 27)){ //class id (we dont use)
- num_header_words32 += 2;
- }
-
- if (vrt_hdr_word & (0x3 << 22)){ //integer time
- metadata.has_time_spec = true;
- metadata.time_spec.secs = ntohl(header_buff[num_header_words32++]);
- }
+ boost::uint8_t pred = 0;
+ if(vrt_hdr_word & 0x10000000) pred |= 0x1;
+ if(vrt_hdr_word & 0x8000000) pred |= 0x2;
+ if(vrt_hdr_word & 0xc00000) pred |= 0x4;
+ if(vrt_hdr_word & 0x300000) pred |= 0x8;
+ if(vrt_hdr_word & 0x4000000) pred |= 0x10;
- if (vrt_hdr_word & (0x3 << 20)){ //fractional time
- metadata.has_time_spec = true;
- metadata.time_spec.ticks = ntohl(header_buff[num_header_words32++]);
- num_header_words32++; //unused part of fractional seconds
+ switch(pred){
+ case 0:
+ num_header_words32 = 1;
+ num_payload_words32 = packet_words32 - 1;
+ break;
+ case 1:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 2;
+ break;
+ case 2:
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 3:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 4:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 2;
+ break;
+ case 5:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 6:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 7:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 8:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 9:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 10:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 11:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 12:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 13:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 14:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 15:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ metadata.time_spec.ticks = ntohl(header_buff[6]);
+ num_header_words32 = 7;
+ num_payload_words32 = packet_words32 - 7;
+ break;
+ case 16:
+ num_header_words32 = 1;
+ num_payload_words32 = packet_words32 - 2;
+ break;
+ case 17:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 18:
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 19:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 20:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 21:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 22:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 23:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 24:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 25:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 26:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 27:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 7;
+ break;
+ case 28:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 29:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 30:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 7;
+ break;
+ case 31:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ metadata.time_spec.ticks = ntohl(header_buff[6]);
+ num_header_words32 = 7;
+ num_payload_words32 = packet_words32 - 8;
+ break;
}
-
- size_t num_trailer_words32 = (vrt_hdr_word & (0x1 << 26))? 1 : 0;
-
- num_payload_words32 = packet_words32 - num_header_words32 - num_trailer_words32;
}
+
diff --git a/host/lib/tune_helper.cpp b/host/lib/tune_helper.cpp
new file mode 100644
index 000000000..1e5c4cd0d
--- /dev/null
+++ b/host/lib/tune_helper.cpp
@@ -0,0 +1,125 @@
+//
+// Copyright 2010 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 <uhd/utils/tune_helper.hpp>
+#include <uhd/utils/algorithm.hpp>
+#include <uhd/props.hpp>
+#include <cmath>
+
+using namespace uhd;
+
+/***********************************************************************
+ * Tune Helper Function
+ **********************************************************************/
+static tune_result_t tune_xx_subdev_and_dxc(
+ bool is_tx,
+ wax::obj subdev, wax::obj dxc,
+ double target_freq, double lo_offset
+){
+ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
+ bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
+ bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>();
+ wax::obj dxc_freq_proxy = dxc[std::string("freq")];
+ double dxc_sample_rate = dxc[std::string("if_rate")].as<double>();
+
+ // Ask the d'board to tune as closely as it can to target_freq+lo_offset
+ double target_inter_freq = target_freq + lo_offset;
+ subdev_freq_proxy = target_inter_freq;
+ double actual_inter_freq = subdev_freq_proxy.as<double>();
+
+ // Calculate the DDC setting that will downconvert the baseband from the
+ // daughterboard to our target frequency.
+ double delta_freq = target_freq - actual_inter_freq;
+ double delta_sign = std::signum(delta_freq);
+ delta_freq *= delta_sign;
+ delta_freq = std::fmod(delta_freq, dxc_sample_rate);
+ bool inverted = delta_freq > dxc_sample_rate/2.0;
+ double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq);
+ target_dxc_freq *= delta_sign;
+
+ // If the spectrum is inverted, and the daughterboard doesn't do
+ // quadrature downconversion, we can fix the inversion by flipping the
+ // sign of the dxc_freq... (This only happens using the basic_rx board)
+ if (subdev_spectrum_inverted){
+ inverted = not inverted;
+ }
+ if (inverted and not subdev_quadrature){
+ target_dxc_freq *= -1.0;
+ inverted = not inverted;
+ }
+ // down conversion versus up conversion, fight!
+ // your mother is ugly and your going down...
+ target_dxc_freq *= (is_tx)? -1.0 : +1.0;
+
+ dxc_freq_proxy = target_dxc_freq;
+ double actual_dxc_freq = dxc_freq_proxy.as<double>();
+
+ //return some kind of tune result tuple/struct
+ tune_result_t tune_result;
+ tune_result.target_inter_freq = target_inter_freq;
+ tune_result.actual_inter_freq = actual_inter_freq;
+ tune_result.target_dxc_freq = target_dxc_freq;
+ tune_result.actual_dxc_freq = actual_dxc_freq;
+ tune_result.spectrum_inverted = inverted;
+ return tune_result;
+}
+
+/***********************************************************************
+ * RX Tune
+ **********************************************************************/
+tune_result_t uhd::tune_rx_subdev_and_ddc(
+ wax::obj subdev, wax::obj ddc,
+ double target_freq, double lo_offset
+){
+ bool is_tx = false;
+ return tune_xx_subdev_and_dxc(is_tx, subdev, ddc, target_freq, lo_offset);
+}
+
+tune_result_t uhd::tune_rx_subdev_and_ddc(
+ wax::obj subdev, wax::obj ddc,
+ double target_freq
+){
+ double lo_offset = 0.0;
+ //if the local oscillator will be in the passband, use an offset
+ if (subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
+ lo_offset = 2.0*ddc[std::string("bb_rate")].as<double>();
+ }
+ return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset);
+}
+
+/***********************************************************************
+ * TX Tune
+ **********************************************************************/
+tune_result_t uhd::tune_tx_subdev_and_duc(
+ wax::obj subdev, wax::obj duc,
+ double target_freq, double lo_offset
+){
+ bool is_tx = true;
+ return tune_xx_subdev_and_dxc(is_tx, subdev, duc, target_freq, lo_offset);
+}
+
+tune_result_t uhd::tune_tx_subdev_and_duc(
+ wax::obj subdev, wax::obj duc,
+ double target_freq
+){
+ double lo_offset = 0.0;
+ //if the local oscillator will be in the passband, use an offset
+ if (subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
+ lo_offset = 2.0*duc[std::string("bb_rate")].as<double>();
+ }
+ return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset);
+}
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index f8a9a9b36..bf9f8b895 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -15,12 +15,27 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/types.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/types/tune_result.hpp>
+#include <uhd/types/clock_config.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/metadata.hpp>
+#include <uhd/types/time_spec.hpp>
+#include <uhd/types/device_addr.hpp>
+#include <uhd/types/mac_addr.hpp>
+#include <uhd/types/otw_type.hpp>
+#include <uhd/types/io_type.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <boost/cstdint.hpp>
+#include <stdexcept>
+#include <complex>
using namespace uhd;
/***********************************************************************
- * gain range
+ * ranges
**********************************************************************/
gain_range_t::gain_range_t(float min_, float max_, float step_){
min = min_;
@@ -28,9 +43,6 @@ gain_range_t::gain_range_t(float min_, float max_, float step_){
step = step_;
}
-/***********************************************************************
- * freq range
- **********************************************************************/
freq_range_t::freq_range_t(double min_, double max_){
min = min_;
max = max_;
@@ -51,7 +63,185 @@ tune_result_t::tune_result_t(void){
* clock config
**********************************************************************/
clock_config_t::clock_config_t(void){
- ref_source = ""; //not a valid setting
- pps_source = ""; //not a valid setting
- pps_polarity = POLARITY_NEG;
+ ref_source = REF_INT,
+ pps_source = PPS_INT,
+ pps_polarity = PPS_NEG;
+}
+
+/***********************************************************************
+ * stream command
+ **********************************************************************/
+stream_cmd_t::stream_cmd_t(void){
+ stream_now = true;
+ continuous = false;
+ num_samps = 0;
+}
+
+/***********************************************************************
+ * metadata
+ **********************************************************************/
+rx_metadata_t::rx_metadata_t(void){
+ stream_id = 0;
+ has_stream_id = false;
+ time_spec = time_spec_t();
+ has_time_spec = false;
+ is_fragment = false;
+}
+
+tx_metadata_t::tx_metadata_t(void){
+ stream_id = 0;
+ has_stream_id = false;
+ time_spec = time_spec_t();
+ has_time_spec = false;
+ start_of_burst = false;
+ end_of_burst = false;
+}
+
+/***********************************************************************
+ * time spec
+ **********************************************************************/
+time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){
+ secs = new_secs;
+ ticks = new_ticks;
+}
+
+static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
+static double time_tick_rate = double(boost::posix_time::time_duration::ticks_per_second());
+
+time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){
+ boost::posix_time::time_duration td = time - epoch;
+ secs = boost::uint32_t(td.total_seconds());
+ double time_ticks_per_device_ticks = time_tick_rate/tick_rate;
+ ticks = boost::uint32_t(td.fractional_seconds()/time_ticks_per_device_ticks);
+}
+
+/***********************************************************************
+ * device addr
+ **********************************************************************/
+std::string device_addr_t::to_string(void) const{
+ const device_addr_t &device_addr = *this;
+ std::stringstream ss;
+ BOOST_FOREACH(std::string key, device_addr.get_keys()){
+ ss << boost::format("%s: %s") % key % device_addr[key] << std::endl;
+ }
+ return ss.str();
+}
+
+static const std::string arg_delim = ";";
+static const std::string pair_delim = "=";
+
+static std::string trim(const std::string &in){
+ return boost::algorithm::trim_copy(in);
+}
+
+std::string device_addr_t::to_args_str(void) const{
+ std::string args_str;
+ const device_addr_t &device_addr = *this;
+ BOOST_FOREACH(const std::string &key, device_addr.get_keys()){
+ args_str += key + pair_delim + device_addr[key] + arg_delim;
+ }
+ return args_str;
+}
+
+device_addr_t device_addr_t::from_args_str(const std::string &args_str){
+ device_addr_t addr;
+
+ //split the args at the semi-colons
+ std::vector<std::string> pairs;
+ boost::split(pairs, args_str, boost::is_any_of(arg_delim));
+ BOOST_FOREACH(const std::string &pair, pairs){
+ if (trim(pair) == "") continue;
+
+ //split the key value pairs at the equals
+ std::vector<std::string> key_val;
+ boost::split(key_val, pair, boost::is_any_of(pair_delim));
+ if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args_str);
+ addr[trim(key_val[0])] = trim(key_val[1]);
+ }
+
+ return addr;
+}
+
+/***********************************************************************
+ * mac addr
+ **********************************************************************/
+mac_addr_t::mac_addr_t(const boost::uint8_t *bytes){
+ std::copy(bytes, bytes+hlen, _bytes);
+}
+
+mac_addr_t mac_addr_t::from_bytes(const boost::uint8_t *bytes){
+ return mac_addr_t(bytes);
+}
+
+mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
+
+ boost::uint8_t p[hlen] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB
+
+ try{
+ //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx
+ //the IAB above will fill in for the shorter pattern
+ if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17)
+ throw std::runtime_error("expected exactly 5 or 17 characters");
+
+ //split the mac addr hex string at the colons
+ std::vector<std::string> hex_strs;
+ boost::split(hex_strs, mac_addr_str, boost::is_any_of(":"));
+ for (size_t i = 0; i < hex_strs.size(); i++){
+ int hex_num;
+ std::istringstream iss(hex_strs[i]);
+ iss >> std::hex >> hex_num;
+ p[i] = boost::uint8_t(hex_num);
+ }
+
+ }
+ catch(std::exception const& e){
+ throw std::runtime_error(str(
+ boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what()
+ ));
+ }
+
+ return from_bytes(p);
+}
+
+const boost::uint8_t *mac_addr_t::to_bytes(void) const{
+ return _bytes;
+}
+
+std::string mac_addr_t::to_string(void) const{
+ return str(
+ boost::format("%02x:%02x:%02x:%02x:%02x:%02x")
+ % int(to_bytes()[0]) % int(to_bytes()[1]) % int(to_bytes()[2])
+ % int(to_bytes()[3]) % int(to_bytes()[4]) % int(to_bytes()[5])
+ );
+}
+
+/***********************************************************************
+ * otw type
+ **********************************************************************/
+otw_type_t::otw_type_t(void){
+ width = 0;
+ shift = 0;
+ byteorder = BO_NATIVE;
+}
+
+/***********************************************************************
+ * io type
+ **********************************************************************/
+static size_t tid_to_size(io_type_t::tid_t tid){
+ switch(tid){
+ case io_type_t::COMPLEX_FLOAT32: return sizeof(std::complex<float>);
+ case io_type_t::COMPLEX_INT16: return sizeof(std::complex<boost::int16_t>);
+ case io_type_t::COMPLEX_INT8: return sizeof(std::complex<boost::int8_t>);
+ default: throw std::runtime_error("unknown io type tid");
+ }
+}
+
+io_type_t::io_type_t(tid_t tid)
+: size(tid_to_size(tid)), tid(tid){
+ /* NOP */
+}
+
+io_type_t::io_type_t(size_t size)
+: size(size), tid(CUSTOM_TYPE){
+ /* NOP */
}
diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp
index 82485ae6a..2f29c8e0c 100644
--- a/host/lib/usrp/dboard/basic.cpp
+++ b/host/lib/usrp/dboard/basic.cpp
@@ -15,9 +15,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
#include <uhd/props.hpp>
-#include <uhd/types.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <boost/assign/list_of.hpp>
@@ -33,26 +34,26 @@ using namespace boost::assign;
**********************************************************************/
class basic_rx : public rx_dboard_base{
public:
- basic_rx(ctor_args_t const& args, freq_t max_freq);
+ basic_rx(ctor_args_t const& args, double max_freq);
~basic_rx(void);
void rx_get(const wax::obj &key, wax::obj &val);
void rx_set(const wax::obj &key, const wax::obj &val);
private:
- freq_t _max_freq;
+ double _max_freq;
};
class basic_tx : public tx_dboard_base{
public:
- basic_tx(ctor_args_t const& args, freq_t max_freq);
+ basic_tx(ctor_args_t const& args, double max_freq);
~basic_tx(void);
void tx_get(const wax::obj &key, wax::obj &val);
void tx_set(const wax::obj &key, const wax::obj &val);
private:
- freq_t _max_freq;
+ double _max_freq;
};
/***********************************************************************
@@ -74,17 +75,17 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){
return dboard_base::sptr(new basic_tx(args, 32e6));
}
-STATIC_BLOCK(reg_dboards){
- dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX", list_of(""));
+UHD_STATIC_BLOCK(reg_dboards){
+ dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX");
dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("ab")("a")("b"));
- dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX", list_of(""));
+ dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX");
dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("ab")("a")("b"));
}
/***********************************************************************
* Basic and LF RX dboard
**********************************************************************/
-basic_rx::basic_rx(ctor_args_t const& args, freq_t max_freq) : rx_dboard_base(args){
+basic_rx::basic_rx(ctor_args_t const& args, double max_freq) : rx_dboard_base(args){
_max_freq = max_freq;
// set the gpios to safe values (all inputs)
get_interface()->set_gpio_ddr(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff);
@@ -112,7 +113,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = gain_t(0);
+ val = float(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -124,7 +125,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_FREQ:
- val = freq_t(0);
+ val = double(0);
return;
case SUBDEV_PROP_FREQ_RANGE:
@@ -163,7 +164,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- ASSERT_THROW(val.as<gain_t>() == gain_t(0));
+ ASSERT_THROW(val.as<float>() == float(0));
return;
case SUBDEV_PROP_ANTENNA:
@@ -195,7 +196,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
/***********************************************************************
* Basic and LF TX dboard
**********************************************************************/
-basic_tx::basic_tx(ctor_args_t const& args, freq_t max_freq) : tx_dboard_base(args){
+basic_tx::basic_tx(ctor_args_t const& args, double max_freq) : tx_dboard_base(args){
_max_freq = max_freq;
// set the gpios to safe values (all inputs)
get_interface()->set_gpio_ddr(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff);
@@ -220,7 +221,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = gain_t(0);
+ val = float(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -232,7 +233,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_FREQ:
- val = freq_t(0);
+ val = double(0);
return;
case SUBDEV_PROP_FREQ_RANGE:
@@ -271,7 +272,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- ASSERT_THROW(val.as<gain_t>() == gain_t(0));
+ ASSERT_THROW(val.as<float>() == float(0));
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp
index 6dd41cfd8..09d3bbfd4 100644
--- a/host/lib/usrp/dboard_base.cpp
+++ b/host/lib/usrp/dboard_base.cpp
@@ -52,15 +52,15 @@ dboard_id_t dboard_base::get_tx_id(void){
* xcvr dboard dboard_base class
**********************************************************************/
xcvr_dboard_base::xcvr_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_rx_id() == ID_NONE){
+ if (get_rx_id() == dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create xcvr board when the rx id is \"%s\""
- ) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(dboard_id::NONE)));
}
- if (get_tx_id() == ID_NONE){
+ if (get_tx_id() == dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create xcvr board when the tx id is \"%s\""
- ) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(dboard_id::NONE)));
}
}
@@ -72,11 +72,11 @@ xcvr_dboard_base::~xcvr_dboard_base(void){
* rx dboard dboard_base class
**********************************************************************/
rx_dboard_base::rx_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_tx_id() != ID_NONE){
+ if (get_tx_id() != dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create rx board when the tx id is \"%s\""
" -> expected a tx id of \"%s\""
- ) % dboard_id::to_string(get_tx_id()) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(get_tx_id()) % dboard_id::to_string(dboard_id::NONE)));
}
}
@@ -96,11 +96,11 @@ void rx_dboard_base::tx_set(const wax::obj &, const wax::obj &){
* tx dboard dboard_base class
**********************************************************************/
tx_dboard_base::tx_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_rx_id() != ID_NONE){
+ if (get_rx_id() != dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create tx board when the rx id is \"%s\""
" -> expected a rx id of \"%s\""
- ) % dboard_id::to_string(get_rx_id()) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(get_rx_id()) % dboard_id::to_string(dboard_id::NONE)));
}
}
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index 6ca15e98c..424626023 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -16,9 +16,10 @@
//
#include <uhd/usrp/dboard_manager.hpp>
-#include <uhd/gain_handler.hpp>
-#include <uhd/utils.hpp>
-#include <uhd/dict.hpp>
+#include <uhd/utils/gain_handler.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/dict.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
@@ -35,7 +36,7 @@ typedef boost::tuple<dboard_manager::dboard_ctor_t, std::string, prop_names_t> a
//map a dboard id to a dboard constructor
typedef uhd::dict<dboard_id_t, args_t> id_to_args_map_t;
-STATIC_INSTANCE(id_to_args_map_t, get_id_to_args_map)
+UHD_SINGLETON_FCN(id_to_args_map_t, get_id_to_args_map)
void dboard_manager::register_dboard(
dboard_id_t dboard_id,
@@ -163,12 +164,12 @@ static args_t get_dboard_args(
std::string const& xx_type
){
//special case, its rx and the none id (0xffff)
- if (xx_type == "rx" and dboard_id == ID_NONE){
+ if (xx_type == "rx" and dboard_id == dboard_id::NONE){
return get_dboard_args(0x0001, xx_type);
}
//special case, its tx and the none id (0xffff)
- if (xx_type == "tx" and dboard_id == ID_NONE){
+ if (xx_type == "tx" and dboard_id == dboard_id::NONE){
return get_dboard_args(0x0000, xx_type);
}
@@ -203,7 +204,7 @@ dboard_manager_impl::dboard_manager_impl(
//make xcvr subdevs (make one subdev for both rx and tx dboards)
if (rx_dboard_ctor == tx_dboard_ctor){
ASSERT_THROW(rx_subdevs == tx_subdevs);
- BOOST_FOREACH(std::string subdev, rx_subdevs){
+ BOOST_FOREACH(const std::string &subdev, rx_subdevs){
dboard_base::sptr xcvr_dboard = rx_dboard_ctor(
dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, tx_dboard_id)
);
@@ -221,9 +222,9 @@ dboard_manager_impl::dboard_manager_impl(
//make tx and rx subdevs (separate subdevs for rx and tx dboards)
else{
//make the rx subdevs
- BOOST_FOREACH(std::string subdev, rx_subdevs){
+ BOOST_FOREACH(const std::string &subdev, rx_subdevs){
dboard_base::sptr rx_dboard = rx_dboard_ctor(
- dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, ID_NONE)
+ dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, dboard_id::NONE)
);
//create a rx proxy for this rx board
_rx_dboards[subdev] = subdev_proxy::sptr(
@@ -231,9 +232,9 @@ dboard_manager_impl::dboard_manager_impl(
);
}
//make the tx subdevs
- BOOST_FOREACH(std::string subdev, tx_subdevs){
+ BOOST_FOREACH(const std::string &subdev, tx_subdevs){
dboard_base::sptr tx_dboard = tx_dboard_ctor(
- dboard_base::ctor_args_t(subdev, interface, ID_NONE, tx_dboard_id)
+ dboard_base::ctor_args_t(subdev, interface, dboard_id::NONE, tx_dboard_id)
);
//create a tx proxy for this tx board
_tx_dboards[subdev] = subdev_proxy::sptr(
diff --git a/host/lib/usrp/usrp1e/usrp1e_none.cpp b/host/lib/usrp/usrp1e/usrp1e_none.cpp
index ac0b12a75..94243523d 100644
--- a/host/lib/usrp/usrp1e/usrp1e_none.cpp
+++ b/host/lib/usrp/usrp1e/usrp1e_none.cpp
@@ -25,7 +25,7 @@ using namespace uhd::usrp;
* when the required kernel module headers are not present.
*/
-device_addrs_t usrp1e::discover(const device_addr_t &){
+device_addrs_t usrp1e::find(const device_addr_t &){
return device_addrs_t(); //return empty list
}
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 66e02d469..fd72aeaa4 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -15,7 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/clock_config.hpp>
#include <boost/format.hpp>
#include "usrp2_impl.hpp"
diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp
index d20465147..8fc7864b0 100644
--- a/host/lib/usrp/usrp2/dboard_interface.cpp
+++ b/host/lib/usrp/usrp2/dboard_interface.cpp
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
#include "usrp2_impl.hpp"
using namespace uhd::usrp;
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 34cce0afb..0d43fac0e 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
#include <boost/format.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/math/special_functions/round.hpp>
@@ -35,7 +35,7 @@ template <class T> T log2(T num){
/***********************************************************************
* DDC Helper Methods
**********************************************************************/
-static boost::uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t clock_freq){
+static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq, double clock_freq){
double scale_factor = std::pow(2.0, 32);
//calculate the freq register word
@@ -63,9 +63,8 @@ void usrp2_impl::init_ddc_config(void){
_ddc_freq = 0;
update_ddc_config();
- _ddc_stream_at = time_spec_t();
- _ddc_enabled = false;
- update_ddc_enabled();
+ //initial command that kills streaming (in case if was left on)
+ //issue_ddc_stream_cmd(TODO)
}
void usrp2_impl::update_ddc_config(void){
@@ -86,21 +85,19 @@ void usrp2_impl::update_ddc_config(void){
ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE);
}
-void usrp2_impl::update_ddc_enabled(void){
+void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
//setup the out data
usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO);
- out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0;
- out_data.data.streaming.secs = htonl(_ddc_stream_at.secs);
- out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks);
- out_data.data.streaming.samples = htonl(_max_rx_samples_per_packet);
+ out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO);
+ out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0;
+ out_data.data.stream_cmd.continuous = (stream_cmd.continuous)? 1 : 0;
+ out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs);
+ out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.ticks);
+ out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps);
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
- ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE);
-
- //clear the stream at time spec (it must be set for the next round of enable/disable)
- _ddc_stream_at = time_spec_t();
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE);
}
/***********************************************************************
@@ -116,12 +113,12 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
case DSP_PROP_OTHERS:{
prop_names_t others = boost::assign::list_of
- ("rate")
+ ("if_rate")
+ ("bb_rate")
("decim")
("decims")
("freq")
- ("enabled")
- ("stream_at")
+ ("stream_cmd")
;
val = others;
}
@@ -131,10 +128,14 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
//handle string-based properties specific to this dsp
std::string key_name = key.as<std::string>();
- if (key_name == "rate"){
+ if (key_name == "if_rate"){
val = get_master_clock_freq();
return;
}
+ else if (key_name == "bb_rate"){
+ val = get_master_clock_freq()/_ddc_decim;
+ return;
+ }
else if (key_name == "decim"){
val = _ddc_decim;
return;
@@ -147,10 +148,6 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
val = _ddc_freq;
return;
}
- else if (key_name == "enabled"){
- val = _ddc_enabled;
- return;
- }
throw std::invalid_argument(str(
boost::format("error getting: unknown key with name %s") % key_name
@@ -171,23 +168,15 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){
return;
}
else if (key_name == "freq"){
- freq_t new_freq = val.as<freq_t>();
+ double new_freq = val.as<double>();
ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
_ddc_freq = new_freq; //shadow
update_ddc_config();
return;
}
- else if (key_name == "enabled"){
- bool new_enabled = val.as<bool>();
- _ddc_enabled = new_enabled; //shadow
- update_ddc_enabled();
- return;
- }
- else if (key_name == "stream_at"){
- time_spec_t new_stream_at = val.as<time_spec_t>();
- _ddc_stream_at = new_stream_at; //shadow
- //update_ddc_enabled(); //dont update from here
+ else if (key_name == "stream_cmd"){
+ issue_ddc_stream_cmd(val.as<stream_cmd_t>());
return;
}
@@ -250,7 +239,8 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
case DSP_PROP_OTHERS:{
prop_names_t others = boost::assign::list_of
- ("rate")
+ ("if_rate")
+ ("bb_rate")
("interp")
("interps")
("freq")
@@ -263,10 +253,14 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
//handle string-based properties specific to this dsp
std::string key_name = key.as<std::string>();
- if (key_name == "rate"){
+ if (key_name == "if_rate"){
val = get_master_clock_freq();
return;
}
+ else if (key_name == "bb_rate"){
+ val = get_master_clock_freq()/_duc_interp;
+ return;
+ }
else if (key_name == "interp"){
val = _duc_interp;
return;
@@ -299,7 +293,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){
return;
}
else if (key_name == "freq"){
- freq_t new_freq = val.as<freq_t>();
+ double new_freq = val.as<double>();
ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
_duc_freq = new_freq; //shadow
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 7fcae6fb2..30fee6c32 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -32,6 +32,9 @@ extern "C" {
#define _SINS_
#endif
+//used to differentiate control packets over data port
+#define USRP2_INVALID_VRT_HEADER 0
+
// size of the vrt header and trailer to the host
#define USRP2_HOST_RX_VRT_HEADER_WORDS32 5
#define USRP2_HOST_RX_VRT_TRAILER_WORDS32 1 //FIXME fpga sets wrong header size when no trailer present
@@ -90,8 +93,8 @@ typedef enum{
USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO,
USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE,
- USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO,
- USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE,
+ USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO,
+ USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE,
USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO,
USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE,
@@ -186,12 +189,13 @@ typedef struct{
_SINS_ uint32_t scale_iq;
} ddc_args;
struct {
- _SINS_ uint8_t enabled;
- _SINS_ uint8_t _pad[3];
+ _SINS_ uint8_t now; //stream now?
+ _SINS_ uint8_t continuous; //auto-reload commmands?
+ _SINS_ uint8_t _pad[2];
_SINS_ uint32_t secs;
_SINS_ uint32_t ticks;
- _SINS_ uint32_t samples;
- } streaming;
+ _SINS_ uint32_t num_samps;
+ } stream_cmd;
struct {
_SINS_ uint32_t freq_word;
_SINS_ uint32_t interp;
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index dc8eea243..c87884ebb 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -16,7 +16,6 @@
//
#include <complex>
-#include <algorithm>
#include <boost/format.hpp>
#include "usrp2_impl.hpp"
@@ -42,20 +41,22 @@ void usrp2_impl::io_init(void){
_rx_copy_buff = asio::buffer("", 0);
//send a small data packet so the usrp2 knows the udp source port
- boost::uint32_t zero_data = 0;
- _data_transport->send(asio::buffer(&zero_data, sizeof(zero_data)));
+ //and the maximum number of lines (32 bit words) per packet
+ boost::uint32_t data[2] = {
+ htonl(USRP2_INVALID_VRT_HEADER),
+ htonl(_max_rx_samples_per_packet)
+ };
+ _data_transport->send(asio::buffer(&data, sizeof(data)));
}
-#define unrolled_loop(__i, __len, __inst) {\
+#define unrolled_loop(__inst, __len){ \
size_t __i = 0; \
- while(__i < (__len & ~0x7)){ \
- __inst; __i++; __inst; __i++; \
- __inst; __i++; __inst; __i++; \
- __inst; __i++; __inst; __i++; \
- __inst; __i++; __inst; __i++; \
+ for(; __i < (__len & ~0x3); __i+= 4){ \
+ __inst(__i+0); __inst(__i+1); \
+ __inst(__i+2); __inst(__i+3); \
} \
- while(__i < __len){ \
- __inst; __i++;\
+ for(; __i < __len; __i++){ \
+ __inst(__i); \
} \
}
@@ -71,11 +72,12 @@ static inline void host_floats_to_usrp2_items(
const fc32_t *host_floats,
size_t num_samps
){
- unrolled_loop(i, num_samps,{
- boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float);
- boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float);
- usrp2_items[i] = htonl((real << 16) | (imag << 0));
- });
+ #define host_floats_to_usrp2_items_i(i){ \
+ boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \
+ boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \
+ usrp2_items[i] = htonl((real << 16) | (imag << 0)); \
+ }
+ unrolled_loop(host_floats_to_usrp2_items_i, num_samps);
}
static inline void usrp2_items_to_host_floats(
@@ -83,12 +85,13 @@ static inline void usrp2_items_to_host_floats(
const boost::uint32_t *usrp2_items,
size_t num_samps
){
- unrolled_loop(i, num_samps,{
- boost::uint32_t item = ntohl(usrp2_items[i]);
- boost::int16_t real = boost::uint16_t(item >> 16);
- boost::int16_t imag = boost::uint16_t(item >> 0);
- host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short));
- });
+ #define usrp2_items_to_host_floats_i(i){ \
+ boost::uint32_t item = ntohl(usrp2_items[i]); \
+ boost::int16_t real = boost::uint16_t(item >> 16); \
+ boost::int16_t imag = boost::uint16_t(item >> 0); \
+ host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \
+ }
+ unrolled_loop(usrp2_items_to_host_floats_i, num_samps);
}
static inline void host_items_to_usrp2_items(
@@ -96,11 +99,12 @@ static inline void host_items_to_usrp2_items(
const boost::uint32_t *host_items,
size_t num_samps
){
+ #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i])
if (is_big_endian){
std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t));
}
else{
- unrolled_loop(i, num_samps, usrp2_items[i] = htonl(host_items[i]));
+ unrolled_loop(host_items_to_usrp2_items_i, num_samps);
}
}
@@ -109,11 +113,12 @@ static inline void usrp2_items_to_host_items(
const boost::uint32_t *usrp2_items,
size_t num_samps
){
+ #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i])
if (is_big_endian){
std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t));
}
else{
- unrolled_loop(i, num_samps, host_items[i] = ntohl(usrp2_items[i]));
+ unrolled_loop(usrp2_items_to_host_items_i, num_samps);
}
}
@@ -167,46 +172,43 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){
size_t usrp2_impl::send(
const asio::const_buffer &buff,
const tx_metadata_t &metadata,
- const std::string &type
+ const io_type_t &io_type
){
boost::uint32_t tx_mem[_mtu/sizeof(boost::uint32_t)];
- boost::uint32_t *items = tx_mem + vrt::max_header_words32; //offset for data
- size_t num_samps = _max_tx_samples_per_packet;
-
- //calculate the number of samples to be copied
- //and copy the samples into the send buffer
- if (type == "32fc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps);
- host_floats_to_usrp2_items(items, asio::buffer_cast<const fc32_t*>(buff), num_samps);
- }
- else if (type == "16sc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps);
- host_items_to_usrp2_items(items, asio::buffer_cast<const boost::uint32_t*>(buff), num_samps);
- }
- else{
- throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type));
- }
+ size_t num_samps = std::min(
+ asio::buffer_size(buff)/io_type.size,
+ size_t(_max_tx_samples_per_packet)
+ );
- boost::uint32_t vrt_hdr[vrt::max_header_words32];
size_t num_header_words32, num_packet_words32;
size_t packet_count = _tx_stream_id_to_packet_seq[metadata.stream_id]++;
//pack metadata into a vrt header
vrt::pack(
metadata, //input
- vrt_hdr, //output
+ tx_mem, //output
num_header_words32, //output
num_samps, //input
num_packet_words32, //output
packet_count //input
);
- //copy in the vrt header (yes we left space)
- items -= num_header_words32;
- std::memcpy(items, vrt_hdr, num_header_words32*sizeof(boost::uint32_t));
+ boost::uint32_t *items = tx_mem + num_header_words32; //offset for data
+
+ //copy the samples into the send buffer
+ switch(io_type.tid){
+ case io_type_t::COMPLEX_FLOAT32:
+ host_floats_to_usrp2_items(items, asio::buffer_cast<const fc32_t*>(buff), num_samps);
+ break;
+ case io_type_t::COMPLEX_INT16:
+ host_items_to_usrp2_items(items, asio::buffer_cast<const boost::uint32_t*>(buff), num_samps);
+ break;
+ default:
+ throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%c\"") % io_type.tid));
+ }
//send and return number of samples
- _data_transport->send(asio::buffer(items, num_packet_words32*sizeof(boost::uint32_t)));
+ _data_transport->send(asio::buffer(tx_mem, num_packet_words32*sizeof(boost::uint32_t)));
return num_samps;
}
@@ -216,7 +218,7 @@ size_t usrp2_impl::send(
size_t usrp2_impl::recv(
const asio::mutable_buffer &buff,
rx_metadata_t &metadata,
- const std::string &type
+ const io_type_t &io_type
){
//perform a receive if no rx data is waiting to be copied
if (asio::buffer_size(_rx_copy_buff) == 0){
@@ -232,21 +234,22 @@ size_t usrp2_impl::recv(
//and a pointer into the usrp2 received items memory
size_t bytes_to_copy = asio::buffer_size(_rx_copy_buff);
if (bytes_to_copy == 0) return 0; //nothing to receive
- size_t num_samps = bytes_to_copy/sizeof(boost::uint32_t);
+ size_t num_samps = std::min(
+ asio::buffer_size(buff)/io_type.size,
+ bytes_to_copy/sizeof(boost::uint32_t)
+ );
const boost::uint32_t *items = asio::buffer_cast<const boost::uint32_t*>(_rx_copy_buff);
- //calculate the number of samples to be copied
- //and copy the samples from the recv buffer
- if (type == "32fc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps);
+ //copy the samples from the recv buffer
+ switch(io_type.tid){
+ case io_type_t::COMPLEX_FLOAT32:
usrp2_items_to_host_floats(asio::buffer_cast<fc32_t*>(buff), items, num_samps);
- }
- else if (type == "16sc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps);
+ break;
+ case io_type_t::COMPLEX_INT16:
usrp2_items_to_host_items(asio::buffer_cast<boost::uint32_t*>(buff), items, num_samps);
- }
- else{
- throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type));
+ break;
+ default:
+ throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%c\"") % io_type.tid));
}
//update the rx copy buffer to reflect the bytes copied
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index cbca8eec7..35dfd6287 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -15,7 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/mac_addr.hpp>
#include "usrp2_impl.hpp"
using namespace uhd;
@@ -35,27 +36,10 @@ void usrp2_impl::mboard_init(void){
}
void usrp2_impl::init_clock_config(void){
- //init the ref source clock config
- _ref_source_dict = boost::assign::map_list_of
- ("int", USRP2_REF_SOURCE_INT)
- ("sma", USRP2_REF_SOURCE_SMA)
- ("mimo", USRP2_REF_SOURCE_MIMO)
- ;
- _clock_config.ref_source = "int";
-
- //init the pps source clock config
- _pps_source_dict = boost::assign::map_list_of
- ("sma", USRP2_PPS_SOURCE_SMA)
- ("mimo", USRP2_PPS_SOURCE_MIMO)
- ;
- _clock_config.pps_source = "sma";
-
- //init the pps polarity clock config
- _pps_polarity_dict = boost::assign::map_list_of
- (clock_config_t::POLARITY_POS, USRP2_PPS_POLARITY_POS)
- (clock_config_t::POLARITY_NEG, USRP2_PPS_POLARITY_NEG)
- ;
- _clock_config.pps_polarity = clock_config_t::POLARITY_NEG;
+ //setup the clock configuration settings
+ _clock_config.ref_source = clock_config_t::REF_INT;
+ _clock_config.pps_source = clock_config_t::PPS_SMA;
+ _clock_config.pps_polarity = clock_config_t::PPS_NEG;
//update the clock config (sends a control packet)
update_clock_config();
@@ -65,9 +49,35 @@ void usrp2_impl::update_clock_config(void){
//setup the out data
usrp2_ctrl_data_t out_data;
out_data.id = htonl(USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO);
- out_data.data.clock_config.ref_source = _ref_source_dict [_clock_config.ref_source];
- out_data.data.clock_config.pps_source = _pps_source_dict [_clock_config.pps_source];
- out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_clock_config.pps_polarity];
+
+ //translate ref source enums
+ switch(_clock_config.ref_source){
+ case clock_config_t::REF_INT:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_INT; break;
+ case clock_config_t::REF_SMA:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_SMA; break;
+ case clock_config_t::REF_MIMO:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_MIMO; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration ref source");
+ }
+
+ //translate pps source enums
+ switch(_clock_config.pps_source){
+ case clock_config_t::PPS_SMA:
+ out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_SMA; break;
+ case clock_config_t::PPS_MIMO:
+ out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_MIMO; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration pps source");
+ }
+
+ //translate pps polarity enums
+ switch(_clock_config.pps_polarity){
+ case clock_config_t::PPS_POS:
+ out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_POS; break;
+ case clock_config_t::PPS_NEG:
+ out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_NEG; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration pps polarity");
+ }
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
@@ -106,7 +116,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE);
//extract the address
- val = reinterpret_cast<mac_addr_t*>(in_data.data.mac_addr)->to_string();
+ val = mac_addr_t::from_bytes(in_data.data.mac_addr).to_string();
return;
}
@@ -159,7 +169,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
return;
case MBOARD_PROP_CLOCK_RATE:
- val = freq_t(get_master_clock_freq());
+ val = double(get_master_clock_freq());
return;
case MBOARD_PROP_RX_DSP:
@@ -184,14 +194,6 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
val = _clock_config;
return;
- case MBOARD_PROP_PPS_SOURCE_NAMES:
- val = prop_names_t(_pps_source_dict.get_keys());
- return;
-
- case MBOARD_PROP_REF_SOURCE_NAMES:
- val = prop_names_t(_ref_source_dict.get_keys());
- return;
-
case MBOARD_PROP_TIME_NOW:
case MBOARD_PROP_TIME_NEXT_PPS:
throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard");
@@ -209,8 +211,8 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
//setup the out data
usrp2_ctrl_data_t out_data;
out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO);
- mac_addr_t mac_addr(val.as<std::string>());
- std::memcpy(out_data.data.mac_addr, &mac_addr, sizeof(mac_addr_t));
+ mac_addr_t mac_addr = mac_addr_t::from_string(val.as<std::string>());
+ std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr);
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
@@ -234,13 +236,9 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
- case MBOARD_PROP_CLOCK_CONFIG:{
- clock_config_t clock_config = val.as<clock_config_t>();
- assert_has(_pps_source_dict.get_keys(), clock_config.pps_source, "usrp2 pps source");
- assert_has(_ref_source_dict.get_keys(), clock_config.ref_source, "usrp2 ref source");
- _clock_config = clock_config; //shadow
- update_clock_config();
- }
+ case MBOARD_PROP_CLOCK_CONFIG:
+ _clock_config = val.as<clock_config_t>();
+ update_clock_config();
return;
case MBOARD_PROP_TIME_NOW:{
@@ -264,8 +262,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_RX_DBOARD_NAMES:
case MBOARD_PROP_TX_DBOARD:
case MBOARD_PROP_TX_DBOARD_NAMES:
- case MBOARD_PROP_PPS_SOURCE_NAMES:
- case MBOARD_PROP_REF_SOURCE_NAMES:
throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard");
}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 85d73e83a..67fbdf8d2 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -15,9 +15,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <uhd/transport/if_addrs.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
#include <boost/format.hpp>
+#include <boost/foreach.hpp>
#include <boost/bind.hpp>
-#include <uhd/utils.hpp>
#include <iostream>
#include "usrp2_impl.hpp"
@@ -27,16 +30,33 @@ using namespace uhd::transport;
namespace asio = boost::asio;
STATIC_BLOCK(register_usrp2_device){
- device::register_device(&usrp2::discover, &usrp2::make);
+ device::register_device(&usrp2::find, &usrp2::make);
}
/***********************************************************************
* Discovery over the udp transport
**********************************************************************/
-uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){
+uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
device_addrs_t usrp2_addrs;
- if (not hint.has_key("addr")) return usrp2_addrs;
+ //if no address was specified, send a broadcast on each interface
+ if (not hint.has_key("addr")){
+ BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){
+ //avoid the loopback device
+ if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue;
+
+ //create a new hint with this broadcast address
+ device_addr_t new_hint = hint;
+ new_hint["addr"] = if_addrs.bcast;
+
+ //call discover with the new hint and append results
+ device_addrs_t new_usrp2_addrs = usrp2::find(new_hint);
+ usrp2_addrs.insert(usrp2_addrs.begin(),
+ new_usrp2_addrs.begin(), new_usrp2_addrs.end()
+ );
+ }
+ return usrp2_addrs;
+ }
//create a udp transport to communicate
//TODO if an addr is not provided, search all interfaces?
@@ -63,7 +83,6 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){
boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr));
device_addr_t new_addr;
new_addr["name"] = "USRP2";
- new_addr["transport"] = "udp";
new_addr["addr"] = ip_addr.to_string();
usrp2_addrs.push_back(new_addr);
//dont break here, it will exit the while loop
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 55ac0b192..3468a0cf1 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -19,9 +19,10 @@
#define INCLUDED_USRP2_IMPL_HPP
#include <uhd/usrp/usrp2.hpp>
-#include <uhd/dict.hpp>
-#include <uhd/types.hpp>
-#include <uhd/time_spec.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/clock_config.hpp>
+#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
@@ -105,8 +106,8 @@ public:
double get_master_clock_freq(void);
//the io interface
- size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &);
- size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &);
+ size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &);
+ size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &);
private:
//device properties interface
@@ -146,11 +147,6 @@ private:
void update_clock_config(void);
void set_time_spec(const uhd::time_spec_t &time_spec, bool now);
- //mappings from clock config strings to over the wire enums
- uhd::dict<std::string, usrp2_ref_source_t> _ref_source_dict;
- uhd::dict<std::string, usrp2_pps_source_t> _pps_source_dict;
- uhd::dict<uhd::clock_config_t::polarity_t, usrp2_pps_polarity_t> _pps_polarity_dict;
-
//rx and tx dboard methods and objects
uhd::usrp::dboard_manager::sptr _dboard_manager;
void dboard_init(void);
@@ -177,16 +173,14 @@ private:
//methods and shadows for the ddc dsp
std::vector<size_t> _allowed_decim_and_interp_rates;
size_t _ddc_decim;
- uhd::freq_t _ddc_freq;
- bool _ddc_enabled;
- uhd::time_spec_t _ddc_stream_at;
+ double _ddc_freq;
void init_ddc_config(void);
void update_ddc_config(void);
- void update_ddc_enabled(void);
+ void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd);
//methods and shadows for the duc dsp
size_t _duc_interp;
- uhd::freq_t _duc_freq;
+ double _duc_freq;
void init_duc_config(void);
void update_duc_config(void);