summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/zpu/apps/txrx_uhd.c35
-rw-r--r--firmware/zpu/lib/eth_addrs.c132
-rw-r--r--firmware/zpu/lib/ethernet.h21
-rw-r--r--firmware/zpu/lib/net_common.c28
-rw-r--r--firmware/zpu/lib/net_common.h5
-rw-r--r--firmware/zpu/usrp2p/u2p_init.c3
-rwxr-xr-xfpga/usrp2/top/extract_usage.py60
-rw-r--r--host/docs/build.rst104
-rw-r--r--host/docs/calibration.rst19
-rw-r--r--host/docs/coding.rst2
-rw-r--r--host/docs/dboards.rst78
-rw-r--r--host/docs/general.rst48
-rw-r--r--host/docs/gpsdo.rst36
-rw-r--r--host/docs/identification.rst24
-rw-r--r--host/docs/images.rst49
-rw-r--r--host/docs/index.rst17
-rw-r--r--host/docs/stream.rst26
-rw-r--r--host/docs/sync.rst24
-rw-r--r--host/docs/transport.rst34
-rw-r--r--host/docs/usrp1.rst16
-rw-r--r--host/docs/usrp2.rst185
-rw-r--r--host/docs/usrp_b1xx.rst30
-rw-r--r--host/docs/usrp_e1xx.rst49
-rw-r--r--host/examples/CMakeLists.txt1
-rw-r--r--host/examples/benchmark_rate.cpp57
-rw-r--r--host/examples/transport_hammer.cpp340
-rw-r--r--host/include/uhd/usrp/multi_usrp.hpp21
-rw-r--r--host/include/uhd/version.hpp2
-rw-r--r--host/lib/usrp/common/fx2_ctrl.cpp39
-rw-r--r--host/lib/usrp/mboard_eeprom.cpp77
-rw-r--r--host/lib/usrp/multi_usrp.cpp56
-rw-r--r--host/lib/usrp/usrp2/fw_common.h9
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp57
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp1
34 files changed, 1174 insertions, 511 deletions
diff --git a/firmware/zpu/apps/txrx_uhd.c b/firmware/zpu/apps/txrx_uhd.c
index 9daf441e2..a4bfce0ec 100644
--- a/firmware/zpu/apps/txrx_uhd.c
+++ b/firmware/zpu/apps/txrx_uhd.c
@@ -92,8 +92,35 @@ static void handle_udp_data_packet(
default: return;
}
- eth_mac_addr_t eth_mac_host; arp_cache_lookup_mac(&src.addr, &eth_mac_host);
- setup_framer(eth_mac_host, *ethernet_mac_addr(), src, dst, which);
+ //assume the packet destination is the packet source
+ //the arp cache lookup should never fail for this case
+ const struct socket_address src_addr = dst;
+ struct socket_address dst_addr = src;
+ eth_mac_addr_t eth_mac_dst;
+ arp_cache_lookup_mac(&dst_addr.addr, &eth_mac_dst);
+
+ //however, if this control packet has an alternative destination...
+ if (payload_len >= sizeof(usrp2_stream_ctrl_t)){
+
+ //parse the destination ip addr and udp port from the payload
+ const usrp2_stream_ctrl_t *stream_ctrl = (const usrp2_stream_ctrl_t *)payload;
+ dst_addr.addr.addr = stream_ctrl->ip_addr;
+ dst_addr.port = (uint16_t)stream_ctrl->udp_port;
+ struct ip_addr ip_dest = dst_addr.addr;
+
+ //are we in the subnet? if not use the gateway
+ const uint32_t subnet_mask = get_subnet()->addr;
+ const bool in_subnet = ((get_ip_addr()->addr & subnet_mask) == (ip_dest.addr & subnet_mask));
+ if (!in_subnet) ip_dest = *get_gateway();
+
+ //lookup the host ip address with ARP (this may fail)
+ const bool ok = arp_cache_lookup_mac(&ip_dest, &eth_mac_dst);
+ if (!ok) net_common_send_arp_request(&ip_dest);
+ const uint32_t result = (ok)? 0 : ~0;
+ send_udp_pkt(dst.port, src, &result, sizeof(result));
+ }
+
+ setup_framer(eth_mac_dst, *ethernet_mac_addr(), dst_addr, src_addr, which);
}
#define OTW_GPIO_BANK_TO_NUM(bank) \
@@ -279,6 +306,7 @@ int
main(void)
{
u2_init();
+ arp_cache_init();
#ifdef BOOTLOADER
putstr("\nUSRP N210 UDP bootloader\n");
#else
@@ -294,8 +322,7 @@ main(void)
//load the production FPGA image or firmware if appropriate
do_the_bootload_thing();
//if we get here we've fallen through to safe firmware
- set_default_mac_addr();
- set_default_ip_addr();
+ eth_addrs_set_default();
#endif
print_mac_addr(ethernet_mac_addr()); newline();
diff --git a/firmware/zpu/lib/eth_addrs.c b/firmware/zpu/lib/eth_addrs.c
index c45ce7559..6d3347cf3 100644
--- a/firmware/zpu/lib/eth_addrs.c
+++ b/firmware/zpu/lib/eth_addrs.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2011 Ettus Research LLC
+ * Copyright 2010-2012 Ettus Research LLC
* Copyright 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "memory_map.h"
#include "nonstdio.h"
#include <stdbool.h>
+#include <string.h>
#include "i2c.h"
#include "usrp2/fw_common.h"
@@ -37,104 +38,69 @@ unprogrammed(const void *t, size_t len)
return all_ones | all_zeros;
}
-//////////////////// MAC Addr Stuff ///////////////////////
+typedef struct{
+ eth_mac_addr_t mac_addr;
+ struct ip_addr ip_addr;
+ struct ip_addr gateway;
+ struct ip_addr subnet;
+} eth_addrs_t;
-static bool src_mac_addr_initialized = false;
+static bool eth_addrs_initialized = false;
-static const eth_mac_addr_t default_mac_addr = {{
- 0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff
- }};
+static const eth_addrs_t default_eth_addrs = {
+ .mac_addr = {{0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff}},
+ .ip_addr = {(192 << 24 | 168 << 16 | 10 << 8 | 2 << 0)},
+ .gateway = {(192 << 24 | 168 << 16 | 10 << 8 | 1 << 0)},
+ .subnet = {(255 << 24 | 255 << 16 | 255 << 8 | 0 << 0)},
+};
-static eth_mac_addr_t src_mac_addr = {{
- 0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff
- }};
-
-void set_default_mac_addr(void)
-{
- src_mac_addr_initialized = true;
- src_mac_addr = default_mac_addr;
-}
+static eth_addrs_t current_eth_addrs;
-const eth_mac_addr_t *
-ethernet_mac_addr(void)
-{
- if (!src_mac_addr_initialized){ // fetch from eeprom
- src_mac_addr_initialized = true;
+static void eth_addrs_init(void){
+ if (eth_addrs_initialized) return;
+ eth_addrs_initialized = true;
- // if we're simulating, don't read the EEPROM model, it's REALLY slow
- if (hwconfig_simulation_p())
- return &src_mac_addr;
-
- eth_mac_addr_t tmp;
- bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, &tmp, sizeof(tmp));
- if (!ok || unprogrammed(&tmp, sizeof(tmp))){
- // use the default
+ #define eth_addrs_init_x(addr, x){ \
+ const bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, addr, &current_eth_addrs.x, sizeof(current_eth_addrs.x)); \
+ if (!ok || unprogrammed(&current_eth_addrs.x, sizeof(current_eth_addrs.x))){ \
+ memcpy(&current_eth_addrs.x, &default_eth_addrs.x, sizeof(current_eth_addrs.x)); \
+ } \
}
- else
- src_mac_addr = tmp;
- }
- return &src_mac_addr;
-}
+ eth_addrs_init_x(USRP2_EE_MBOARD_MAC_ADDR, mac_addr);
+ eth_addrs_init_x(USRP2_EE_MBOARD_IP_ADDR, ip_addr);
+ eth_addrs_init_x(USRP2_EE_MBOARD_GATEWAY, gateway);
+ eth_addrs_init_x(USRP2_EE_MBOARD_SUBNET, subnet);
-bool
-ethernet_set_mac_addr(const eth_mac_addr_t *t)
-{
- bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t));
- if (ok){
- src_mac_addr = *t;
- src_mac_addr_initialized = true;
- //eth_mac_set_addr(t); //this breaks the link
- }
-
- return ok;
}
-//////////////////// IP Addr Stuff ///////////////////////
-
-static bool src_ip_addr_initialized = false;
-
-static const struct ip_addr default_ip_addr = {
- (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0)
-};
-
-static struct ip_addr src_ip_addr = {
- (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0)
-};
-
-void set_default_ip_addr(void)
-{
- src_ip_addr_initialized = true;
- src_ip_addr = default_ip_addr;
+const eth_mac_addr_t *ethernet_mac_addr(void){
+ eth_addrs_init();
+ return &current_eth_addrs.mac_addr;
}
-const struct ip_addr *get_ip_addr(void)
-{
- if (!src_ip_addr_initialized){ // fetch from eeprom
- src_ip_addr_initialized = true;
-
- // if we're simulating, don't read the EEPROM model, it's REALLY slow
- if (hwconfig_simulation_p())
- return &src_ip_addr;
+const struct ip_addr *get_ip_addr(void){
+ eth_addrs_init();
+ return &current_eth_addrs.ip_addr;
+}
- struct ip_addr tmp;
- bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, &tmp, sizeof(tmp));
- if (!ok || unprogrammed(&tmp, sizeof(tmp))){
- // use the default
- }
- else
- src_ip_addr = tmp;
- }
+const struct ip_addr *get_subnet(void){
+ eth_addrs_init();
+ return &current_eth_addrs.subnet;
+}
- return &src_ip_addr;
+const struct ip_addr *get_gateway(void){
+ eth_addrs_init();
+ return &current_eth_addrs.gateway;
}
bool set_ip_addr(const struct ip_addr *t){
- bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, t, sizeof(struct ip_addr));
- if (ok){
- src_ip_addr = *t;
- src_ip_addr_initialized = true;
- }
+ const bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, t, sizeof(struct ip_addr));
+ if (ok) current_eth_addrs.ip_addr = *t;
+ return ok;
+}
- return ok;
+void eth_addrs_set_default(void){
+ eth_addrs_initialized = true;
+ memcpy(&current_eth_addrs, &default_eth_addrs, sizeof(default_eth_addrs));
}
diff --git a/firmware/zpu/lib/ethernet.h b/firmware/zpu/lib/ethernet.h
index 52b297349..b5b08cb8c 100644
--- a/firmware/zpu/lib/ethernet.h
+++ b/firmware/zpu/lib/ethernet.h
@@ -1,5 +1,5 @@
-/* -*- c -*- */
/*
+ * Copyright 2010-2012 Ettus Research LLC
* Copyright 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
@@ -44,27 +44,28 @@ void ethernet_register_link_changed_callback(ethernet_link_changed_callback_t cb
*/
const eth_mac_addr_t *ethernet_mac_addr(void);
-/*!set mac addr to default*/
-void set_default_mac_addr(void);
-
/*!
- * \brief write mac address to eeprom and begin using it
+ * \returns IP address
*/
-bool ethernet_set_mac_addr(const eth_mac_addr_t *t);
+const struct ip_addr *get_ip_addr(void);
/*!
- * \returns IP address
+ * \returns gateway address
*/
-const struct ip_addr *get_ip_addr(void);
+const struct ip_addr *get_gateway(void);
-/*!set ip addr to default*/
-void set_default_ip_addr(void);
+/*!
+ * \returns subnet address
+ */
+const struct ip_addr *get_subnet(void);
/*!
* \brief write ip address to eeprom and begin using it
*/
bool set_ip_addr(const struct ip_addr *t);
+//! Apply default settings to eth addrs
+void eth_addrs_set_default(void);
/*
* \brief read RMON regs and return error mask
diff --git a/firmware/zpu/lib/net_common.c b/firmware/zpu/lib/net_common.c
index 42e365393..9b75006d3 100644
--- a/firmware/zpu/lib/net_common.c
+++ b/firmware/zpu/lib/net_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2011 Ettus Research LLC
+ * Copyright 2009-2012 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
@@ -374,6 +374,22 @@ send_arp_reply(struct arp_eth_ipv4 *req, eth_mac_addr_t our_mac)
send_pkt(t, ETHERTYPE_ARP, &reply, sizeof(reply), 0, 0, 0, 0);
}
+void net_common_send_arp_request(const struct ip_addr *addr){
+ struct arp_eth_ipv4 req _AL4;
+ req.ar_hrd = ARPHRD_ETHER;
+ req.ar_pro = ETHERTYPE_IPV4;
+ req.ar_hln = sizeof(eth_mac_addr_t);
+ req.ar_pln = sizeof(struct ip_addr);
+ req.ar_op = ARPOP_REQUEST;
+ memcpy(req.ar_sha, ethernet_mac_addr(), sizeof(eth_mac_addr_t));
+ memcpy(req.ar_sip, get_ip_addr(), sizeof(struct ip_addr));
+ memset(req.ar_tha, 0x00, sizeof(eth_mac_addr_t));
+ memcpy(req.ar_tip, addr, sizeof(struct ip_addr));
+
+ //send the request with a broadcast ethernet mac address
+ send_pkt(BCAST_MAC_ADDR, ETHERTYPE_ARP, &req, sizeof(req), 0, 0, 0, 0);
+}
+
void send_gratuitous_arp(void){
struct arp_eth_ipv4 req _AL4;
req.ar_hrd = ARPHRD_ETHER;
@@ -415,7 +431,15 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size)
|| p->ar_hln != 6
|| p->ar_pln != 4)
return;
-
+
+ if (p->ar_op == ARPOP_REPLY){
+ struct ip_addr ip_addr;
+ memcpy(&ip_addr, p->ar_sip, sizeof(ip_addr));
+ eth_mac_addr_t mac_addr;
+ memcpy(&mac_addr, p->ar_sha, sizeof(mac_addr));
+ arp_cache_update(&ip_addr, &mac_addr);
+ }
+
if (p->ar_op != ARPOP_REQUEST)
return;
diff --git a/firmware/zpu/lib/net_common.h b/firmware/zpu/lib/net_common.h
index 3cbc5c514..5e6daf689 100644
--- a/firmware/zpu/lib/net_common.h
+++ b/firmware/zpu/lib/net_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2011 Ettus Research LLC
+ * Copyright 2009-2012 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
@@ -55,4 +55,7 @@ void handle_eth_packet(uint32_t *p, size_t nlines);
void send_gratuitous_arp(void);
+//! Send an ARP request for the given IP address
+void net_common_send_arp_request(const struct ip_addr *addr);
+
#endif /* INCLUDED_NET_COMMON_H */
diff --git a/firmware/zpu/usrp2p/u2p_init.c b/firmware/zpu/usrp2p/u2p_init.c
index 381987ae6..1890dd726 100644
--- a/firmware/zpu/usrp2p/u2p_init.c
+++ b/firmware/zpu/usrp2p/u2p_init.c
@@ -24,7 +24,6 @@ void u2p_init(void){
bool safe_fw = find_safe_booted_flag();
set_safe_booted_flag(0);
if (safe_fw) {
- set_default_ip_addr();
- set_default_mac_addr();
+ eth_addrs_set_default();
}
}
diff --git a/fpga/usrp2/top/extract_usage.py b/fpga/usrp2/top/extract_usage.py
new file mode 100755
index 000000000..55fbf384c
--- /dev/null
+++ b/fpga/usrp2/top/extract_usage.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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/>.
+#
+
+import os
+import sys
+
+ALL_MAP_FILES = """\
+./N2x0/build-N210R4/u2plus_map.map N210
+./N2x0/build-N200R4/u2plus_map.map N200
+./USRP2/build/u2_rev3_map.map USRP2
+./E1x0/build-E100/u1e_map.map E100
+./E1x0/build-E110/u1e_map.map E110
+./B100/build-B100/B100_map.map B100
+"""
+
+def extract_map_from_file(path):
+ output = ''
+ found = False
+ for line in open(path).readlines():
+ if line.strip() == 'Mapping completed.': found = False
+ if line.strip() == 'Logic Utilization:': found = True
+ if found: output += line
+ return output
+
+def extract_maps():
+ output = ''
+ for line in ALL_MAP_FILES.splitlines():
+ path, name = line.split()
+ if not os.path.exists(path):
+ print 'DNE ', path, ' skipping...'
+ output += """
+
+
+
+########################################################################
+## %s Usage Summary
+########################################################################
+
+%s"""%(name, extract_map_from_file(path).strip())
+ return output + '\n\n'
+
+if __name__ == '__main__':
+ summary = extract_maps()
+ if len(sys.argv) == 1: print summary
+ else: open(sys.argv[1], 'w').write(summary)
diff --git a/host/docs/build.rst b/host/docs/build.rst
index ee522780a..0a18e9e9a 100644
--- a/host/docs/build.rst
+++ b/host/docs/build.rst
@@ -14,25 +14,25 @@ the dependencies should be available in the package repositories for your
package manager.
**Mac OS X Notes:**
-Install the "Xcode Developer Tools" to get the build tools (gcc and make).
+Install the "Xcode Developer Tools" to get the build tools (GCC and Make).
Use MacPorts to get the Boost and Cheetah dependencies.
-Other dependencies can be downloaded as dmg installers from the web.
+Other dependencies can be downloaded as DMG installers from the web.
**Windows Notes:**
-The dependencies can be acquired through installable exe files.
-Usually, the windows installer can be found on the project's website.
-Some projects do not host windows installers, and if this is the case,
-follow the auxiliary download url for the windows installer (below).
+The dependencies can be acquired through installable EXE files.
+Usually, the Windows installer can be found on the project's website.
+Some projects do not host Windows installers, and if this is the case,
+follow the auxiliary download URL for the Windows installer (below).
^^^^^^^^^^^^^^^^
Git
^^^^^^^^^^^^^^^^
Required to check out the repository.
-On windows, install cygwin with git support to checkout the repository,
-or install msysgit from http://code.google.com/p/msysgit/downloads/list
+On Windows, install Cygwin with Git support to checkout the repository
+or install msysGit from http://code.google.com/p/msysgit/downloads/list.
^^^^^^^^^^^^^^^^
-C++ compiler
+C++ Compiler
^^^^^^^^^^^^^^^^
The following compilers are known to work:
@@ -44,7 +44,7 @@ The following compilers are known to work:
CMake
^^^^^^^^^^^^^^^^
* **Purpose:** generates project build files
-* **Version:** at least 2.6
+* **Minimum Version:** 2.6
* **Usage:** build time (required)
* **Download URL:** http://www.cmake.org/cmake/resources/software.html
@@ -52,57 +52,57 @@ CMake
Boost
^^^^^^^^^^^^^^^^
* **Purpose:** C++ library
-* **Version:** at least 1.36 unix, at least 1.40 windows
-* **Usage:** build time + run time (required)
+* **Minimum Version:** 1.36 (Linux), 1.40 (Windows)
+* **Usage:** build time + runtime (required)
* **Download URL:** http://www.boost.org/users/download/
-* **Download URL (windows installer):** http://www.boostpro.com/download
+* **Download URL (Windows installer):** http://www.boostpro.com/download
^^^^^^^^^^^^^^^^
LibUSB
^^^^^^^^^^^^^^^^
* **Purpose:** USB-based hardware support
-* **Version:** at least 1.0
-* **Usage:** build time + run time (optional)
+* **Minimum Version:** 1.0
+* **Usage:** build time + runtime (optional)
* **Download URL:** http://sourceforge.net/projects/libusb/files/libusb-1.0/
-* **Download URL (windows binaries):** http://www.libusb.org/wiki/windows_backend#LatestBinarySnapshots
+* **Download URL (Windows binaries):** http://www.libusb.org/wiki/windows_backend#LatestBinarySnapshots
^^^^^^^^^^^^^^^^
Python
^^^^^^^^^^^^^^^^
* **Purpose:** used by Cheetah and utility scripts
-* **Version:** at least 2.6
-* **Usage:** build time + run time utility scripts (required)
+* **Minimum Version:** 2.6
+* **Usage:** build time + runtime utility scripts (required)
* **Download URL:** http://www.python.org/download/
^^^^^^^^^^^^^^^^
Cheetah
^^^^^^^^^^^^^^^^
* **Purpose:** source code generation
-* **Version:** at least 2.0
+* **Minimum Version:** 2.0
* **Usage:** build time (required)
* **Download URL:** http://www.cheetahtemplate.org/download.html
-* **Download URL (windows installer):** http://feisley.com/python/cheetah/
+* **Download URL (Windows installer):** http://feisley.com/python/cheetah/
**Alternative method:**
-Install setuptools, and use the easy_install command to install Cheetah.
+Install **setuptools**, and use the **easy_install** command to install Cheetah.
http://pypi.python.org/pypi/setuptools
^^^^^^^^^^^^^^^^
Doxygen
^^^^^^^^^^^^^^^^
-* **Purpose:** generates html api documentation
+* **Purpose:** generates HTML API documentation
* **Usage:** build time (optional)
* **Download URL:** http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc
^^^^^^^^^^^^^^^^
Docutils
^^^^^^^^^^^^^^^^
-* **Purpose:** generates html user manual
+* **Purpose:** generates HTML user manual
* **Usage:** build time (optional)
* **Download URL:** http://docutils.sourceforge.net/
**Alternate method:**
-Install setuptools, and use the easy_install command to install Docutils.
+Install **setuptools**, and use the **easy_install** command to install Docutils.
http://pypi.python.org/pypi/setuptools
------------------------------------------------------------------------
@@ -110,7 +110,7 @@ Build Instructions (Unix)
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Generate Makefiles with cmake
+Generate Makefiles with CMake
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
@@ -119,11 +119,11 @@ Generate Makefiles with cmake
cd build
cmake ../
-Additionally, configuration variables can be passed into cmake via the command line.
+Additionally, configuration variables can be passed into CMake via the command line.
The following common-use configuration variables are listed below:
-* For a custom install prefix: -DCMAKE_INSTALL_PREFIX=<install-path>
-* To install libs into lib64: cmake -DLIB_SUFFIX=64
+* For a custom install prefix: **-DCMAKE_INSTALL_PREFIX=<install-path>**
+* To install libs into lib64: **cmake -DLIB_SUFFIX=64**
Example usage:
::
@@ -142,8 +142,8 @@ Build and install
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Setup the library path (Linux)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Make sure that libuhd.so is in your LD_LIBRARY_PATH
-or add it to /etc/ld.so.conf and make sure to run:
+Make sure that **libuhd.so** is in your **LD_LIBRARY_PATH**,
+or add it to **/etc/ld.so.conf** and make sure to run:
::
sudo ldconfig
@@ -151,46 +151,46 @@ or add it to /etc/ld.so.conf and make sure to run:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Setup the library path (Mac OS X)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Make sure that libuhd.dylib is in your DYLD_LIBRARY_PATH
+Make sure that **libuhd.dylib** is in your **DYLD_LIBRARY_PATH**.
------------------------------------------------------------------------
Build Instructions (Windows)
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Generate the project with cmake
+Generate the project with CMake
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-* Open the cmake gui program.
-* Set the path to the source code: <uhd-repo-path>/host
-* Set the path to the build directory: <uhd-repo-path>/host/build
+* Open the CMake GUI.
+* Set the path to the source code: **<uhd-repo-path>/host**.
+* Set the path to the build directory: **<uhd-repo-path>/host/build**.
* Make sure that the paths do not contain spaces.
-* Click configure and select the MSVC compiler.
-* Set the build variables and click configure again.
-* Click generate and a project file will be created in the build directory.
+* Click "Configure" and select "Microsoft Visual Studio 10".
+* Set the build variables and click "Configure" again.
+* Click "Generate", and a project file will be created in the build directory.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LibUSB cmake notes
+LibUSB CMake notes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-On Windows, cmake does not have the advantage of pkg-config,
-so we must manually tell cmake how to locate the LibUSB header and lib.
+On Windows, CMake does not have the advantage of **pkg-config**,
+so we must manually tell CMake how to locate the LibUSB header and lib.
-* From the cmake gui, select "Advanded View"
-* Set LIBUSB_INCLUDE_DIRS to the directory with "libusb.h".
-* Set LIBUSB_LIBRARIES to the full path for "libusb-1.0.lib".
+* From the CMake GUI, select "Advanced View".
+* Set **LIBUSB_INCLUDE_DIRS** to the directory with **libusb.h**.
+* Set **LIBUSB_LIBRARIES** to the full path for **libusb-1.0.lib**.
- * Recommend the static libusb-1.0.lib to simplify runtime dependencies.
+ * Recommend the static **libusb-1.0.lib** to simplify runtime dependencies.
-* Check the box to enable USB support, click configure and generate.
+* Check the box to enable USB support, click "Configure" and "Generate".
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Build the project in MSVC
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Open the generated project file in MSVC.
* Change the build type from "Debug" to "Release".
-* Select the build all target, right click, and choose build.
-* Select the install target, right click, and choose build.
+* Select the "Build All" target, right-click, and choose "Build".
+* Select the install target, right-click, and choose "Build".
-**Note:** you may not have permission to build the install target.
+**Note:** You may not have permission to build the install target.
You need to be an administrator or to run MSVC as administrator.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -206,11 +206,11 @@ Open the Visual Studio Command Prompt Shorcut:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Setup the PATH environment variable
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-* Add the uhd bin path to %PATH% (usually c:\\program files\\uhd\\bin)
+* Add the UHD bin path to **%PATH%** (usually **C:\\Program Files\\UHD\\bin**)
**Note:**
-The interface for editing environment variable paths in Windows is very poor.
-I recommend using "Rapid Environment Editor" (http://www.rapidee.com) over the default editor.
+The default interface for editing environment variable paths in Windows is very poor.
+We recommend using "Rapid Environment Editor" (http://www.rapidee.com) over the default editor.
------------------------------------------------------------------------
Post-Install Tasks
diff --git a/host/docs/calibration.rst b/host/docs/calibration.rst
index 14e66a312..680a74f3b 100644
--- a/host/docs/calibration.rst
+++ b/host/docs/calibration.rst
@@ -7,10 +7,10 @@ UHD - Calibration Application Notes
------------------------------------------------------------------------
Self-calibration
------------------------------------------------------------------------
-The UHD comes with several self-calibration utilities for minimizing IQ imbalance and DC offset.
+UHD comes with several self-calibration utilities for minimizing IQ imbalance and DC offset.
These utilities perform calibration sweeps using transmit leakage into the receive path
(special equipment is not required).
-The results from a calibration are written to a csv file in the user's home directory.
+The results from a calibration are written to a CSV file in the user's home directory.
UHD will automatically apply corrections at runtime when the user re-tunes the daughterboard LO.
Calibration results are specific to an individual RF board.
@@ -21,10 +21,9 @@ the user should re-apply the desired setting every time the LO is re-tuned.
UHD comes with the following calibration utilities:
- * **uhd_cal_rx_iq_balance:** - mimimizes RX IQ imbalance vs LO frequency
- * **uhd_cal_tx_dc_offset:** - mimimizes TX DC offset vs LO frequency
- * **uhd_cal_tx_iq_balance:** - mimimizes TX IQ imbalance vs LO frequency
-
+ * **uhd_cal_rx_iq_balance:** - mimimizes RX IQ imbalance vs. LO frequency
+ * **uhd_cal_tx_dc_offset:** - mimimizes TX DC offset vs. LO frequency
+ * **uhd_cal_tx_iq_balance:** - mimimizes TX IQ imbalance vs. LO frequency
The following RF frontends are supported by the self-calibration utilities:
@@ -33,9 +32,9 @@ The following RF frontends are supported by the self-calibration utilities:
* more to come...
********************************************
-Calibration utilities
+Calibration Utilities
********************************************
-UHD installs the calibration utilities into <install-path>/bin.
+UHD installs the calibration utilities into **<install-path>/bin**.
**Disconnect** any extrernal hardware from the RF antenna ports,
and run the following from the command line.
Each utility will take several minutes to complete.
@@ -49,13 +48,13 @@ See the output given by --help for more advanced options, such as:
manually choosing the frequency range and step size for the sweeps.
********************************************
-Calibration data
+Calibration Data
********************************************
Calibration files are stored in the user's home/application directory.
They can easily be moved from machine to another by copying the "cal" directory.
Re-running a calibration utility will replace the existing calibration file.
The old calibration file will be renamed so it may be recovered by the user.
- * **Unix:** ${HOME}/.uhd/cal/
+ * **Linux:** ${HOME}/.uhd/cal/
* **Windows:** %APPDATA%\\.uhd\\cal\\
diff --git a/host/docs/coding.rst b/host/docs/coding.rst
index ed858ceb4..ef8cb5fe2 100644
--- a/host/docs/coding.rst
+++ b/host/docs/coding.rst
@@ -23,7 +23,7 @@ considered to be a "device". The device API provides ways to:
See the documentation in *device.hpp* for reference.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-High-Level: The multi usrp
+High-Level: The Multi-USRP
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The Multi-USRP class provides a fat interface to a single USRP with
one or more channels, or multiple USRPs in a homogeneous setup.
diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst
index d41bf824c..29812592f 100644
--- a/host/docs/dboards.rst
+++ b/host/docs/dboards.rst
@@ -13,7 +13,7 @@ Eventually, this page will be expanded to list out the full
properties of each board as well.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Basic RX and and LFRX
+Basic RX and LFRX
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The Basic RX and LFRX boards have 4 frontends:
@@ -23,21 +23,21 @@ The Basic RX and LFRX boards have 4 frontends:
* **Frontend BA:** quadrature frontend using both antennas (QI)
The boards have no tunable elements or programmable gains.
-Though the magic of aliasing, you can down-convert signals
+Through the magic of aliasing, you can down-convert signals
greater than the Nyquist rate of the ADC.
BasicRX Bandwidth (Hz):
-* For Real-Mode (A or B frontend): 250M
-* For Complex (AB or BA frontend): 500M
+* **For Real-Mode (A or B frontend)**: 250M
+* **For Complex (AB or BA frontend)**: 500M
LFRX Bandwidth (Hz):
-* For Real-Mode (A or B frontend): 33M
-* For Complex (AB or BA frontend): 66M
+* **For Real-Mode (A or B frontend)**: 33M
+* **For Complex (AB or BA frontend)**: 66M
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Basic TX and and LFTX
+Basic TX and LFTX
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The Basic TX and LFTX boards have 4 frontends:
@@ -47,30 +47,30 @@ The Basic TX and LFTX boards have 4 frontends:
* **Frontend BA:** quadrature frontend using both antennas (QI)
The boards have no tunable elements or programmable gains.
-Though the magic of aliasing, you can up-convert signals
+Through the magic of aliasing, you can up-convert signals
greater than the Nyquist rate of the DAC.
BasicTX Bandwidth (Hz): 250M
-* For Real-Mode (A or B frontend): 250M
-* For Complex (AB or BA frontend): 500M
+* **For Real-Mode (A or B frontend**): 250M
+* **For Complex (AB or BA frontend)**: 500M
LFTX Bandwidth (Hz): 33M
-* For Real-Mode (A or B frontend): 33M
-* For Complex (AB or BA frontend): 66M
+* **For Real-Mode (A or B frontend)**: 33M
+* **For Complex (AB or BA frontend)**: 66M
^^^^^^^^^^^^^^^^^^^^^^^^^^^
DBSRX
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The DBSRX board has 1 quadrature frontend.
-It defaults to direct conversion, but can use a low IF through lo_offset in uhd::tune_request_t
+It defaults to direct conversion but can use a low IF through lo_offset in **uhd::tune_request_t**.
Receive Antennas: **J3**
* **Frontend 0:** Complex baseband signal from antenna J3
-The board has no user selectable antenna setting
+The board has no user selectable antenna setting.
Receive Gains:
@@ -87,13 +87,13 @@ Sensors:
DBSRX2
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The DBSRX2 board has 1 quadrature frontend.
-It defaults to direct conversion, but can use a low IF through lo_offset in uhd::tune_request_t
+It defaults to direct conversion, but can use a low IF through lo_offset in **uhd::tune_request_t**.
Receive Antennas: **J3**
* **Frontend 0:** Complex baseband signal from antenna J3
-The board has no user selectable antenna setting
+The board has no user-selectable antenna setting.
Receive Gains:
@@ -109,9 +109,9 @@ Sensors:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
RFX Series
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The RFX Series boards have 2 quadrature frontends, one transmit, one receive.
-Transmit defaults to low IF and Receive defaults to direct conversion.
-The IF can be adjusted through lo_offset in uhd::tune_request_t
+The RFX Series boards have 2 quadrature frontends: Transmit and Receive.
+Transmit defaults to low IF, and Receive defaults to direct conversion.
+The IF can be adjusted through lo_offset in **uhd::tune_request_t**.
The RFX Series boards have independent receive and transmit LO's and synthesizers
allowing full-duplex operation on different transmit and receive frequencies.
@@ -185,7 +185,7 @@ WBX Series
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The WBX Series boards have 2 quadrature frontends, one transmit, one receive.
Transmit and Receive default to direct conversion but
-can be used in low IF mode through lo_offset in uhd::tune_request_t
+can be used in low IF mode through lo_offset in **uhd::tune_request_t**.
The WBX Series boards have independent receive and transmit LO's and synthesizers
allowing full-duplex operation on different transmit and receive frequencies.
@@ -218,7 +218,7 @@ SBX Series
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The SBX Series boards have 2 quadrature frontends, one transmit, one receive.
Transmit and Receive default to direct conversion but
-can be used in low IF mode through lo_offset in uhd::tune_request_t
+can be used in low IF mode through lo_offset in **uhd::tune_request_t**.
The SBX Series boards have independent receive and transmit LO's and synthesizers
allowing full-duplex operation on different transmit and receive frequencies.
@@ -282,7 +282,7 @@ Receive Frontends:
* **Frontend RX1:** real-mode baseband from antenna J100
* **Frontend RX2:** real-mode baseband from antenna J140
-Note: The TVRX2 has always-on AGC, the software controllable gain is the
+Note: The TVRX2 has always-on AGC; the software controllable gain is the
final gain stage which controls the AGC set-point for output to ADC.
Receive Gains:
@@ -303,8 +303,8 @@ Daughterboard Modifications
Sometimes, daughterboards will require modification
to work on certain frequencies or to work with certain hardware.
-Modification usually involves moving/removing a SMT component
-and burning a new daughterboard id into the eeprom.
+Modification usually involves moving/removing an SMT component
+and burning a new daughterboard ID into the EEPROM.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
DBSRX - Mod
@@ -319,13 +319,13 @@ over the standard daughterboard clock lines.
**Step 1: Move the clock configuration resistor**
-Remove R193 (which is 10 ohms, 0603 size) and put it on R194, which is empty.
+Remove **R193** (which is 10 ohms, 0603 size), and put it on **R194**, which is empty.
This is made somewhat more complicated by the fact that the silkscreen is not clear in that area.
-R193 is on the back, immediately below the large beige connector, J2.
-R194 is just below, and to the left of R193.
-The silkscreen for R193 is ok, but for R194,
+**R193** is on the back, immediately below the large beige connector, **J2**.
+**R194** is just below, and to the left of **R193**.
+The silkscreen for **R193** is ok, but for **R194**,
it is upside down, and partially cut off.
-If you lose R193, you can use anything from 0 to 10 ohms there.
+If you lose **R193**, you can use anything from 0 to 10 ohms there.
**Step 2: Burn a new daughterboard id into the EEPROM**
@@ -335,8 +335,8 @@ With the daughterboard plugged-in, run the following commands:
cd <install-path>/share/uhd/utils
./usrp_burn_db_eeprom --id=0x000d --unit=RX --args=<args> --slot=<slot>
-* <args> are device address arguments (optional if only one USRP is on your machine)
-* <slot> is the name of the daughterboard slot (optional if the USRP has only one slot)
+* **<args>** are device address arguments (optional if only one USRP is on your machine)
+* **<slot>** is the name of the daughterboard slot (optional if the USRP has only one slot)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
RFX - Mod
@@ -347,14 +347,14 @@ Please follow the modification procedures below:
**Step 1: Disable the daughterboard clocks**
-Move R64 to R84, Move R142 to R153
+Move **R64** to **R84**. Move **R142** to **R153**.
**Step 2: Connect the motherboard blocks**
-Move R35 to R36, Move R117 to R115
-These are all 0-ohm, so if you lose one, just short across the appropriate pads
+Move **R35** to **R36**. Move **R117** to **R115**.
+These are all 0-ohm, so if you lose one, just short across the appropriate pads.
-**Step 3: Burn the appropriate daughterboard id into the EEPROM**
+**Step 3: Burn the appropriate daughterboard ID into the EEPROM**
With the daughterboard plugged-in, run the following commands:
::
@@ -363,19 +363,19 @@ With the daughterboard plugged-in, run the following commands:
./usrp_burn_db_eeprom --id=<rx_id> --unit=RX --args=<args> --slot=<slot>
./usrp_burn_db_eeprom --id=<tx_id> --unit=TX --args=<args> --slot=<slot>
-* <rx_id> choose the appropriate RX ID for your daughterboard
+* **<rx_id>** choose the appropriate RX ID for your daughterboard
* **RFX400:** 0x0024
* **RFX900:** 0x0025
* **RFX1800:** 0x0034
* **RFX1200:** 0x0026
* **RFX2400:** 0x0027
-* <tx_id> choose the appropriate TX ID for your daughterboard
+* **<tx_id>** choose the appropriate TX ID for your daughterboard
* **RFX400:** 0x0028
* **RFX900:** 0x0029
* **RFX1800:** 0x0035
* **RFX1200:** 0x002a
* **RFX2400:** 0x002b
-* <args> are device address arguments (optional if only one USRP is on your machine)
-* <slot> is the name of the daughterboard slot (optional if the USRP has only one slot)
+* **<args>** are device address arguments (optional if only one USRP is on your machine)
+* **<slot>** is the name of the daughterboard slot (optional if the USRP has only one slot)
diff --git a/host/docs/general.rst b/host/docs/general.rst
index 5df89fc19..fc7caff3c 100644
--- a/host/docs/general.rst
+++ b/host/docs/general.rst
@@ -5,7 +5,7 @@ UHD - General Application Notes
.. contents:: Table of Contents
------------------------------------------------------------------------
-Tuning notes
+Tuning Notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,12 +20,12 @@ In a typical use-case, the user specifies an overall center frequency for the
signal chain. The RF front-end will be tuned as close as possible to the center
frequency, and the DSP will account for the error in tuning between target
frequency and actual frequency. The user may also explicitly control both
-stages of tuning through through the tune_request_t object, which allows for
+stages of tuning through through the **tune_request_t** object, which allows for
more advanced tuning.
In general, Using UHD's advanced tuning is highly recommended as it makes it
easy to move the DC component out of your band-of-interest. This can be done by
-passing your desired LO offset to the tune_request_t object, and letting UHD
+passing your desired LO offset to the **tune_request_t** object, and letting UHD
handle the rest.
Tuning the receive chain:
@@ -50,7 +50,7 @@ After tuning, the RF front-end will need time to settle into a usable state.
Typically, this means that the local oscillators must be given time to lock
before streaming begins. Lock time is not consistent; it varies depending upon
the device and requested settings. After tuning and before streaming, the user
-should wait for the "lo_locked" sensor to become true, or sleep for
+should wait for the **lo_locked** sensor to become true or sleep for
a conservative amount of time (perhaps a second).
Pseudo-code for dealing with settling time after tuning on receive:
@@ -69,7 +69,7 @@ Pseudo-code for dealing with settling time after tuning on receive:
usrp->issue_stream_command(...);
------------------------------------------------------------------------
-Specifying the subdevice to use
+Specifying the Subdevice to Use
------------------------------------------------------------------------
A subdevice specification string for USRP family devices is composed of:
@@ -115,7 +115,7 @@ The frontend names are documented in the
`Daughterboard Application Notes <./dboards.html>`_
------------------------------------------------------------------------
-Overflow/Underflow notes
+Overflow/Underflow Notes
------------------------------------------------------------------------
**Note:** The following overflow/underflow notes do not apply to USRP1,
which does not support the advanced features available in newer products.
@@ -132,26 +132,26 @@ and pushes an inline message packet into the receive stream.
The host does not back-pressure the receive stream.
When the kernel's socket buffer becomes full, it will drop subsequent packets.
UHD detects the overflow as a discontinuity in the packet's sequence numbers,
-and muxes an inline message packet into the receive stream.
+and pushes an inline message packet into the receive stream.
**Other devices**:
The host back-pressures the receive stream.
Therefore, overflows always occur in the device itself.
-When the device's internal buffers become full, streaming is shutoff,
+When the device's internal buffers become full, streaming is shut off,
and an inline message packet is sent to the host.
If the device was in continuous streaming mode,
-the UHD will automatically restart streaming.
+UHD will automatically restart streaming.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Underflow notes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When transmitting, the device consumes samples at a constant rate.
Underflow occurs when the host does not produce data fast enough.
-When the UHD detects underflow, it prints an "U" to stdout,
+When UHD detects underflow, it prints a "U" to stdout,
and pushes a message packet into the async message stream.
------------------------------------------------------------------------
-Threading notes
+Threading Notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -161,7 +161,7 @@ For the most part, UHD is thread-safe.
Please observe the following limitations:
**Fast-path thread requirements:**
-There are three fast-path methods for a device: send(), recv(), and recv_async_msg().
+There are three fast-path methods for a device: **send()**, **recv()**, and **recv_async_msg()**.
All three methods are thread-safe and can be called from different thread contexts.
For performance, the user should call each method from a separate thread context.
These methods can also be used in a non-blocking fashion by using a timeout of zero.
@@ -169,7 +169,7 @@ These methods can also be used in a non-blocking fashion by using a timeout of z
**Slow-path thread requirements:**
It is safe to change multiple settings simultaneously. However,
this could leave the settings for a device in an uncertain state.
-The is because changing one setting could have an impact on how a call affects other settings.
+This is because changing one setting could have an impact on how a call affects other settings.
Example: setting the channel mapping affects how the antennas are set.
It is recommended to use at most one thread context for manipulating device settings.
@@ -177,23 +177,23 @@ It is recommended to use at most one thread context for manipulating device sett
Thread priority scheduling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-When the UHD spawns a new thread it may try to boost the thread's scheduling priority.
-When setting the priority fails, the UHD prints out an error.
-This error is harmless, it simply means that the thread will have a normal scheduling priority.
+When UHD spawns a new thread it may try to boost the thread's scheduling priority.
+When setting the priority fails, UHD prints out an error.
+This error is harmless; it simply means that the thread will have a normal scheduling priority.
**Linux Notes:**
Non-privileged users need special permission to change the scheduling priority.
-Add the following line to */etc/security/limits.conf*:
+Add the following line to **/etc/security/limits.conf**:
::
@<my_group> - rtprio 99
-Replace <my_group> with a group to which your user belongs.
-Settings will not take effect until the user has logged in and out.
+Replace **<my_group>** with a group to which your user belongs.
+Settings will not take effect until the user is in a different login session.
------------------------------------------------------------------------
-Misc notes
+Miscellaneous Notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -201,9 +201,9 @@ Support for dynamically loadable modules
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For a module to be loaded at runtime, it must be:
-* found in the UHD_MODULE_PATH environment variable,
-* installed into the <install-path>/share/uhd/modules directory,
-* or installed into /usr/share/uhd/modules directory (unix only).
+* found in the **UHD_MODULE_PATH** environment variable,
+* installed into the **<install-path>/share/uhd/modules** directory,
+* or installed into **/usr/share/uhd/modules** directory (UNIX only).
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Disabling or redirecting prints to stdout
@@ -211,7 +211,7 @@ Disabling or redirecting prints to stdout
The user can disable the UHD library from printing directly to stdout by registering a custom message handler.
The handler will intercept all messages, which can be dropped or redirected.
Only one handler can be registered at a time.
-Make "register_handler" your first call into UHD:
+Make **register_handler** your first call into UHD:
::
diff --git a/host/docs/gpsdo.rst b/host/docs/gpsdo.rst
index e84af8500..f5e6f5e57 100644
--- a/host/docs/gpsdo.rst
+++ b/host/docs/gpsdo.rst
@@ -11,11 +11,11 @@ to the Jackson Labs Firefly-1A device unless noted otherwise.
------------------------------------------------------------------------
Specifications
------------------------------------------------------------------------
-* Receiver type: 50 channel with WAAS, EGNOS, MSAS
-* 10MHz ADEV: 1e-11 over >24h
-* 1PPS RMS jitter: <50ns 1-sigma
-* Holdover: <11us over 3h
-* Phase noise:
+* **Receiver type**: 50 channel with WAAS, EGNOS, MSAS
+* **10MHz ADEV**: 1e-11 over >24h
+* **1PPS RMS jitter**: <50ns 1-sigma
+* **Holdover**: <11us over 3h
+* **Phase noise**:
* **1Hz:** -80dBc/Hz
* **10Hz:** -110dBc/Hz
@@ -25,25 +25,25 @@ Specifications
**Antenna Types:**
-The GPSDO is capable of supplying a 3V for active GPS antennas or supporting passive antennas
+The GPSDO is capable of supplying a 3V for active GPS antennas or supporting passive antennas.
------------------------------------------------------------------------
-Installation instructions
+Installation Instructions
------------------------------------------------------------------------
Installation instructions can be found here:
`www.ettus.com/downloads/gpsdo-kit.pdf <http://www.ettus.com/downloads/gpsdo-kit.pdf>`_
********************************************
-Post installation task (N-Series only)
+Post-installation Task (N-Series only)
********************************************
-This is necessary if you require absolute GPS time in your application,
+This is necessary if you require absolute GPS time in your application
or need to communicate with the GPSDO to obtain location, satellite info, etc.
-If you only require 10MHz and PPS signals for reference or MIMO use,
+If you only require 10MHz and PPS signals for reference or MIMO use
(see the `Synchronization Application Notes <./sync.html>`_),
it is not necessary to perform this step.
To configure the USRP to communicate with the GPSDO, use the
-usrp_burn_mb_eeprom utility:
+**usrp_burn_mb_eeprom** utility:
::
@@ -54,7 +54,7 @@ usrp_burn_mb_eeprom utility:
./usrp_burn_mb_eeprom --args=<optional device args> --key=gpsdo --val=none
------------------------------------------------------------------------
-Using the GPSDO in your application
+Using the GPSDO in Your Application
------------------------------------------------------------------------
By default, if a GPSDO is detected at startup, the USRP will be configured
to use it as a frequency and time reference. The internal VITA timestamp
@@ -62,8 +62,8 @@ will be initialized to the GPS time, and the internal oscillator will be
phase-locked to the 10MHz GPSDO reference. If the GPSDO is not locked to
satellites, the VITA time will not be initialized.
-GPS data is obtained through the mboard_sensors interface. To retrieve
-the current GPS time, use the "gps_time" sensor:
+GPS data is obtained through the **mboard_sensors** interface. To retrieve
+the current GPS time, use the **gps_time** sensor:
::
@@ -71,10 +71,10 @@ the current GPS time, use the "gps_time" sensor:
The returned value will be the current epoch time, in seconds since
January 1, 1970. This value is readily converted into human-readable
-format using the time.h library in C, boost::posix_time in C++, etc.
+format using the **time.h** library in C, **boost::posix_time** in C++, etc.
Other information can be fetched as well. You can query the lock status
-with the "gps_locked" sensor, as well as obtain raw NMEA sentences using
-the "gps_gpgsa", "gps_gprmc", and "gps_gpgga" sensors. Location
-information can be parsed out of the "gps_gpgga" sensor by using gpsd or
+with the **gps_locked** sensor, as well as obtain raw NMEA sentences using
+the **gps_gpgsa**, **gps_gprmc**, and **gps_gpgga** sensors. Location
+information can be parsed out of the **gps_gpgga** sensor by using **gpsd** or
another NMEA parser.
diff --git a/host/docs/identification.rst b/host/docs/identification.rst
index deda61531..a5e60e7f9 100644
--- a/host/docs/identification.rst
+++ b/host/docs/identification.rst
@@ -9,9 +9,9 @@ Identifying USRPs
------------------------------------------------------------------------
Devices are addressed through key/value string pairs.
These string pairs can be used to narrow down the search for a specific device or group of devices.
-Most UHD utility applications and examples have a --args parameter that takes a device address;
-where the device address is expressed as a delimited string.
-See the documentation in types/device_addr.hpp for reference.
+Most UHD utility applications and examples have an **--args** parameter that takes a device address, which is expressed as a delimited string.
+
+See the documentation in **types/device_addr.hpp** for reference.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Common device identifiers
@@ -33,8 +33,8 @@ Every device has several ways of identifying it on the host system:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Device discovery via command line
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Devices attached to your system can be discovered using the "uhd_find_devices" program.
-The find devices program scans your system for supported devices and prints
+Devices attached to your system can be discovered using the **uhd_find_devices** program.
+This program scans your system for supported devices and prints
out an enumerated list of discovered devices and their addresses.
The list of discovered devices can be narrowed down by specifying device address args.
@@ -55,14 +55,14 @@ Device address arguments can be supplied to narrow the scope of the search.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Device discovery through the API
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The device::find() API call searches for devices and returns a list of discovered devices.
+The **device::find()** API call searches for devices and returns a list of discovered devices.
::
uhd::device_addr_t hint; //an empty hint discovers all devices
uhd::device_addrs_t dev_addrs = uhd::device::find(hint);
-The hint argument can be populated to narrow the scope of the search.
+The **hint** argument can be populated to narrow the scope of the search.
::
@@ -79,9 +79,9 @@ The hint argument can be populated to narrow the scope of the search.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Device properties
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Properties of devices attached to your system can be probed with the "uhd_usrp_probe" program.
-The usrp probe program constructs an instance of the device and prints out its properties;
-properties such as detected daughter-boards, frequency range, gain ranges, etc...
+Properties of devices attached to your system can be probed with the **uhd_usrp_probe** program.
+This program constructs an instance of the device and prints out its properties,
+such as detected daughterboards, frequency range, gain ranges, etc...
**Usage:**
::
@@ -97,7 +97,7 @@ The USRP can then be identified via name, rather than a difficult to remember se
A name has the following properties:
* is composed of ASCII characters
-* is between 0 and 20 characters
+* is 0-20 characters
* is not required to be unique
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -114,7 +114,7 @@ Run the following commands:
Discovery via name
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The keyword "name" can be used to narrow the scope of the search.
+The keyword **name** can be used to narrow the scope of the search.
Example with the find devices utility:
::
diff --git a/host/docs/images.rst b/host/docs/images.rst
index a25268990..eaddfdf1d 100644
--- a/host/docs/images.rst
+++ b/host/docs/images.rst
@@ -8,7 +8,7 @@ UHD - Firmware and FPGA Image Application Notes
Images Overview
------------------------------------------------------------------------
Every USRP device must be loaded with special firmware and FPGA images.
-The methods of loading images into the device varies among devices:
+The methods of loading images into the device vary among devices:
* **USRP1:** The host code will automatically load the firmware and FPGA at runtime.
* **USRP2:** The user must manually write the images onto the USRP2 SD card.
@@ -17,10 +17,15 @@ The methods of loading images into the device varies among devices:
* **USRP-B Series:** The host code will automatically load the FPGA at runtime.
------------------------------------------------------------------------
-Pre-built images
+Pre-built Images
------------------------------------------------------------------------
Pre-built images are available for download.
+
+* `Master Branch images <http://files.ettus.com/binaries/master_images/>`_
+* `Maint Branch images <http://files.ettus.com/binaries/maint_images/>`_
+* `Next Branch images <http://files.ettus.com/binaries/next_images/>`_
+
See the UHD wiki for the download link.
The pre-built images come in two forms:
@@ -31,8 +36,9 @@ The pre-built images come in two forms:
^^^^^^^^^^^^^^^^^^^^^^
Platform installers
^^^^^^^^^^^^^^^^^^^^^^
-The UNIX-based installers will install the images into /usr/share/uhd/images.
-On windows, the images will be installed to <install-path>/share/uhd/images.
+The UNIX-based installers will install the images into **/usr/share/uhd/images**.
+
+The Windows installers will install the images into **C:/Program Files/UHD/share/uhd/images**.
^^^^^^^^^^^^^^^^^^^^^^
Archive install
@@ -42,52 +48,53 @@ When installing images from an archive, there are two options:
**Option 1:**
Unpack the archive into the UHD installation prefix.
-The UHD will always search <install-path>/share/uhd/images for image files.
-Where <install-path> was set by the CMAKE_INSTALL_PREFIX at configure-time.
+UHD will always search **<install-path>/share/uhd/images** for image files.
+Where **<install-path>** was set by the **CMAKE_INSTALL_PREFIX** at configure-time.
**Option 2:**
-Unpack the archive anywhere and set the UHD_IMAGE_PATH environment variable.
-The UHD_IMAGE_PATH may contain a list of directories to search for image files.
+Unpack the archive anywhere and set the **UHD_IMAGES_PATH** environment variable.
+**UHD_IMAGES_PATH** may contain a list of directories to search for image files.
------------------------------------------------------------------------
-Building images
+Building Images
------------------------------------------------------------------------
The UHD source repository comes with the source code necessary to build
both firmware and FPGA images for all supported devices.
-The build commands for a particular image can be found in <uhd-repo-path>/images/Makefile.
+
+The build commands for a particular image can be found in **<uhd-repo-path>/images/Makefile**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Xilinx FPGA builds
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Xilinx ISE 12.x and up is required to build the Xilinx FPGA images.
-The build requires that you have a unix-like environment with make.
-Make sure that xtclsh from the Xilinx ISE bin directory is in your $PATH.
+The build requires that you have a UNIX-like environment with **Make**.
+Make sure that **xtclsh** from the Xilinx ISE bin directory is in your **$PATH**.
-See <uhd-repo-path>/fpga/usrp2/top/*
+See **<uhd-repo-path>/fpga/usrp2/top/**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ZPU firmware builds
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ZPU GCC compiler is required to build the ZPU firmware images.
-The build requires that you have a unix-like environment with cmake and make.
-Make sure that zpu-elf-gcc is in your $PATH.
+The build requires that you have a UNIX-like environment with **CMake** and **Make**.
+Make sure that **zpu-elf-gcc** is in your **$PATH**.
-See <uhd-repo-path>/firmware/zpu
+See **<uhd-repo-path>/firmware/zpu**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Altera FPGA builds
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Quartus is required to build the Altera FPGA images.
-Pre-built images can also be found in <uhd-repo-path>/fpga/usrp1/rbf
+Pre-built images can also be found in **<uhd-repo-path>/fpga/usrp1/rbf**.
-See <uhd-repo-path>/fpga/usrp1/toplevel/*
+See **<uhd-repo-path>/fpga/usrp1/toplevel/***.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FX2 firmware builds
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The sdcc compiler is required to build the FX2 firmware images.
-The build requires that you have a unix-like environment with cmake and make.
+The SDCC compiler is required to build the FX2 firmware images.
+The build requires that you have a UNIX-like environment with **CMake** and **Make**.
-See <uhd-repo-path>/firmware/fx2
+See **<uhd-repo-path>/firmware/fx2**.
diff --git a/host/docs/index.rst b/host/docs/index.rst
index f881e8585..8649e7ce3 100644
--- a/host/docs/index.rst
+++ b/host/docs/index.rst
@@ -2,18 +2,20 @@
UHD - USRP Hardware Driver
========================================================================
-The UHD is the "Universal Software Radio Peripheral" hardware driver.
-The goal of the UHD is to provide a host driver and API for current and future Ettus Research products.
-Users will be able to use the UHD driver standalone or with 3rd party applications.
+UHD is the "Universal Software Radio Peripheral" hardware driver.
+The goal of UHD is to provide a host driver and API for current and future Ettus Research products.
+Users will be able to use the UHD driver standalone or with third-party applications.
------------------------------------------------------------------------
Contents
------------------------------------------------------------------------
-^^^^^^^^^^^^^^^^^^^^^
-Building the UHD
-^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Building and Installing UHD
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* `Build Guide <./build.html>`_
+* `Installation Guide (Linux) <http://code.ettus.com/redmine/ettus/projects/uhd/wiki/UHD_Linux>`_
+* `Installation Guide (Windows) <http://code.ettus.com/redmine/ettus/projects/uhd/wiki/UHD_Windows>`_
^^^^^^^^^^^^^^^^^^^^^
Application Notes
@@ -37,5 +39,4 @@ API Documentation
^^^^^^^^^^^^^^^^^^^^^
* `Doxygen <./../../doxygen/html/index.html>`_
* `Using the API <./coding.html>`_
-* `Device streaming <./stream.html>`_
-
+* `Device Streaming <./stream.html>`_
diff --git a/host/docs/stream.rst b/host/docs/stream.rst
index 9ffec22e5..13523c077 100644
--- a/host/docs/stream.rst
+++ b/host/docs/stream.rst
@@ -5,15 +5,15 @@ UHD - Device streaming
.. contents:: Table of Contents
------------------------------------------------------------------------
-Introduction to streaming
+Introduction to Streaming
------------------------------------------------------------------------
The concept of streaming refers to the transportation of samples between host and device.
A stream is an object that facilitates streaming between host application and device.
-A RX stream allows the user to receive samples from the device.
+An RX stream allows the user to receive samples from the device.
A TX stream allows the user to transmit samples to the device.
------------------------------------------------------------------------
-Link layer encapsulation
+Link Layer Encapsulation
------------------------------------------------------------------------
The VITA49 standard provides encapsulation for sample data across a link layer.
On all generation2 hardware, samples are encapsulated into VRT IF data packets.
@@ -22,12 +22,12 @@ Sample decoration is exposed to the user in the form of RX and TX metadata struc
The length of an IF data packet can be limited by several factors:
-* MTU of the link layer - network card, network switch
-* Buffering on the host - frame size in a ring buffer
-* Buffering on the device - size of BRAM FIFOs
+* **MTU of the link layer:** network card, network switch
+* **Buffering on the host:** frame size in a ring buffer
+* **Buffering on the device:** size of BRAM FIFOs
------------------------------------------------------------------------
-Data types
+Data Types
------------------------------------------------------------------------
There are two important data types to consider when streaming:
@@ -38,15 +38,15 @@ There are two important data types to consider when streaming:
The host/CPU data type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The host data type refers to the format of samples used in the host for baseband processing.
-Typically, the data type is complex baseband such as normalized complex-float32 or complex-int16.
+Typically, the data type is complex baseband such as normalized **complex-float32** or **complex-int16**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The link-layer data type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The link-layer or "over-the-wire" data type refers to the format of the samples sent through the link.
-Typically, this data type is complex-int16.
-However, To increase throughput over the link-layer,
-at the expense of precision, complex-int8 may be used.
+Typically, this data type is **complex-int16*.
+However, to increase throughput over the link-layer,
+at the expense of precision, **complex-int8** may be used.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Conversion
@@ -54,6 +54,6 @@ Conversion
The user may request arbitrary combinations of host and link data types;
however, not all combinations are supported.
The user may register custom data type formats and conversion routines.
-See uhd/convert.hpp for futher documentation.
+See **uhd/convert.hpp** for futher documentation.
-TODO provide example of convert API
+TODO: provide example of convert API
diff --git a/host/docs/sync.rst b/host/docs/sync.rst
index 55c9f81f0..4cf52e38d 100644
--- a/host/docs/sync.rst
+++ b/host/docs/sync.rst
@@ -12,13 +12,13 @@ or other applications requiring multiple USRPs operating synchronously.
which does not support the advanced features available in newer products.
------------------------------------------------------------------------
-Common reference signals
+Common Reference Signals
------------------------------------------------------------------------
USRPs take two reference signals in order to synchronize clocks and time:
* A 10MHz reference to provide a single frequency reference for both devices.
-* A pulse-per-second (1PPS) to synchronize the sample time across devices.
-* Or, the MIMO cable transmits an encoded time message from one device to another.
+* A pulse-per-second (PPS) to synchronize the sample time across devices.
+* A MIMO cable transmits an encoded time message from one device to another.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PPS and 10 MHz reference signals
@@ -36,7 +36,7 @@ However, some USRP models can provide these signals from an optional internal GP
Sometimes the delay on the PPS signal will cause it to arrive inside the timing
margin the FPGA sampling clock, causing PPS edges to be separated by less or
more than 100 million cycles of the FPGA clock. If this is the case,
-you can change the edge reference of the PPS signal with this special parameter:
+you can change the edge reference of the PPS signal with this parameter:
::
@@ -44,7 +44,7 @@ you can change the edge reference of the PPS signal with this special parameter:
**Note2:**
For users generating their own signals for the external SMA connectors,
-the pulse-per-second should be clocked from the 10MHz reference.
+the PPS should be clocked from the 10MHz reference.
See the application notes for your device for specific signal requirements.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,7 +52,7 @@ MIMO cable reference signals
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use the MIMO expansion cable to share reference sources (USRP2 and N-Series).
The MIMO cable can be used synchronize one device to another device.
-Users of the MIMO cable may use method 1 to synchronize multiple pairs of devices.
+Users of the MIMO cable may use Method 1 (explained below) to synchronize multiple pairs of devices.
::
@@ -60,13 +60,13 @@ Users of the MIMO cable may use method 1 to synchronize multiple pairs of device
usrp->set_time_source("mimo");
------------------------------------------------------------------------
-Synchronizing the device time
+Synchronizing the Device Time
------------------------------------------------------------------------
The purpose of the PPS signal is to synchronously latch a time into the device.
-You can use the set_time_next_pps(...) function to either initialize the sample time to 0,
-or to an absolute time such as GPS time or UTC time.
+You can use the **set_time_next_pps(...)** function to either initialize the sample time to 0
+or an absolute time, such as GPS time or UTC time.
For the purposes of synchronizing devices,
-it doesn't matter what time you initialize to when using set_time_next_pps(...).
+it doesn't matter what time you initialize to when using **set_time_next_pps(...)**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Method 1 - poll the USRP time registers
@@ -85,7 +85,7 @@ When the last PPS time increments, the user can determine that a PPS has occurre
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Method 2 - query the GPSDO for seconds
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Most GPSDO can be configured to output a NMEA string over the serial port once every PPS.
+Most GPSDOs can be configured to output a NMEA string over the serial port once every PPS.
The user can wait for this string to determine the PPS edge,
and the user can also parse this string to determine GPS time:
@@ -117,7 +117,7 @@ The slave device will automatically synchronize to the time on the master device
See the `MIMO Cable Application Notes <./usrp2.html#using-the-mimo-cable>`_ for more detail.
------------------------------------------------------------------------
-Synchronizing channel phase
+Synchronizing Channel Phase
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/host/docs/transport.rst b/host/docs/transport.rst
index 7dc465b4c..b136f3e87 100644
--- a/host/docs/transport.rst
+++ b/host/docs/transport.rst
@@ -17,7 +17,7 @@ that are known to perform well on a variety of systems.
The transport parameters are defined below for the various transports in the UHD:
------------------------------------------------------------------------
-UDP transport (sockets)
+UDP Transport (Sockets)
------------------------------------------------------------------------
The UDP transport is implemented with user-space sockets.
This means standard Berkeley sockets API using send()/recv().
@@ -33,15 +33,15 @@ The following parameters can be used to alter the transport's default behavior:
* **num_send_frames:** The number of send buffers to allocate
**Note1:**
-num_recv_frames does not affect performance.
+**num_recv_frames** does not affect performance.
**Note2:**
-num_send_frames does not affect performance.
+**num_send_frames** does not affect performance.
**Note3:**
-recv_frame_size and send_frame_size can be used to
+**recv_frame_size** and **send_frame_size** can be used to
increase or decrease the maximum number of samples per packet.
-The frame sizes default to an MTU of 1472 bytes per IP/UDP packet,
+The frame sizes default to an MTU of 1472 bytes per IP/UDP packet
and may be increased if permitted by your network hardware.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -58,8 +58,8 @@ The following mechanisms affect the transmission of periodic update packets:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Resize socket buffers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-It may be useful increase the size of the socket buffers to
-move the burden of buffering samples into the kernel, or to
+It may be useful to increase the size of the socket buffers to
+move the burden of buffering samples into the kernel or to
buffer incoming samples faster than they can be processed.
However, if your application cannot process samples fast enough,
no amount of buffering can save you.
@@ -74,7 +74,7 @@ The following parameters can be used to alter socket's buffer sizes:
Latency Optimization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Latency is a measurement of the time it takes a sample to travel between the host and device.
-Most computer hardware and software is bandwidth optimized which may negatively affect latency.
+Most computer hardware and software is bandwidth optimized, which may negatively affect latency.
If your application has strict latency requirements, please consider the following notes:
**Note1:**
@@ -92,7 +92,7 @@ Also, consult:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Linux specific notes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-On linux, the maximum buffer sizes are capped by the sysctl values
+On Linux, the maximum buffer sizes are capped by the sysctl values
**net.core.rmem_max** and **net.core.wmem_max**.
To change the maximum values, run the following commands:
::
@@ -100,7 +100,7 @@ To change the maximum values, run the following commands:
sudo sysctl -w net.core.rmem_max=<new value>
sudo sysctl -w net.core.wmem_max=<new value>
-Set the values permanently by editing */etc/sysctl.conf*
+Set the values permanently by editing **/etc/sysctl.conf**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Windows specific notes
@@ -112,10 +112,10 @@ FastSendDatagramThreshold registry key to change documented here:
* http://www.microsoft.com/windows/windowsmedia/howto/articles/optimize_web.aspx#appendix_e
------------------------------------------------------------------------
-USB transport (libusb)
+USB Transport (LibUSB)
------------------------------------------------------------------------
-The USB transport is implemented with libusb.
-Libusb provides an asynchronous API for USB bulk transfers.
+The USB transport is implemented with LibUSB.
+LibUSB provides an asynchronous API for USB bulk transfers.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Transport parameters
@@ -145,9 +145,9 @@ Install USB driver (Windows)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A driver package must be installed to use a USB-based product with UHD:
-* Download the driver from the UHD wiki page.
-* Unzip the file into a known location. We will refer to this as the <directory>.
-* Open the device manager and plug-in the USRP. You will see an unrecognized USB device in the device manager.
+* Download the driver from the UHD wiki page `here <http://files.ettus.com/binaries/misc/erllc_uhd_winusb_driver.zip>`_.
+* Unzip the file into a known location. We will refer to this as the **<directory>**.
+* Open the device manager and plug in the USRP. You will see an unrecognized USB device in the device manager.
* Right click on the unrecognized USB device and select update/install driver software (may vary for your OS).
-* In the driver installation wizard, select "browse for driver", browse to the <directory>, and select the .inf file.
+* In the driver installation wizard, select "browse for driver", browse to the **<directory>**, and select the **.inf** file.
* Continue through the installation wizard until the driver is installed.
diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst
index 597b5b17f..6242ccb6a 100644
--- a/host/docs/usrp1.rst
+++ b/host/docs/usrp1.rst
@@ -5,7 +5,7 @@ UHD - USRP1 Application Notes
.. contents:: Table of Contents
------------------------------------------------------------------------
-Specify a non-standard image
+Specify a Non-standard Image
------------------------------------------------------------------------
The standard USRP1 images installer comes with two FPGA images:
* **usrp1_fpga.rbf:** 2 DDCs + 2 DUCs
@@ -31,7 +31,7 @@ Example device address string representations to specify non-standard firmware a
fpga=usrp1_fpga_4rx.rbf, fw=usrp1_fw_custom.ihx
------------------------------------------------------------------------
-Missing and emulated features
+Missing and Emulated Features
------------------------------------------------------------------------
The USRP1 FPGA does not have the necessary space to support the advanced
streaming capabilities that are possible with the newer USRP devices.
@@ -53,7 +53,7 @@ List of emulated features
* Notification on broken chain error
**Note:**
-These emulated features rely on the host system's clock for timed operations,
+These emulated features rely on the host system's clock for timed operations
and therefore may not have sufficient precision for the application.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,17 +62,17 @@ List of missing features
* Start of burst flags for transmit/receive
------------------------------------------------------------------------
-Hardware setup notes
+Hardware Setup Notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
External clock modification
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The USRP can be modified to accept an external clock reference instead of the 64MHz onboard reference.
- * Solder SMA (LTI-SASF54GT) connector to J2001
- * Move 0 ohm 0603 resistor R2029 to R2030
- * Move 0.01uF 0603 capacitor C925 to C926
- * Remove 0.01uF 0603 capacitor C924
+ * Solder SMA (**LTI-SASF54GT**) connector to **J2001**.
+ * Move 0 ohm 0603 resistor **R2029** to **R2030**.
+ * Move 0.01uF 0603 capacitor **C925** to **C926**.
+ * Remove 0.01uF 0603 capacitor **C924**.
The new external clock needs to be a square wave between +7dBm and +15dBm
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index d81440b07..d70a08cd7 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -5,11 +5,11 @@ UHD - USRP2 and N Series Application Notes
.. contents:: Table of Contents
------------------------------------------------------------------------
-Load the images onto the SD card (USRP2 only)
+Load the Images onto the SD card (USRP2 only)
------------------------------------------------------------------------
**Warning!**
-Use the usrp2_card_burner.py with caution. If you specify the wrong device node,
-you could overwrite your hard drive. Make sure that --dev= specifies the SD card.
+Use **usrp2_card_burner.py** with caution. If you specify the wrong device node,
+you could overwrite your hard drive. Make sure that **--dev=** specifies the SD card.
**Warning!**
It is possible to use 3rd party SD cards with the USRP2.
@@ -21,7 +21,7 @@ However, certain types of SD cards will not interface with the CPLD:
For these reasons, we recommend that you use the SD card that was supplied with the USRP2.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Use the card burner tool (unix)
+Use the card burner tool (UNIX)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
@@ -33,19 +33,19 @@ Use the card burner tool (unix)
sudo ./usrp2_card_burner.py --dev=/dev/sd<XXX> --fpga=<path_to_fpga_image>
sudo ./usrp2_card_burner.py --dev=/dev/sd<XXX> --fw=<path_to_firmware_image>
-Use the *--list* option to get a list of possible raw devices.
+Use the **--list** option to get a list of possible raw devices.
The list result will filter out disk partitions and devices too large to be the sd card.
The list option has been implemented on Linux, Mac OS X, and Windows.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Use the card burner tool (windows)
+Use the card burner tool (Windows)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
<path_to_python.exe> <install-path>/share/uhd/utils/usrp2_card_burner_gui.py
------------------------------------------------------------------------
-Load the images onto the on-board flash (USRP-N Series only)
+Load the Images onto the On-board Flash (USRP-N Series only)
------------------------------------------------------------------------
The USRP-N Series can be reprogrammed over the network
to update or change the firmware and FPGA images.
@@ -58,7 +58,7 @@ Determine the revision number from the sticker on the rear of the chassis.
Use this number to select the correct FPGA image for your device.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Use the net burner tool (unix)
+Use the net burner tool (UNIX)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
@@ -88,22 +88,22 @@ The safe-mode button is a pushbutton switch (S2) located inside the enclosure.
To boot into the safe image, hold-down the safe-mode button while power-cycling the device.
Continue to hold-down the button until the front-panel LEDs blink and remain solid.
-When in safe-mode, the USRP-N device will always have the IP address 192.168.10.2
+When in safe-mode, the USRP-N device will always have the IP address **192.168.10.2**.
------------------------------------------------------------------------
-Setup networking
+Setup Networking
------------------------------------------------------------------------
-The USRP2 only supports gigabit ethernet,
+The USRP2 only supports Gigabit Ethernet
and will not work with a 10/100 Mbps interface.
However, a 10/100 Mbps interface can be connected indirectly
-to a USRP2 through a gigabit ethernet switch.
+to a USRP2 through a Gigabit Ethernet switch.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Setup the host interface
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The USRP2 communicates at the IP/UDP layer over the gigabit ethernet.
-The default IP address of the USRP2 is **192.168.10.2**
-You will need to configure the host's ethernet interface with a static IP
+The default IP address of the USRP2 is **192.168.10.2**.
+You will need to configure the host's Ethernet interface with a static IP
address to enable communication. An address of **192.168.10.1** and a subnet
mask of **255.255.255.0** is recommended.
@@ -113,15 +113,15 @@ On a Linux system, you can set a static IP address very easily by using the
sudo ifconfig <interface> 192.168.10.1
-Note that <interface> is usually something like 'eth0'. You can discover the
-names of the network interfaces in your computer by running 'ifconfig' without
+Note that **<interface>** is usually something like **eth0**. You can discover the
+names of the network interfaces in your computer by running **ifconfig** without
any parameters:
::
ifconfig -a
**Note:**
-When using the UHD, if an IP address for the USRP2 is not specified,
+When using UHD, if an IP address for the USRP2 is not specified,
the software will use UDP broadcast packets to locate the USRP2.
On some systems, the firewall will block UDP broadcast packets.
It is recommended that you change or disable your firewall settings.
@@ -129,23 +129,23 @@ It is recommended that you change or disable your firewall settings.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Multiple devices per host
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-For maximum throughput, one ethernet interface per USRP2 is recommended,
-although multiple devices may be connected via a gigabit ethernet switch.
-In any case, each ethernet interface should have its own subnet,
+For maximum throughput, one Ethernet interface per USRP2 is recommended,
+although multiple devices may be connected via a Gigabit Ethernet switch.
+In any case, each Ethernet interface should have its own subnet,
and the corresponding USRP2 device should be assigned an address in that subnet.
Example:
**Configuration for USRP2 device 0:**
-* Ethernet interface IPv4 address: 192.168.10.1
-* Ethernet interface subnet mask: 255.255.255.0
-* USRP2 device IPv4 address: 192.168.10.2
+* Ethernet interface IPv4 address: **192.168.10.1**
+* Ethernet interface subnet mask: **255.255.255.0**
+* USRP2 device IPv4 address: **192.168.10.2**
**Configuration for USRP2 device 1:**
-* Ethernet interface IPv4 address: 192.168.20.1
-* Ethernet interface subnet mask: 255.255.255.0
-* USRP2 device IPv4 address: 192.168.20.2
+* Ethernet interface IPv4 address: **192.168.20.1**
+* Ethernet interface subnet mask: **255.255.255.0**
+* USRP2 device IPv4 address: **192.168.20.2**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Change the USRP2's IP address
@@ -157,7 +157,7 @@ You may need to change the USRP2's IP address for several reasons:
* to set a known IP address into USRP2 (in case you forgot)
**Method 1:**
-To change the USRP2's IP address
+To change the USRP2's IP address,
you must know the current address of the USRP2,
and the network must be setup properly as described above.
Run the following commands:
@@ -168,7 +168,7 @@ Run the following commands:
**Method 2 (Linux Only):**
This method assumes that you do not know the IP address of your USRP2.
-It uses raw ethernet packets to bypass the IP/UDP layer to communicate with the USRP2.
+It uses raw Ethernet packets to bypass the IP/UDP layer to communicate with the USRP2.
Run the following commands:
::
@@ -176,23 +176,23 @@ Run the following commands:
sudo ./usrp2_recovery.py --ifc=eth0 --new-ip=192.168.10.3
------------------------------------------------------------------------
-Communication problems
+Communication Problems
------------------------------------------------------------------------
When setting up a development machine for the first time,
you may have various difficulties communicating with the USRP device.
-The following tips are designed to help narrow-down and diagnose the problem.
+The following tips are designed to help narrow down and diagnose the problem.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: no control response
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a common error that occurs when you have set the subnet of your network
interface to a different subnet than the network interface of the USRP. For
-example, if your network interface is set to 192.168.20.1, and the USRP is
-192.168.10.2 (note the difference in the third numbers of the IP addresses), you
+example, if your network interface is set to **192.168.20.1**, and the USRP is
+**192.168.10.2** (note the difference in the third numbers of the IP addresses), you
will likely see a 'no control response' error message.
Fixing this is simple - just set the your host PC's IP address to the same
-subnet as your USRP. Instructions for setting your IP address are in the
+subnet as that of your USRP. Instructions for setting your IP address are in the
previous section of this documentation.
@@ -200,19 +200,19 @@ previous section of this documentation.
Firewall issues
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the IP address is not specified,
-the device discovery sends broadcast UDP packets from each ethernet interface.
+the device discovery broadcasts UDP packets from each ethernet interface.
Many firewalls will block the replies to these broadcast packets.
-If disabling your system's firewall,
-or specifying the IP address yeilds a discovered device,
+If disabling your system's firewall
+or specifying the IP address yields a discovered device,
then your firewall may be blocking replies to UDP broadcast packets.
-If this is the case, we recommend that you disable the firewall,
-or create a rule to allow all incoming packets with UDP source port 49152.
+If this is the case, we recommend that you disable the firewall
+or create a rule to allow all incoming packets with UDP source port **49152**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ping the device
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The USRP will reply to icmp echo requests.
-A successful ping response means that the device has booted properly,
+The USRP will reply to ICMP echo requests.
+A successful ping response means that the device has booted properly
and that it is using the expected IP address.
::
@@ -222,12 +222,12 @@ and that it is using the expected IP address.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Monitor the serial output
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Read the serial port to get debug verbose from the embedded microcontroller.
+Read the serial port to get debug verbose output from the embedded microcontroller.
The microcontroller prints useful information about IP addresses,
MAC addresses, control packets, fast-path settings, and bootloading.
Use a standard USB to 3.3v-level serial converter at 230400 baud.
-Connect GND to the converter ground, and connect TXD to the converter receive.
-The RXD pin can be left unconnected as this is only a one-way communication.
+Connect **GND** to the converter ground, and connect **TXD** to the converter receive.
+The **RXD** pin can be left unconnected as this is only a one-way communication.
* **USRP2:** Serial port located on the rear edge
* **N210:** Serial port located on the left side
@@ -235,10 +235,10 @@ The RXD pin can be left unconnected as this is only a one-way communication.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Monitor the host network traffic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Use wireshark to monitor packets sent to and received from the device.
+Use Wireshark to monitor packets sent to and received from the device.
------------------------------------------------------------------------
-Addressing the device
+Addressing the Device
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -248,9 +248,9 @@ In a single-device configuration,
the USRP device must have a unique IPv4 address on the host computer.
The USRP can be identified through its IPv4 address, resolvable hostname, or by other means.
See the application notes on `device identification <./identification.html>`_.
-Use this addressing scheme with the *single_usrp* interface.
+Use this addressing scheme with the **single_usrp** interface.
-Example device address string representation for a USRP2 with IPv4 address 192.168.10.2
+Example device address string representation for a USRP2 with IPv4 address **192.168.10.2**:
::
@@ -263,12 +263,12 @@ In a multi-device configuration,
each USRP device must have a unique IPv4 address on the host computer.
The device address parameter keys must be suffixed with the device index.
Each parameter key should be of the format <key><index>.
-Use this addressing scheme with the *multi_usrp* interface.
+Use this addressing scheme with the **multi_usrp** interface.
* The order in which devices are indexed corresponds to the indexing of the transmit and receive channels.
* The key indexing provides the same granularity of device identification as in the single device case.
-Example device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 and 192.168.20.2
+Example device address string representation for 2 USRP2s with IPv4 addresses **192.168.10.2** and **192.168.20.2**:
::
addr0=192.168.10.2, addr1=192.168.20.2
@@ -277,31 +277,31 @@ Example device address string representation for 2 USRP2s with IPv4 addresses 19
Using the MIMO Cable
------------------------------------------------------------------------
The MIMO cable allows two USRP devices to share reference clocks,
-time synchronization, and the ethernet interface.
-One of the devices will sink its clock and time references to the MIMO cable.
+time synchronization, and the Ethernet interface.
+One of the devices will sync its clock and time references to the MIMO cable.
This device will be referred to as the slave, and the other device, the master.
* The slave device acquires the clock and time references from the master device.
* The master and slave may be used individually or in a multi-device configuration.
-* External clocking is optional, and should only be supplied to the master device.
+* External clocking is optional and should only be supplied to the master device.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Shared ethernet mode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-In shared ethernet mode,
-only one device in the configuration can be attached to the ethernet.
+In shared Ethernet mode,
+only one device in the configuration can be attached to the Tthernet.
* Clock reference, time reference, and data are communicated over the MIMO cable.
-* Both master and slave must have different IPv4 addresses in the same subnet.
+* Master and slave must have different IPv4 addresses in the same subnet.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dual ethernet mode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-In dual ethernet mode,
-both devices in the configuration must be attached to the ethernet.
+In dual Ethernet mode,
+both devices in the configuration must be attached to the Ethernet.
* Only clock reference and time reference are communicated over the MIMO cable.
-* Both master and slave must have different IPv4 addresses in different subnets.
+* The master and slave must have different IPv4 addresses in different subnets.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Configuring the slave
@@ -315,8 +315,57 @@ the following clock configuration must be set on the slave device:
clock_config.pps_source = uhd::clock_config_t::PPS_MIMO;
usrp->set_clock_config(clock_config, slave_index);
+
+------------------------------------------------------------------------
+Alternative stream destination
+------------------------------------------------------------------------
+It is possible to program the USRP to send RX packets to an alternative IP/UDP destination.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Set the subnet and gateway
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+To use an alternative streaming destination,
+the device needs to be able to determine if the destination address
+is within its subnet, and ARP appropriately.
+Therefore, the user should ensure that subnet and gateway addresses
+have been programmed into the device's EEPROM.
+
+Run the following commands:
+::
+
+ cd <install-path>/share/uhd/utils
+ ./usrp_burn_mb_eeprom --args=<optional device args> --key=subnet --val=255.255.255.0
+ ./usrp_burn_mb_eeprom --args=<optional device args> --key=gateway --val=192.168.10.1
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Create a receive streamer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Set the stream args "addr" and "port" values to the alternative destination.
+Packets will be sent to this destination when the user issues a stream command.
+
+::
+
+ //create a receive streamer, host type does not matter
+ uhd::stream_args_t stream_args("fc32");
+
+ //resolvable address and port for a remote udp socket
+ stream_args.args["addr"] = "192.168.10.42";
+ stream_args.args["port"] = "12345";
+
+ //create the streamer
+ uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
+
+ //issue stream command
+ uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
+ stream_cmd.num_samps = total_num_samps;
+ stream_cmd.stream_now = true;
+ usrp->issue_stream_cmd(stream_cmd);
+
+**Note:**
+Calling recv() on this streamer object should yield a timeout.
+
------------------------------------------------------------------------
-Hardware setup notes
+Hardware Setup Notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -336,8 +385,8 @@ The LEDs reveal the following about the state of the device:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ref Clock - 10MHz
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Using an external 10MHz reference clock, square wave will offer the best phase
-noise performance, but sinusoid is acceptable. The reference clock requires the following power level:
+Using an external 10MHz reference clock, a square wave will offer the best phase
+noise performance, but a sinusoid is acceptable. The reference clock requires the following power level:
* **USRP2** 5 to 15dBm
* **N2XX** 0 to 15dBm
@@ -353,7 +402,7 @@ Using a PPS signal for timestamp synchronization requires a square wave signal w
Test the PPS input with the following app:
-* <args> are device address arguments (optional if only one USRP is on your machine)
+* **<args>** are device address arguments (optional if only one USRP is on your machine)
::
@@ -376,8 +425,8 @@ Available Sensors
The following sensors are available for the USRP2/N-Series motherboards;
they can be queried through the API.
-* mimo_locked - clock reference locked over the MIMO cable
-* ref_locked - clock reference locked (internal/external)
+* **mimo_locked** - clock reference locked over the MIMO cable
+* **ref_locked** - clock reference locked (internal/external)
* other sensors are added when the GPSDO is enabled
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -386,13 +435,13 @@ Multiple RX channels
There are two complete DDC chains in the FPGA.
In the single channel case, only one chain is ever used.
To receive from both channels,
-the user must set the RX subdevice specification.
+the user must set the **RX** subdevice specification.
This hardware has only one daughterboard slot,
-which has been aptly named slot "A".
+which has been aptly named slot **A**.
In the following example, a TVRX2 is installed.
-Channel 0 is sourced from subdevice RX1,
-channel 1 is sourced from subdevice RX2:
+Channel 0 is sourced from subdevice **RX1**,
+and channel 1 is sourced from subdevice **RX2**:
::
usrp->set_rx_subdev_spec("A:RX1 A:RX2");
diff --git a/host/docs/usrp_b1xx.rst b/host/docs/usrp_b1xx.rst
index 564fb89be..b38936021 100644
--- a/host/docs/usrp_b1xx.rst
+++ b/host/docs/usrp_b1xx.rst
@@ -5,10 +5,10 @@ UHD - USRP-B1XX Series Application Notes
.. contents:: Table of Contents
------------------------------------------------------------------------
-Specify a non-standard image
+Specify a Non-standard Image
------------------------------------------------------------------------
-The UHD will automatically select the USRP B-Series images from the installed images package.
-The image selection can be overridden with the "fpga" and "fw" device address parameters.
+UHD will automatically select the USRP B-Series images from the installed images package.
+The image selection can be overridden with the **--fpga=** and **--fw=** device address parameters.
Example device address string representations to specify non-standard images:
@@ -21,37 +21,37 @@ Example device address string representations to specify non-standard images:
fw=usrp_b100_fw_firmware.ihx
------------------------------------------------------------------------
-Changing the master clock rate
+Changing the Master Clock Rate
------------------------------------------------------------------------
The master clock rate of the USRP embedded feeds both the FPGA DSP and the codec chip.
Hundreds of rates between 32MHz and 64MHz are available.
A few notable rates are:
-* 64MHz - maximum rate of the codec chip
-* 61.44MHz - good for UMTS/WCDMA applications
-* 52Mhz - good for GSM applications
+* **64MHz:** maximum rate of the codec chip
+* **61.44MHz:** good for UMTS/WCDMA applications
+* **52Mhz:** good for GSM applications
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set 61.44MHz - uses external VCXO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To use the 61.44MHz clock rate, the USRP embedded will require two jumpers to be moved.
-* J16 is a two pin header, remove the jumper (or leave it on pin1 only)
-* J15 is a three pin header, move the jumper to (pin1, pin2)
+* **J16** is a two pin header, remove the jumper (or leave it on pin1 only)
+* **J15** is a three pin header, move the jumper to (pin1, pin2)
-**Note:** See instructions below to communicate the desired clock rate into the UHD.
+**Note:** See instructions below to communicate the desired clock rate into UHD.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set other rates - uses internal VCO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To use other clock rates, the jumpers will need to be in the default position.
-* J16 is a two pin header, move the jumper to (pin1, pin2)
-* J15 is a three pin header, move the jumper to (pin2, pin3)
+* **J16** is a two pin header, move the jumper to (pin1, pin2)
+* **J15** is a three pin header, move the jumper to (pin2, pin3)
-To communicate the desired clock rate into the UHD,
+To communicate the desired clock rate into UHD,
specify the a special device address argument,
-where the key is "master_clock_rate" and the value is a rate in Hz.
+where the key is **master_clock_rate** and the value is a rate in Hz.
Example:
::
@@ -84,4 +84,4 @@ Available Sensors
The following sensors are available;
they can be queried through the API.
-* ref_locked - clock reference locked (internal/external)
+* **ref_locked:** clock reference locked (internal/external)
diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst
index ef1e22b3a..31a47347f 100644
--- a/host/docs/usrp_e1xx.rst
+++ b/host/docs/usrp_e1xx.rst
@@ -5,11 +5,11 @@ UHD - USRP-E1XX Series Application Notes
.. contents:: Table of Contents
------------------------------------------------------------------------
-Specify a non-standard image
+Specify a Non-standard Image
------------------------------------------------------------------------
UHD will automatically select the USRP-Embedded FPGA image from the
installed images package. The FPGA image selection can be overridden with the
-"fpga" device address parameter.
+**--fpga=** device address parameter.
Example device address string representations to specify non-standard FPGA
image:
@@ -19,15 +19,15 @@ image:
fpga=usrp_e100_custom.bin
------------------------------------------------------------------------
-Changing the master clock rate
+Changing the Master Clock Rate
------------------------------------------------------------------------
The master clock rate of the USRP-Embedded feeds both the FPGA DSP and the codec
chip. Hundreds of rates between 32MHz and 64MHz are available. A few notable
rates are:
-* 64MHz - maximum rate of the codec chip
-* 61.44MHz - good for UMTS/WCDMA applications
-* 52Mhz - good for GSM applications
+* **64MHz:** maximum rate of the codec chip
+* **61.44MHz:** good for UMTS/WCDMA applications
+* **52Mhz:** good for GSM applications
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set 61.44MHz - uses external VCXO
@@ -35,23 +35,22 @@ Set 61.44MHz - uses external VCXO
To use the 61.44MHz clock rate with the USRP-Embedded, two jumpers must be moved
on the device.
-* J16 is a two pin header, remove the jumper (or leave it on pin1 only)
-* J15 is a three pin header, move the jumper to (pin1, pin2)
+* **J16** is a two pin header; remove the jumper (or leave it on pin1 only).
+* **J15** is a three pin header; move the jumper to (pin1, pin2).
-**Note:** See instructions below to communicate the desired clock rate into the
-UHD.
+**Note:** See instructions below to communicate the desired clock rate UHD.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set other rates - uses internal VCO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To use other clock rates, the jumpers will need to be in the default position.
-* J16 is a two pin header, move the jumper to (pin1, pin2)
-* J15 is a three pin header, move the jumper to (pin2, pin3)
+* **J16** is a two pin header; move the jumper to (pin1, pin2).
+* **J15** is a three pin header; move the jumper to (pin2, pin3).
-To communicate the desired clock rate into the UHD,
+To communicate the desired clock rate into UHD,
specify the a special device address argument,
-where the key is "master_clock_rate" and the value is a rate in Hz.
+where the key is **master_clock_rate** and the value is a rate in Hz.
Example:
::
@@ -66,15 +65,15 @@ Clock Synchronization
Ref Clock - 10MHz
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The E1xx has a 10MHz TCXO which can be used to discipline the flexible clocking
-by selecting REF_INT for the clock_config_t.
+by selecting **REF_INT** for the **clock_config_t**.
Alternately, an external 10MHz reference clock can be supplied by soldering
a connector.
-* Connector J10 (REF_IN) needs MCX connector WM5541-ND or similar
-* Square wave will offer the best phase noise performance, but sinusoid is acceptable
-* Power level: 0 to 15dBm
-* Select REF_SMA in clock_config_t
+* Connector **J10** (REF_IN) needs MCX connector **WM5541-ND** or similar.
+* Square wave will offer the best phase noise performance, but sinusoid is acceptable.
+* **Power level:** 0 to 15dBm
+* Select **REF_SMA** in **clock_config_t**.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -83,13 +82,13 @@ PPS - Pulse Per Second
An exteral PPS signal for timestamp synchronization can be supplied by soldering
a connector.
-* Connector J13 (PPS) needs MCX connector WM5541-ND or similar
-* Requires a square wave signal
-* Amplitude: 3.3 to 5Vpp
+* Connector **J13** (PPS) needs MCX connector **WM5541-ND** or similar.
+* Requires a square wave signal.
+* **Amplitude:** 3.3 to 5Vpp
Test the PPS input with the following app:
-* <args> are device address arguments (optional if only one USRP is on your machine)
+* **<args** are device address arguments (optional if only one USRP is on your machine).
::
@@ -106,7 +105,7 @@ UHD will always try to detect an installed GPSDO at runtime.
There is not a special EEPROM value to burn for GPSDO detection.
------------------------------------------------------------------------
-Hardware setup notes
+Hardware Setup Notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -132,5 +131,5 @@ Available Sensors
The following sensors are available;
they can be queried through the API.
-* ref_locked - clock reference locked (internal/external)
+* **ref_locked:** clock reference locked (internal/external)
* other sensors are added when the GPSDO is enabled
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
index 3c9a3880a..b41d53d11 100644
--- a/host/examples/CMakeLists.txt
+++ b/host/examples/CMakeLists.txt
@@ -27,6 +27,7 @@ SET(example_sources
rx_timed_samples.cpp
test_messages.cpp
test_pps_input.cpp
+ transport_hammer.cpp
tx_bursts.cpp
tx_samples_from_file.cpp
tx_timed_samples.cpp
diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp
index 8f00e25de..8a000f6c3 100644
--- a/host/examples/benchmark_rate.cpp
+++ b/host/examples/benchmark_rate.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 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
@@ -16,6 +16,7 @@
//
#include <uhd/utils/thread_priority.hpp>
+#include <uhd/convert.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <boost/program_options.hpp>
@@ -40,11 +41,13 @@ unsigned long long num_seq_errors = 0;
/***********************************************************************
* Benchmark RX Rate
**********************************************************************/
-void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_otw){
+void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_cpu, const std::string &rx_otw){
uhd::set_thread_priority_safe();
//create a receive streamer
- uhd::stream_args_t stream_args("fc32", rx_otw); //complex floats
+ uhd::stream_args_t stream_args(rx_cpu, rx_otw);
+ for (size_t ch = 0; ch < usrp->get_num_mboards(); ch++) //linear channel mapping
+ stream_args.channels.push_back(ch);
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
//print pre-test summary
@@ -55,16 +58,20 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_o
//setup variables and allocate buffer
uhd::rx_metadata_t md;
const size_t max_samps_per_packet = rx_stream->get_max_num_samps();
- std::vector<std::complex<float> > buff(max_samps_per_packet);
+ std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(rx_cpu));
+ std::vector<void *> buffs;
+ for (size_t ch = 0; ch < stream_args.channels.size(); ch++)
+ buffs.push_back(&buff.front()); //same buffer for each channel
bool had_an_overflow = false;
uhd::time_spec_t last_time;
const double rate = usrp->get_rx_rate();
- usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
+ uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
+ cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05);
+ cmd.stream_now = (buffs.size() == 1);
+ usrp->issue_stream_cmd(cmd);
while (not boost::this_thread::interruption_requested()){
- num_rx_samps += rx_stream->recv(
- &buff.front(), buff.size(), md
- );
+ num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md);
//handle the error codes
switch(md.error_code){
@@ -94,11 +101,13 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_o
/***********************************************************************
* Benchmark TX Rate
**********************************************************************/
-void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &tx_otw){
+void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &tx_cpu, const std::string &tx_otw){
uhd::set_thread_priority_safe();
//create a transmit streamer
- uhd::stream_args_t stream_args("fc32", tx_otw); //complex floats
+ uhd::stream_args_t stream_args(tx_cpu, tx_otw);
+ for (size_t ch = 0; ch < usrp->get_num_mboards(); ch++) //linear channel mapping
+ stream_args.channels.push_back(ch);
uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);
//print pre-test summary
@@ -108,17 +117,22 @@ void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &tx_o
//setup variables and allocate buffer
uhd::tx_metadata_t md;
- md.has_time_spec = false;
+ md.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05);
const size_t max_samps_per_packet = tx_stream->get_max_num_samps();
- std::vector<std::complex<float> > buff(max_samps_per_packet);
+ std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(tx_cpu));
+ std::vector<const void *> buffs;
+ for (size_t ch = 0; ch < stream_args.channels.size(); ch++)
+ buffs.push_back(&buff.front()); //same buffer for each channel
+ md.has_time_spec = (buffs.size() != 1);
while (not boost::this_thread::interruption_requested()){
- num_tx_samps += tx_stream->send(&buff.front(), buff.size(), md);
+ num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md);
+ md.has_time_spec = false;
}
//send a mini EOB packet
md.end_of_burst = true;
- tx_stream->send("", 0, md);
+ tx_stream->send(buffs, 0, md);
}
void benchmark_tx_rate_async_helper(uhd::usrp::multi_usrp::sptr usrp){
@@ -163,6 +177,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
double duration;
double rx_rate, tx_rate;
std::string rx_otw, tx_otw;
+ std::string rx_cpu, tx_cpu;
+ std::string mode;
//setup the program options
po::options_description desc("Allowed options");
@@ -174,6 +190,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("tx_rate", po::value<double>(&tx_rate), "specify to perform a TX rate test (sps)")
("rx_otw", po::value<std::string>(&rx_otw)->default_value("sc16"), "specify the over-the-wire sample mode for RX")
("tx_otw", po::value<std::string>(&tx_otw)->default_value("sc16"), "specify the over-the-wire sample mode for TX")
+ ("rx_cpu", po::value<std::string>(&rx_cpu)->default_value("fc32"), "specify the host/cpu sample mode for RX")
+ ("tx_cpu", po::value<std::string>(&tx_cpu)->default_value("fc32"), "specify the host/cpu sample mode for TX")
+ ("mode", po::value<std::string>(&mode)->default_value("none"), "multi-channel sync mode option: none, mimo")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
@@ -201,18 +220,24 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
+ if (mode == "mimo"){
+ usrp->set_clock_source("mimo", 0);
+ usrp->set_time_source("mimo", 0);
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ }
+
boost::thread_group thread_group;
//spawn the receive test thread
if (vm.count("rx_rate")){
usrp->set_rx_rate(rx_rate);
- thread_group.create_thread(boost::bind(&benchmark_rx_rate, usrp, rx_otw));
+ thread_group.create_thread(boost::bind(&benchmark_rx_rate, usrp, rx_cpu, rx_otw));
}
//spawn the transmit test thread
if (vm.count("tx_rate")){
usrp->set_tx_rate(tx_rate);
- thread_group.create_thread(boost::bind(&benchmark_tx_rate, usrp, tx_otw));
+ thread_group.create_thread(boost::bind(&benchmark_tx_rate, usrp, tx_cpu, tx_otw));
thread_group.create_thread(boost::bind(&benchmark_tx_rate_async_helper, usrp));
}
diff --git a/host/examples/transport_hammer.cpp b/host/examples/transport_hammer.cpp
new file mode 100644
index 000000000..597614050
--- /dev/null
+++ b/host/examples/transport_hammer.cpp
@@ -0,0 +1,340 @@
+//
+// Copyright 2012 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/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/usrp/multi_usrp.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <iostream>
+#include <complex>
+
+namespace po = boost::program_options;
+
+/************************************************************************
+ * RX Samples
+ ************************************************************************/
+
+void rx_hammer(uhd::usrp::multi_usrp::sptr usrp, double rx_rate, bool rx_rand, int rx_low, int rx_high, int rx_step, bool verbose){
+ uhd::set_thread_priority_safe();
+
+ //Set RX sample rate
+ std::cout << boost::format("Setting RX rate: %f Msps") % (rx_rate/1e6) << std::endl;
+ usrp->set_rx_rate(rx_rate);
+ std::cout << boost::format("Actual RX rate: %f Msps") % (usrp->get_rx_rate()/1e6) << std::endl << std::endl;
+
+ if(rx_rand){
+ std::srand((unsigned int) time(NULL));
+
+ while(true){
+ size_t total_num_samps = (rand() % (rx_high - rx_low)) + rx_low;
+
+ usrp->set_time_now(uhd::time_spec_t(0.0));
+
+ //Create a receive streamer
+ uhd::stream_args_t stream_args("fc32");
+ uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
+
+ std::cout << boost::format("About to receive %u samples.") % total_num_samps << std::endl;
+
+ uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
+ stream_cmd.num_samps = total_num_samps;
+ stream_cmd.stream_now = true;
+ usrp->issue_stream_cmd(stream_cmd);
+
+ //Metadata will be filled in by recv()
+ uhd::rx_metadata_t md;
+
+ //Allocate buffer to receive with samples
+ std::vector<std::complex<float> > buff(rx_stream->get_max_num_samps());
+ double timeout = 1;
+
+ size_t num_acc_samps = 0; //Number of accumulated samples
+ while(num_acc_samps < total_num_samps){
+ //Receive a single packet
+ size_t num_rx_samps = rx_stream->recv(
+ &buff.front(), buff.size(), md, timeout, true
+ );
+
+ //Handle the error code
+ if(md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){std::cout << "timeout" << std::endl; break;}
+ if(md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE && md.error_code != uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){
+ std::cout << "Error" << std::endl;
+ throw std::runtime_error(str(boost::format(
+ "Unexpected error code 0x%x"
+ ) % md.error_code));
+ }
+ num_acc_samps += num_rx_samps;
+ }
+
+ if(num_acc_samps < total_num_samps) std::cerr << "Received timeout before all samples were received..." << std::endl;
+ else std::cout << boost::format("Successfully received %u samples.") % total_num_samps << std::endl;
+ }
+ }
+ else{
+ for(int i = int(rx_low); i <= int(rx_high); i += rx_step){
+ usrp->set_time_now(uhd::time_spec_t(0.0));
+
+ //Create a receive streamer
+ uhd::stream_args_t stream_args("fc32");
+ uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
+
+ //Set up streaming
+ std::cout << boost::format ("About to receive %u samples.") % i << std::endl;
+ uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
+ stream_cmd.num_samps = i;
+ stream_cmd.stream_now = true;
+ usrp->issue_stream_cmd(stream_cmd);
+
+ //Metadata will be filled in by recv()
+ uhd::rx_metadata_t md;
+
+ //Allocate buffer to receive with samples
+ std::vector<std::complex<float> > buff(rx_stream->get_max_num_samps());
+
+ double timeout = 1;
+
+ size_t num_acc_samps = 0; //Number of accumulated samples
+ while(int(num_acc_samps) < i){
+ //Receive a single packet
+ size_t num_rx_samps = rx_stream->recv(
+ &buff.front(), buff.size(), md, timeout, true
+ );
+
+ //Handle the error code
+ if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break;
+ if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE && md.error_code != uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){
+ throw std::runtime_error(str(boost::format(
+ "Unexpected error code 0x%x"
+ ) % md.error_code));
+ }
+
+ if(verbose) std::cout << boost::format("Received %u samples.") % num_rx_samps << std::endl;
+
+ num_acc_samps += num_rx_samps;
+
+ }
+ std::cout << boost::format("Successfully received %u samples.") % i << std::endl;
+
+ if (int(num_acc_samps) < i) std::cerr << "Timeout received before all samples were received..." << std::endl;
+
+ }
+ }
+}
+
+/************************************************************************
+ * TX Samples
+ ************************************************************************/
+
+void tx_hammer(uhd::usrp::multi_usrp::sptr usrp, double tx_rate, bool tx_rand, int tx_low, int tx_high, int tx_step, double tx_ampl, bool verbose){
+ uhd::set_thread_priority_safe();
+
+ //Set the TX sample rate
+ std::cout << boost::format("Setting TX Rate: %f Msps...") % (tx_rate / 1e6) << std::endl;
+ usrp->set_tx_rate(tx_rate);
+ std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl;
+ usrp->set_time_now(uhd::time_spec_t(0.0));
+
+ //Create a transmit streamer
+ uhd::stream_args_t stream_args("fc32"); //complex floats
+ uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);
+
+ //Allocate buffer with data to send
+ std::vector<std::complex<float> > buff(tx_stream->get_max_num_samps(), std::complex<float>(tx_ampl, tx_ampl));
+
+ //Setup metadata for the first packet
+ uhd::tx_metadata_t md;
+ md.start_of_burst = false;
+ md.end_of_burst = false;
+ md.has_time_spec = false;
+
+ if(tx_rand){
+ std::srand((unsigned int) time(NULL));
+
+ while(true){
+ size_t total_num_samps = (rand() % (tx_high - tx_low)) + tx_low;
+ size_t num_acc_samps = 0;
+ float timeout = 1;
+
+ std::cout << boost::format("About to send %u samples.") % total_num_samps << std::endl;
+
+ usrp->set_time_now(uhd::time_spec_t(0.0));
+
+ while(num_acc_samps < total_num_samps){
+ size_t samps_to_send = std::min(total_num_samps - num_acc_samps, buff.size());
+
+ //Send a single packet
+ size_t num_tx_samps = tx_stream->send(&buff.front(), samps_to_send, md, timeout);
+
+ if(num_tx_samps < samps_to_send) std::cerr << "Send timeout..." << std::endl;
+
+ num_acc_samps += num_tx_samps;
+ }
+
+ md.end_of_burst = true;
+ tx_stream->send("", 0, md);
+
+ if(verbose) std::cout << std::endl;
+ std::cout << "Waiting for async burst ACK... " << std::flush;
+ uhd::async_metadata_t async_md;
+ bool got_async_burst_ack = false;
+
+ //Loop through all messages for the ACK packet (may have underflow messages in queue)
+ while (not got_async_burst_ack and usrp->get_device()->recv_async_msg(async_md, timeout)){
+ got_async_burst_ack = (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK);
+ }
+ std::cout << (got_async_burst_ack? "Success!" : "Failure...") << std::endl;
+
+ std::cout << boost::format("Successfully sent %u samples.") % total_num_samps << std::endl;
+
+ }
+ }
+ else{
+ float timeout = 1;
+
+ for(int i = int(tx_low); i <= int(tx_high); i += tx_step){
+
+ usrp->set_time_now(uhd::time_spec_t(0.0));
+
+ std::cout << boost::format("About to send %u samples.") % i << std::endl;
+ if(verbose) std::cout << std::endl;
+
+ size_t num_acc_samps = 0; //Number of accumulated samples
+ size_t total_num_samps = i;
+
+ while(num_acc_samps < total_num_samps){
+ size_t samps_to_send = std::min(total_num_samps - num_acc_samps, buff.size());
+
+ //Send a single packet
+ size_t num_tx_samps = tx_stream->send(
+ &buff.front(), samps_to_send, md, timeout
+ );
+
+ if (num_tx_samps < samps_to_send) std::cerr << "Send timeout..." << std::endl;
+
+ num_acc_samps += num_tx_samps;
+ }
+
+ //Send a mini EOB packet
+ md.end_of_burst = true;
+ tx_stream->send("", 0, md);
+
+ std::cout << std::endl << "Waiting for async burst ACK... " << std::flush;
+ uhd::async_metadata_t async_md;
+ bool got_async_burst_ack = false;
+ //Loop through all messages for the ACK packet (may have underflow messages in queue)
+ while (not got_async_burst_ack and usrp->get_device()->recv_async_msg(async_md, timeout)){
+ got_async_burst_ack = (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK);
+ }
+ std::cout << (got_async_burst_ack? "Success!" : "Failure...") << std::endl;
+
+ }
+ //Finished
+ std::cout << "Done!" << std::endl;
+ }
+}
+
+/************************************************************************
+ * Main code + dispatcher
+ ************************************************************************/
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ uhd::set_thread_priority_safe();
+
+ //Variables to be set by program options
+ std::string args;
+ double rx_rate;
+ int rx_low;
+ int rx_high;
+ int rx_step;
+ double tx_rate;
+ int tx_low;
+ int tx_high;
+ int tx_step;
+ double tx_ampl;
+
+ //Set up the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "Print this help message.")
+ ("args", po::value<std::string>(&args)->default_value(""), "Single UHD device address args.")
+ ("rx_rate", po::value<double>(&rx_rate), "RX sample rate.")
+ ("rx_rand", "Specify to use random amounts of RX samples (between rx_low and rx_high values).")
+ ("rx_low", po::value<int>(&rx_low)->default_value(1), "Lowest value of RX samples.")
+ ("rx_high", po::value<int>(&rx_high)->default_value(10000), "Highest value of RX samples.")
+ ("rx_step", po::value<int>(&rx_step)->default_value(10), "Delta between number of collected RX samples.")
+ ("tx_rate", po::value<double>(&tx_rate), "TX sample rate.")
+ ("tx_rand", "Specify to use random amounts of TX samples (between tx_low and tx_high values).")
+ ("tx_low", po::value<int>(&tx_low)->default_value(1), "Lowest value of TX samples.")
+ ("tx_high", po::value<int>(&tx_high)->default_value(10000), "Highest value of TX samples.")
+ ("tx_step", po::value<int>(&tx_step)->default_value(10), "Delta between number of sent TX samples.")
+ ("tx_ampl", po::value<double>(&tx_ampl)->default_value(0.5), "TX amplitude.")
+ ("verbose", "Enables verbosity")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //Set verbose or RX/TX random if requested by user
+ bool rx_rand = vm.count("rx_rand") > 0;
+ bool tx_rand = vm.count("tx_rand") > 0;
+ bool verbose = vm.count("verbose") > 0;
+
+ //Print the help message
+
+ if (vm.count("help") or (vm.count("rx_rate") + vm.count("tx_rate")) == 0){
+ std::cout << boost::format("UHD Transport Hammer %s") % desc << std::endl;
+ std::cout <<
+ " Specify --rx_rate for a receive-only test.\n"
+ " Specify --tx_rate for a transmit-only test.\n"
+ " Specify both options for a full-duplex test.\n"
+ << std::endl;
+ return ~0;
+ }
+
+ //Create a USRP device
+ std::cout << std::endl;
+ uhd::device_addrs_t device_addrs = uhd::device::find(args);
+ std::cout << boost::format("Creating the USRP device with: %s...") % args << std::endl;
+ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
+ std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
+
+ boost::thread_group thread_group;
+
+ //Spawn the receive test thread
+ if (vm.count("rx_rate")){
+ usrp->set_rx_rate(rx_rate);
+ thread_group.create_thread(boost::bind(&rx_hammer, usrp, rx_rate, rx_rand, rx_low, rx_high, rx_step, verbose));
+ }
+
+ //Spawn the transmit test thread
+ if (vm.count("tx_rate")){
+ usrp->set_tx_rate(tx_rate);
+ thread_group.create_thread(boost::bind(&tx_hammer, usrp, tx_rate, tx_rand, tx_low, tx_high, tx_step, tx_ampl, verbose));
+ }
+
+ //Interrupt and join the threads
+ boost::this_thread::sleep(boost::posix_time::microseconds(long(1e6)));
+ thread_group.interrupt_all();
+ thread_group.join_all();
+ //Finished
+ std::cout << std::endl << "Done!" << std::endl << std::endl;
+
+ return 0;
+}
diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp
index 88affa40c..429ae356b 100644
--- a/host/include/uhd/usrp/multi_usrp.hpp
+++ b/host/include/uhd/usrp/multi_usrp.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -25,6 +25,7 @@
#define UHD_USRP_MULTI_USRP_COMMAND_TIME_API
#define UHD_USRP_MULTI_USRP_BW_RANGE_API
#define UHD_USRP_MULTI_USRP_USER_REGS_API
+#define UHD_USRP_MULTI_USRP_GET_USRP_INFO_API
#include <uhd/config.hpp>
#include <uhd/device.hpp>
@@ -127,6 +128,24 @@ public:
return this->get_device()->get_tx_stream(args);
}
+ /*!
+ * Returns identifying information about this USRP's configuration.
+ * Returns motherboard ID, name, and serial.
+ * Returns daughterboard RX ID, subdev name, and serial.
+ * \param chan channel index 0 to N-1
+ * \return RX info
+ */
+ virtual dict<std::string, std::string> get_usrp_rx_info(size_t chan = 0) = 0;
+
+ /*!
+ * Returns identifying information about this USRP's configuration.
+ * Returns motherboard ID, name, and serial.
+ * Returns daughterboard TX ID, subdev name, and serial.
+ * \param chan channel index 0 to N-1
+ * \return TX info
+ */
+ virtual dict<std::string, std::string> get_usrp_tx_info(size_t chan = 0) = 0;
+
/*******************************************************************
* Mboard methods
******************************************************************/
diff --git a/host/include/uhd/version.hpp b/host/include/uhd/version.hpp
index ee0c4fe43..9a95b4786 100644
--- a/host/include/uhd/version.hpp
+++ b/host/include/uhd/version.hpp
@@ -27,7 +27,7 @@
* The format is oldest ABI compatible release - ABI compat number.
* The compatibility number allows pre-release ABI to be versioned.
*/
-#define UHD_VERSION_ABI_STRING "3.4.0-0"
+#define UHD_VERSION_ABI_STRING "3.4.0-1"
namespace uhd{
diff --git a/host/lib/usrp/common/fx2_ctrl.cpp b/host/lib/usrp/common/fx2_ctrl.cpp
index 7b8920eb1..5cc701eb0 100644
--- a/host/lib/usrp/common/fx2_ctrl.cpp
+++ b/host/lib/usrp/common/fx2_ctrl.cpp
@@ -411,6 +411,26 @@ public:
return usrp_control_write(request, value, index, 0, 0);
}
+ void write_eeprom(
+ boost::uint8_t addr,
+ boost::uint8_t offset,
+ const byte_vector_t &bytes
+ ){
+ byte_vector_t bytes_with_cmd(bytes.size() + 1);
+ bytes_with_cmd[0] = offset;
+ std::copy(bytes.begin(), bytes.end(), &bytes_with_cmd[1]);
+ this->write_i2c(addr, bytes_with_cmd);
+ }
+
+ byte_vector_t read_eeprom(
+ boost::uint8_t addr,
+ boost::uint8_t offset,
+ size_t num_bytes
+ ){
+ this->write_i2c(addr, byte_vector_t(1, offset));
+ return this->read_i2c(addr, num_bytes);
+ }
+
int usrp_i2c_write(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len)
{
return usrp_control_write(VRQ_I2C_WRITE, i2c_addr, 0, buf, len);
@@ -428,12 +448,7 @@ public:
{
UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes);
- unsigned char buff[max_i2c_data_bytes] = {};
- std::copy(bytes.begin(), bytes.end(), buff);
-
- int ret = this->usrp_i2c_write(addr & 0xff,
- buff,
- bytes.size());
+ int ret = this->usrp_i2c_write(addr, (unsigned char *)&bytes.front(), bytes.size());
if (iface_debug && (ret < 0))
uhd::runtime_error("USRP: failed i2c write");
@@ -443,19 +458,13 @@ public:
{
UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes);
- unsigned char buff[max_i2c_data_bytes] = {};
- int ret = this->usrp_i2c_read(addr & 0xff,
- buff,
- num_bytes);
+ byte_vector_t bytes(num_bytes);
+ int ret = this->usrp_i2c_read(addr, (unsigned char *)&bytes.front(), num_bytes);
if (iface_debug && ((ret < 0) || (unsigned)ret < (num_bytes)))
uhd::runtime_error("USRP: failed i2c read");
- byte_vector_t out_bytes;
- for (size_t i = 0; i < num_bytes; i++)
- out_bytes.push_back(buff[i]);
-
- return out_bytes;
+ return bytes;
}
diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp
index 785d30296..96a0d36ce 100644
--- a/host/lib/usrp/mboard_eeprom.cpp
+++ b/host/lib/usrp/mboard_eeprom.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -84,17 +84,20 @@ static std::string uint16_bytes_to_string(const byte_vector_t &bytes){
**********************************************************************/
static const boost::uint8_t N100_EEPROM_ADDR = 0x50;
-static const uhd::dict<std::string, boost::uint8_t> USRP_N100_OFFSETS = boost::assign::map_list_of
- ("hardware", 0x00)
- ("mac-addr", 0x02)
- ("ip-addr", 0x0C)
- //leave space here for other addresses (perhaps)
- ("revision", 0x12)
- ("product", 0x14)
- ("gpsdo", 0x17)
- ("serial", 0x18)
- ("name", 0x18 + SERIAL_LEN)
-;
+struct n100_eeprom_map{
+ boost::uint16_t hardware;
+ boost::uint8_t mac_addr[6];
+ boost::uint32_t subnet;
+ boost::uint32_t ip_addr;
+ boost::uint16_t _pad0;
+ boost::uint16_t revision;
+ boost::uint16_t product;
+ unsigned char _pad1;
+ unsigned char gpsdo;
+ unsigned char serial[SERIAL_LEN];
+ unsigned char name[NAME_MAX_LEN];
+ boost::uint32_t gateway;
+};
enum n200_gpsdo_type{
N200_GPSDO_NONE = 0,
@@ -105,30 +108,36 @@ enum n200_gpsdo_type{
static void load_n100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
//extract the hardware number
mb_eeprom["hardware"] = uint16_bytes_to_string(
- iface.read_eeprom(N100_EEPROM_ADDR, USRP_N100_OFFSETS["hardware"], 2)
+ iface.read_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, hardware), 2)
);
//extract the revision number
mb_eeprom["revision"] = uint16_bytes_to_string(
- iface.read_eeprom(N100_EEPROM_ADDR, USRP_N100_OFFSETS["revision"], 2)
+ iface.read_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, revision), 2)
);
//extract the product code
mb_eeprom["product"] = uint16_bytes_to_string(
- iface.read_eeprom(N100_EEPROM_ADDR, USRP_N100_OFFSETS["product"], 2)
+ iface.read_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, product), 2)
);
//extract the addresses
mb_eeprom["mac-addr"] = mac_addr_t::from_bytes(iface.read_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["mac-addr"], 6
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, mac_addr), 6
)).to_string();
boost::asio::ip::address_v4::bytes_type ip_addr_bytes;
- byte_copy(iface.read_eeprom(N100_EEPROM_ADDR, USRP_N100_OFFSETS["ip-addr"], 4), ip_addr_bytes);
+ byte_copy(iface.read_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, ip_addr), 4), ip_addr_bytes);
mb_eeprom["ip-addr"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
+ byte_copy(iface.read_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, subnet), 4), ip_addr_bytes);
+ mb_eeprom["subnet"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
+
+ byte_copy(iface.read_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, gateway), 4), ip_addr_bytes);
+ mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
+
//gpsdo capabilities
- boost::uint8_t gpsdo_byte = iface.read_eeprom(N100_EEPROM_ADDR, USRP_N100_OFFSETS["gpsdo"], 1).at(0);
+ boost::uint8_t gpsdo_byte = iface.read_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, gpsdo), 1).at(0);
switch(n200_gpsdo_type(gpsdo_byte)){
case N200_GPSDO_INTERNAL: mb_eeprom["gpsdo"] = "internal"; break;
case N200_GPSDO_ONBOARD: mb_eeprom["gpsdo"] = "onboard"; break;
@@ -137,12 +146,12 @@ static void load_n100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
//extract the serial
mb_eeprom["serial"] = bytes_to_string(iface.read_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["serial"], SERIAL_LEN
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, serial), SERIAL_LEN
));
//extract the name
mb_eeprom["name"] = bytes_to_string(iface.read_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["name"], NAME_MAX_LEN
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, name), NAME_MAX_LEN
));
//Empty serial correction: use the mac address to determine serial.
@@ -158,32 +167,44 @@ static void load_n100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
static void store_n100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
//parse the revision number
if (mb_eeprom.has_key("hardware")) iface.write_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["hardware"],
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, hardware),
string_to_uint16_bytes(mb_eeprom["hardware"])
);
//parse the revision number
if (mb_eeprom.has_key("revision")) iface.write_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["revision"],
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, revision),
string_to_uint16_bytes(mb_eeprom["revision"])
);
//parse the product code
if (mb_eeprom.has_key("product")) iface.write_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["product"],
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, product),
string_to_uint16_bytes(mb_eeprom["product"])
);
//store the addresses
if (mb_eeprom.has_key("mac-addr")) iface.write_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["mac-addr"],
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, mac_addr),
mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes()
);
if (mb_eeprom.has_key("ip-addr")){
byte_vector_t ip_addr_bytes(4);
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"]).to_bytes(), ip_addr_bytes);
- iface.write_eeprom(N100_EEPROM_ADDR, USRP_N100_OFFSETS["ip-addr"], ip_addr_bytes);
+ iface.write_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, ip_addr), ip_addr_bytes);
+ }
+
+ if (mb_eeprom.has_key("subnet")){
+ byte_vector_t ip_addr_bytes(4);
+ byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet"]).to_bytes(), ip_addr_bytes);
+ iface.write_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, subnet), ip_addr_bytes);
+ }
+
+ if (mb_eeprom.has_key("gateway")){
+ byte_vector_t ip_addr_bytes(4);
+ byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), ip_addr_bytes);
+ iface.write_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, gateway), ip_addr_bytes);
}
//gpsdo capabilities
@@ -191,18 +212,18 @@ static void store_n100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
boost::uint8_t gpsdo_byte = N200_GPSDO_NONE;
if (mb_eeprom["gpsdo"] == "internal") gpsdo_byte = N200_GPSDO_INTERNAL;
if (mb_eeprom["gpsdo"] == "onboard") gpsdo_byte = N200_GPSDO_ONBOARD;
- iface.write_eeprom(N100_EEPROM_ADDR, USRP_N100_OFFSETS["gpsdo"], byte_vector_t(1, gpsdo_byte));
+ iface.write_eeprom(N100_EEPROM_ADDR, offsetof(n100_eeprom_map, gpsdo), byte_vector_t(1, gpsdo_byte));
}
//store the serial
if (mb_eeprom.has_key("serial")) iface.write_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["serial"],
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, serial),
string_to_bytes(mb_eeprom["serial"], SERIAL_LEN)
);
//store the name
if (mb_eeprom.has_key("name")) iface.write_eeprom(
- N100_EEPROM_ADDR, USRP_N100_OFFSETS["name"],
+ N100_EEPROM_ADDR, offsetof(n100_eeprom_map, name),
string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN)
);
}
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 93c0eada6..39f9cb490 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -21,6 +21,10 @@
#include <uhd/exception.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/utils/gain_group.hpp>
+#include <uhd/usrp/dboard_id.hpp>
+#include <uhd/usrp/mboard_eeprom.hpp>
+#include <uhd/usrp/dboard_eeprom.hpp>
+#include <boost/assign/list_of.hpp>
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
@@ -214,6 +218,48 @@ public:
return _dev;
}
+ dict<std::string, std::string> get_usrp_rx_info(size_t chan){
+ mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ dict<std::string, std::string> usrp_info;
+
+ mboard_eeprom_t mb_eeprom = _tree->access<mboard_eeprom_t>(mb_root(mcp.mboard) / "eeprom").get();
+ dboard_eeprom_t db_eeprom = _tree->access<dboard_eeprom_t>(rx_rf_fe_root(mcp.chan).branch_path().branch_path() / "rx_eeprom").get();
+
+ usrp_info["mboard_id"] = _tree->access<std::string>(mb_root(mcp.mboard) / "name").get();
+ usrp_info["mboard_name"] = mb_eeprom["name"];
+ usrp_info["mboard_serial"] = mb_eeprom["serial"];
+ usrp_info["rx_id"] = db_eeprom.id.to_pp_string();
+ usrp_info["rx_subdev_name"] = _tree->access<std::string>(rx_rf_fe_root(mcp.chan) / "name").get();
+ usrp_info["rx_subdev_spec"] = _tree->access<subdev_spec_t>(mb_root(mcp.mboard) / "rx_subdev_spec").get().to_string();
+ usrp_info["rx_serial"] = db_eeprom.serial;
+ usrp_info["rx_antenna"] = _tree->access<std::string>(rx_rf_fe_root(mcp.chan) / "antenna" / "value").get();
+
+ return usrp_info;
+ }
+
+ dict<std::string, std::string> get_usrp_tx_info(size_t chan){
+ mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ dict<std::string, std::string> usrp_info;
+
+ mboard_eeprom_t mb_eeprom = _tree->access<mboard_eeprom_t>(mb_root(mcp.mboard) / "eeprom").get();
+ dboard_eeprom_t gdb_eeprom = _tree->access<dboard_eeprom_t>(tx_rf_fe_root(mcp.chan).branch_path().branch_path() / "gdb_eeprom").get();
+ dboard_eeprom_t db_eeprom;
+
+ if(gdb_eeprom.id != dboard_id_t::none()) db_eeprom = gdb_eeprom;
+ else db_eeprom = _tree->access<dboard_eeprom_t>(tx_rf_fe_root(mcp.chan).branch_path().branch_path() / "tx_eeprom").get();
+
+ usrp_info["mboard_id"] = _tree->access<std::string>(mb_root(mcp.mboard) / "name").get();
+ usrp_info["mboard_name"] = mb_eeprom["name"];
+ usrp_info["mboard_serial"] = mb_eeprom["serial"];
+ usrp_info["tx_id"] = db_eeprom.id.to_pp_string();
+ usrp_info["tx_subdev_name"] = _tree->access<std::string>(tx_rf_fe_root(mcp.chan) / "name").get();
+ usrp_info["tx_subdev_spec"] = _tree->access<subdev_spec_t>(mb_root(mcp.mboard) / "tx_subdev_spec").get().to_string();
+ usrp_info["tx_serial"] = db_eeprom.serial;
+ usrp_info["tx_antenna"] = _tree->access<std::string>(tx_rf_fe_root(mcp.chan) / "antenna" / "value").get();
+
+ return usrp_info;
+ }
+
/*******************************************************************
* Mboard methods
******************************************************************/
@@ -621,10 +667,6 @@ public:
return _tree->access<subdev_spec_t>(mb_root(mboard) / "tx_subdev_spec").get();
}
- std::string get_tx_subdev_name(size_t chan){
- return _tree->access<std::string>(tx_rf_fe_root(chan) / "name").get();
- }
-
size_t get_tx_num_channels(void){
size_t sum = 0;
for (size_t m = 0; m < get_num_mboards(); m++){
@@ -633,6 +675,10 @@ public:
return sum;
}
+ std::string get_tx_subdev_name(size_t chan){
+ return _tree->access<std::string>(tx_rf_fe_root(chan) / "name").get();
+ }
+
void set_tx_rate(double rate, size_t chan){
if (chan != ALL_CHANS){
_tree->access<double>(tx_dsp_root(chan) / "rate" / "value").set(rate);
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 0babf7445..2add74c47 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -37,6 +37,13 @@ extern "C" {
//used to differentiate control packets over data port
#define USRP2_INVALID_VRT_HEADER 0
+typedef struct{
+ uint32_t sequence;
+ uint32_t vrt_hdr;
+ uint32_t ip_addr;
+ uint32_t udp_port;
+} usrp2_stream_ctrl_t;
+
// udp ports for the usrp2 communication
// Dynamic and/or private ports: 49152-65535
#define USRP2_UDP_CTRL_PORT 49152
@@ -65,6 +72,8 @@ extern "C" {
////////////////////////////////////////////////////////////////////////
#define USRP2_EE_MBOARD_REV 0x00 //2 bytes, little-endian (historic, don't blame me)
#define USRP2_EE_MBOARD_MAC_ADDR 0x02 //6 bytes
+#define USRP2_EE_MBOARD_GATEWAY 0x38 //uint32, big-endian
+#define USRP2_EE_MBOARD_SUBNET 0x08 //uint32, big-endian
#define USRP2_EE_MBOARD_IP_ADDR 0x0C //uint32, big-endian
#define USRP2_EE_MBOARD_BOOTLOADER_FLAGS 0xF7
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index d32ffb62c..ea4aa716c 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -21,6 +21,7 @@
#include "../../transport/super_send_packet_handler.hpp"
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
+#include "fw_common.h"
#include <uhd/utils/log.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/utils/tasks.hpp>
@@ -31,6 +32,7 @@
#include <boost/thread/thread.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
+#include <boost/asio.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
@@ -361,6 +363,60 @@ bool usrp2_impl::recv_async_msg(
}
/***********************************************************************
+ * Stream destination programmer
+ **********************************************************************/
+void usrp2_impl::program_stream_dest(
+ zero_copy_if::sptr &xport, const uhd::stream_args_t &args
+){
+ //perform an initial flush of transport
+ while (xport->get_recv_buff(0.0)){}
+
+ //program the stream command
+ usrp2_stream_ctrl_t stream_ctrl = usrp2_stream_ctrl_t();
+ stream_ctrl.sequence = uhd::htonx(boost::uint32_t(0 /* don't care seq num */));
+ stream_ctrl.vrt_hdr = uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER));
+
+ //user has provided an alternative address and port for destination
+ if (args.args.has_key("addr") and args.args.has_key("port")){
+ UHD_MSG(status) << boost::format(
+ "Programming streaming destination for custom address.\n"
+ "IPv4 Address: %s, UDP Port: %s\n"
+ ) % args.args["addr"] % args.args["port"] << std::endl;
+
+ asio::io_service io_service;
+ asio::ip::udp::resolver resolver(io_service);
+ asio::ip::udp::resolver::query query(asio::ip::udp::v4(), args.args["addr"], args.args["port"]);
+ asio::ip::udp::endpoint endpoint = *resolver.resolve(query);
+ stream_ctrl.ip_addr = uhd::htonx(boost::uint32_t(endpoint.address().to_v4().to_ulong()));
+ stream_ctrl.udp_port = uhd::htonx(boost::uint32_t(endpoint.port()));
+
+ for (size_t i = 0; i < 3; i++){
+ UHD_MSG(status) << "ARP attempt " << i << std::endl;
+ managed_send_buffer::sptr send_buff = xport->get_send_buff();
+ std::memcpy(send_buff->cast<void *>(), &stream_ctrl, sizeof(stream_ctrl));
+ send_buff->commit(sizeof(stream_ctrl));
+ boost::this_thread::sleep(boost::posix_time::milliseconds(300));
+ managed_recv_buffer::sptr recv_buff = xport->get_recv_buff(0.0);
+ if (recv_buff and recv_buff->size() >= sizeof(boost::uint32_t)){
+ const boost::uint32_t result = uhd::ntohx(recv_buff->cast<const boost::uint32_t *>()[0]);
+ if (result == 0){
+ UHD_MSG(status) << "Success! " << std::endl;
+ return;
+ }
+ }
+ }
+ throw uhd::runtime_error("Device failed to ARP when programming alternative streaming destination.");
+ }
+
+ else{
+ //send the partial stream control without destination
+ managed_send_buffer::sptr send_buff = xport->get_send_buff();
+ std::memcpy(send_buff->cast<void *>(), &stream_ctrl, sizeof(stream_ctrl));
+ send_buff->commit(sizeof(stream_ctrl)/2);
+ }
+}
+
+/***********************************************************************
* Receive streamer
**********************************************************************/
rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){
@@ -406,6 +462,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){
const size_t dsp = chan + _mbc[mb].rx_chan_occ - num_chan_so_far;
_mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this
_mbc[mb].rx_dsps[dsp]->setup(args);
+ this->program_stream_dest(_mbc[mb].rx_dsp_xports[dsp], args);
my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
&zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1
), true /*flush*/);
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index e5065c02d..6053c3890 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -129,6 +129,7 @@ private:
double set_tx_dsp_freq(const std::string &, const double);
uhd::meta_range_t get_tx_dsp_freq_range(const std::string &);
void update_clock_source(const std::string &, const std::string &);
+ void program_stream_dest(uhd::transport::zero_copy_if::sptr &, const uhd::stream_args_t &);
};
#endif /* INCLUDED_USRP2_IMPL_HPP */