aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-03-30 13:32:52 +0000
committerJosh Blum <josh@joshknows.com>2010-03-30 13:32:52 +0000
commitf94fa1e464c9e2a87274c991dc6461f7f4c956d8 (patch)
tree1b88020a0dece1ae509cf3fb219b7cce487dc198
parent29e88b3478aad89ff76363029395200a8601e667 (diff)
parent281307833c8275031bd2469e6aef3f472490749a (diff)
downloaduhd-f94fa1e464c9e2a87274c991dc6461f7f4c956d8.tar.gz
uhd-f94fa1e464c9e2a87274c991dc6461f7f4c956d8.tar.bz2
uhd-f94fa1e464c9e2a87274c991dc6461f7f4c956d8.zip
Merge branch 'master' of git@ettus.sourcerepo.com:ettus/uhd into usrp_e
Conflicts: host/include/uhd/usrp/dboard_id.hpp host/lib/usrp/usrp2/usrp2_impl.cpp
-rw-r--r--firmware/microblaze/apps/txrx.c233
-rw-r--r--firmware/microblaze/lib/memory_map.h3
-rw-r--r--host/CMakeLists.txt12
-rw-r--r--host/README8
-rw-r--r--host/examples/CMakeLists.txt20
-rw-r--r--host/examples/rx_timed_samples.cpp99
-rw-r--r--host/include/uhd/CMakeLists.txt11
-rw-r--r--host/include/uhd/config.hpp159
-rw-r--r--host/include/uhd/device.hpp28
-rw-r--r--host/include/uhd/device_addr.hpp69
-rw-r--r--host/include/uhd/metadata.hpp61
-rw-r--r--host/include/uhd/props.hpp2
-rw-r--r--host/include/uhd/simple_device.hpp13
-rw-r--r--host/include/uhd/transport/CMakeLists.txt3
-rw-r--r--host/include/uhd/transport/if_addrs.hpp (renamed from host/lib/metadata.cpp)50
-rw-r--r--host/include/uhd/transport/smart_buffer.hpp2
-rw-r--r--host/include/uhd/transport/udp_simple.hpp2
-rw-r--r--host/include/uhd/transport/udp_zero_copy.hpp2
-rw-r--r--host/include/uhd/transport/vrt.hpp2
-rw-r--r--host/include/uhd/types/CMakeLists.txt32
-rw-r--r--host/include/uhd/types/clock_config.hpp50
-rw-r--r--host/include/uhd/types/device_addr.hpp70
-rw-r--r--host/include/uhd/types/dict.hpp (renamed from host/include/uhd/dict.hpp)13
-rw-r--r--host/include/uhd/types/io_type.hpp69
-rw-r--r--host/include/uhd/types/mac_addr.hpp68
-rw-r--r--host/include/uhd/types/metadata.hpp61
-rw-r--r--host/include/uhd/types/otw_type.hpp63
-rw-r--r--host/include/uhd/types/ranges.hpp (renamed from host/include/uhd/types.hpp)43
-rw-r--r--host/include/uhd/types/stream_cmd.hpp56
-rw-r--r--host/include/uhd/types/time_spec.hpp (renamed from host/include/uhd/time_spec.hpp)16
-rw-r--r--host/include/uhd/types/tune_result.hpp44
-rw-r--r--host/include/uhd/usrp/CMakeLists.txt2
-rw-r--r--host/include/uhd/usrp/dboard_id.hpp2
-rw-r--r--host/include/uhd/usrp/dboard_manager.hpp4
-rw-r--r--host/include/uhd/usrp/usrp1e.hpp5
-rw-r--r--host/include/uhd/usrp/usrp2.hpp5
-rw-r--r--host/include/uhd/utils/CMakeLists.txt26
-rw-r--r--host/include/uhd/utils/algorithm.hpp60
-rw-r--r--host/include/uhd/utils/assert.hpp (renamed from host/include/uhd/utils.hpp)74
-rw-r--r--host/include/uhd/utils/gain_handler.hpp (renamed from host/include/uhd/gain_handler.hpp)6
-rw-r--r--host/include/uhd/utils/safe_main.hpp44
-rw-r--r--host/include/uhd/utils/static.hpp37
-rw-r--r--host/include/uhd/utils/tune_helper.hpp79
-rw-r--r--host/include/uhd/wax.hpp4
-rw-r--r--host/lib/CMakeLists.txt39
-rw-r--r--host/lib/device.cpp29
-rw-r--r--host/lib/device_addr.cpp86
-rw-r--r--host/lib/gain_handler.cpp28
-rw-r--r--host/lib/load_modules.cpp8
-rw-r--r--host/lib/simple_device.cpp140
-rw-r--r--host/lib/time_spec.cpp40
-rwxr-xr-xhost/lib/transport/gen_vrt.py206
-rw-r--r--host/lib/transport/if_addrs.cpp109
-rw-r--r--host/lib/transport/udp_simple.cpp1
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp3
-rw-r--r--host/lib/transport/vrt.cpp550
-rw-r--r--host/lib/tune_helper.cpp125
-rw-r--r--host/lib/types.cpp206
-rw-r--r--host/lib/usrp/dboard/basic.cpp35
-rw-r--r--host/lib/usrp/dboard_base.cpp16
-rw-r--r--host/lib/usrp/dboard_manager.cpp23
-rw-r--r--host/lib/usrp/usrp1e/usrp1e_none.cpp2
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp3
-rw-r--r--host/lib/usrp/usrp2/dboard_interface.cpp2
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp68
-rw-r--r--host/lib/usrp/usrp2/fw_common.h16
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp121
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp88
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp29
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp24
-rw-r--r--host/test/addr_test.cpp45
-rw-r--r--host/test/gain_handler_test.cpp28
-rw-r--r--host/test/module_test.cpp4
-rw-r--r--host/test/wax_test.cpp19
-rw-r--r--host/uhd.pc.in2
-rw-r--r--host/utils/CMakeLists.txt (renamed from host/apps/CMakeLists.txt)9
-rw-r--r--host/utils/uhd_find_devices.cpp (renamed from host/apps/discover_usrps.cpp)15
-rw-r--r--host/utils/usrp2_burner.cpp (renamed from host/apps/usrp2_burner.cpp)20
-rwxr-xr-xhost/utils/usrp2_recovery.py (renamed from host/apps/usrp2_recovery.py)16
79 files changed, 2749 insertions, 1118 deletions
diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c
index b82c7702b..262995885 100644
--- a/firmware/microblaze/apps/txrx.c
+++ b/firmware/microblaze/apps/txrx.c
@@ -22,6 +22,8 @@
#include "config.h"
#endif
+#define DEBUG_MODE 0 //0 for normal operation
+
#include <lwip/ip.h>
#include <lwip/udp.h>
#include "u2_init.h"
@@ -50,13 +52,6 @@
#include <ethertype.h>
#include <arp_cache.h>
-#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now)
-
-#if (FW_SETS_SEQNO)
-static int fw_seqno; // used when f/w is filling in sequence numbers
-#endif
-
-
/*
* Full duplex Tx and Rx between ethernet and DSP pipelines
*
@@ -102,8 +97,15 @@ dbsm_t dsp_tx_sm; // the state machine
* ================================================================
*/
+typedef struct{
+ uint32_t control_word;
+ uint32_t vrt_header[];
+} rx_dsp_buff_t;
+
+#define MK_RX_CTRL_WORD(num_words) (((num_words)*sizeof(uint32_t)) | (1 << 16))
+
// DSP Rx writes ethernet header words
-#define DSP_RX_FIRST_LINE 1 //1 = control stuff to udp sm
+#define DSP_RX_FIRST_LINE 1 //1 = number of control words (see above)
// receive from DSP
buf_cmd_args_t dsp_rx_recv_args = {
@@ -125,18 +127,14 @@ dbsm_t dsp_rx_sm; // the state machine
// The mac address of the host we're sending to.
eth_mac_addr_t host_mac_addr;
-#define TIME_NOW ((uint32_t)(~0))
-
-// variables for streaming mode
-
-static bool streaming_p = false;
-static unsigned int streaming_items_per_frame = 0;
-static uint32_t time_secs = TIME_NOW;
-static uint32_t time_ticks = TIME_NOW;
-static int streaming_frame_count = 0;
+//controls continuous streaming...
+static bool auto_reload_command = false;
+static size_t streaming_items_per_frame = 0;
+static int streaming_frame_count = 0;
#define FRAMES_PER_CMD 2
-bool is_streaming(void){ return streaming_p; }
+static void setup_network(void);
+static void setup_vrt(void);
// ----------------------------------------------------------------
// the fast-path setup global variables
@@ -157,6 +155,9 @@ void handle_udp_data_packet(
struct socket_address src, struct socket_address dst,
unsigned char *payload, int payload_len
){
+ //store the 2nd word as the following:
+ streaming_items_per_frame = ((uint32_t *)payload)[1];
+
//its a tiny payload, load the fast-path variables
fp_mac_addr_src = *ethernet_mac_addr();
arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst);
@@ -174,6 +175,24 @@ void handle_udp_data_packet(
print_ip_addr(&fp_socket_dst.addr); newline();
printf(" destination udp port: %d\n", fp_socket_dst.port);
newline();
+
+ //setup network and vrt
+ setup_network();
+ setup_vrt();
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+
+}
+
+static void inline issue_stream_command(size_t nsamps, bool now, bool chain, uint32_t secs, uint32_t ticks, bool start){
+ //printf("Stream cmd: nsamps %d, now %d, chain %d, secs %u, ticks %u\n", (int)nsamps, now, chain, secs, ticks);
+ sr_rx_ctrl->cmd = MK_RX_CMD(nsamps, now, chain);
+
+ if (start) dbsm_start(&dsp_rx_sm);
+
+ sr_rx_ctrl->time_secs = secs;
+ sr_rx_ctrl->time_ticks = ticks; // enqueue command
}
#define OTW_GPIO_BANK_TO_NUM(bank) \
@@ -275,7 +294,7 @@ void handle_udp_ctrl_packet(
* GPIO
******************************************************************/
case USRP2_CTRL_ID_USE_THESE_GPIO_DDR_SETTINGS_BRO:
- hal_gpio_set_ddr(
+ if (!DEBUG_MODE) hal_gpio_set_ddr(
OTW_GPIO_BANK_TO_NUM(ctrl_data_in->data.gpio_config.bank),
ctrl_data_in->data.gpio_config.value,
ctrl_data_in->data.gpio_config.mask
@@ -284,7 +303,7 @@ void handle_udp_ctrl_packet(
break;
case USRP2_CTRL_ID_SET_YOUR_GPIO_PIN_OUTS_BRO:
- hal_gpio_write(
+ if (!DEBUG_MODE) hal_gpio_write(
OTW_GPIO_BANK_TO_NUM(ctrl_data_in->data.gpio_config.bank),
ctrl_data_in->data.gpio_config.value,
ctrl_data_in->data.gpio_config.mask
@@ -302,7 +321,7 @@ void handle_udp_ctrl_packet(
case USRP2_CTRL_ID_USE_THESE_ATR_SETTINGS_BRO:{
//setup the atr registers for this bank
int bank = OTW_GPIO_BANK_TO_NUM(ctrl_data_in->data.atr_config.bank);
- set_atr_regs(
+ if (!DEBUG_MODE) set_atr_regs(
bank,
ctrl_data_in->data.atr_config.rx_value,
ctrl_data_in->data.atr_config.tx_value
@@ -312,7 +331,7 @@ void handle_udp_ctrl_packet(
int mask = ctrl_data_in->data.atr_config.mask;
for (int i = 0; i < 16; i++){
// set to either GPIO_SEL_SW or GPIO_SEL_ATR
- hal_gpio_set_sel(bank, i, (mask & (1 << i)) ? 'a' : 's');
+ if (!DEBUG_MODE) hal_gpio_set_sel(bank, i, (mask & (1 << i)) ? 'a' : 's');
}
ctrl_data_out.id = USRP2_CTRL_ID_GOT_THE_ATR_SETTINGS_DUDE;
}
@@ -441,20 +460,69 @@ void handle_udp_ctrl_packet(
ctrl_data_out.id = USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE;
break;
- case USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO:
- time_secs = ctrl_data_in->data.streaming.secs;
- time_ticks = ctrl_data_in->data.streaming.ticks;
- streaming_items_per_frame = ctrl_data_in->data.streaming.samples;
+ /*******************************************************************
+ * Streaming
+ ******************************************************************/
+ case USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO:{
+
+ //issue two commands and set the auto-reload flag
+ if (ctrl_data_in->data.stream_cmd.continuous){
+ printf("Setting up continuous streaming...\n");
+ printf("items per frame: %d\n", (int)streaming_items_per_frame);
+ auto_reload_command = true;
+ streaming_frame_count = FRAMES_PER_CMD;
+
+ issue_stream_command(
+ streaming_items_per_frame * FRAMES_PER_CMD,
+ (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now
+ true, //chain
+ ctrl_data_in->data.stream_cmd.secs,
+ ctrl_data_in->data.stream_cmd.ticks,
+ true //start
+ );
+
+ issue_stream_command(
+ streaming_items_per_frame * FRAMES_PER_CMD,
+ true, //now
+ true, //chain
+ 0, 0, //time does not matter
+ false
+ );
- if (ctrl_data_in->data.streaming.enabled == 0){
- stop_rx_cmd();
}
+
+ //issue regular stream commands (split commands if too large)
else{
- start_rx_streaming_cmd();
- }
+ auto_reload_command = false;
+ size_t num_samps = ctrl_data_in->data.stream_cmd.num_samps;
+ if (num_samps == 0) num_samps = 1; //FIXME hack, zero is used when stopping continuous streaming but it somehow makes it inifinite
+
+ bool chain = num_samps > MAX_SAMPLES_PER_CMD;
+ issue_stream_command(
+ (chain)? streaming_items_per_frame : num_samps, //nsamps
+ (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now
+ chain, //chain
+ ctrl_data_in->data.stream_cmd.secs,
+ ctrl_data_in->data.stream_cmd.ticks,
+ false
+ );
- ctrl_data_out.id = USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE;
+ //handle rest of the samples that did not fit into one cmd
+ while(chain){
+ num_samps -= MAX_SAMPLES_PER_CMD;
+ chain = num_samps > MAX_SAMPLES_PER_CMD;
+ issue_stream_command(
+ (chain)? streaming_items_per_frame : num_samps, //nsamps
+ true, //now
+ chain, //chain
+ 0, 0, //time does not matter
+ false
+ );
+ }
+ }
+ ctrl_data_out.id = USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE;
break;
+ }
/*******************************************************************
* DUC
@@ -529,7 +597,7 @@ eth_pkt_inspector(dbsm_t *sm, int bufno)
// In the future, a hardware state machine will do this...
if ( //warning! magic numbers approaching....
(((buff + ((2 + 14 + 20)/sizeof(uint32_t)))[0] & 0xffff) == USRP2_UDP_DATA_PORT) &&
- ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != 0)
+ ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != USRP2_INVALID_VRT_HEADER)
) return false;
//test if its an ip recovery packet
@@ -555,19 +623,11 @@ eth_pkt_inspector(dbsm_t *sm, int bufno)
//------------------------------------------------------------------
-static uint16_t get_vrt_packet_words(void){
- return streaming_items_per_frame + \
- USRP2_HOST_RX_VRT_HEADER_WORDS32 + \
- USRP2_HOST_RX_VRT_TRAILER_WORDS32;
-}
-
static bool vrt_has_trailer(void){
return USRP2_HOST_RX_VRT_TRAILER_WORDS32 > 0;
}
-void
-restart_streaming(void)
-{
+static void setup_vrt(void){
// setup RX DSP regs
sr_rx_ctrl->nsamples_per_pkt = streaming_items_per_frame;
sr_rx_ctrl->nchannels = 1;
@@ -580,26 +640,6 @@ restart_streaming(void)
);
sr_rx_ctrl->vrt_stream_id = 0;
sr_rx_ctrl->vrt_trailer = 0;
-
- streaming_p = true;
- streaming_frame_count = FRAMES_PER_CMD;
-
- sr_rx_ctrl->cmd =
- MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
- (time_ticks==TIME_NOW)?1:0, 1); // conditionally set "now" bit, set "chain" bit
-
- // kick off the state machine
- dbsm_start(&dsp_rx_sm);
-
- sr_rx_ctrl->time_secs = time_secs;
- sr_rx_ctrl->time_ticks = time_ticks; // enqueue first of two commands
-
- // make sure this one and the rest have the "now" and "chain" bits set.
- sr_rx_ctrl->cmd =
- MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, 1, 1);
-
- sr_rx_ctrl->time_secs = 0;
- sr_rx_ctrl->time_ticks = 0; // enqueue second command
}
/*
@@ -628,23 +668,7 @@ link_changed_callback(int speed)
printf("\neth link changed: speed = %d\n", speed);
}
-void
-start_rx_streaming_cmd(void)
-{
- /*
- * Construct ethernet header and preload into two buffers
- */
- struct {
- uint32_t ctrl_word;
- } mem _AL4;
-
- memset(&mem, 0, sizeof(mem));
- printf("samples per frame: %d\n", streaming_items_per_frame);
- printf("words in a vrt packet %d\n", get_vrt_packet_words());
- mem.ctrl_word = get_vrt_packet_words()*sizeof(uint32_t) | 1 << 16;
-
- memcpy_wa(buffer_ram(DSP_RX_BUF_0), &mem, sizeof(mem));
- memcpy_wa(buffer_ram(DSP_RX_BUF_1), &mem, sizeof(mem));
+static void setup_network(void){
//setup ethernet header machine
sr_udp_sm->eth_hdr.mac_dst_0_1 = (fp_mac_addr_dst.addr[0] << 8) | fp_mac_addr_dst.addr[1];
@@ -676,50 +700,29 @@ start_rx_streaming_cmd(void)
sr_udp_sm->udp_hdr.dst_port = fp_socket_dst.port;
sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN;
sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum
-
- if (FW_SETS_SEQNO)
- fw_seqno = 0;
-
- restart_streaming();
}
-void
-stop_rx_cmd(void)
-{
- if (is_streaming()){
- streaming_p = false;
-
- // no samples, "now", not chained
- sr_rx_ctrl->cmd = MK_RX_CMD(0, 1, 0);
-
- sr_rx_ctrl->time_secs = 0;
- sr_rx_ctrl->time_ticks = 0; // enqueue command
- }
-
-}
-
-#if (FW_SETS_SEQNO)
/*
- * Debugging ONLY. This will be handled by the tx_protocol_engine.
- *
* This is called when the DSP Rx chain has filled in a packet.
- * We set and increment the seqno, then return false, indicating
- * that we didn't handle the packet. A bit of a kludge
- * but it should work.
*/
bool
fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
{
+ // insert the correct length into the control word and vrt header
+ rx_dsp_buff_t *buff = (rx_dsp_buff_t*)buffer_ram(buf_this);
+ size_t vrt_len = buffer_pool_status->last_line[buf_this]-1;
+ buff->control_word = MK_RX_CTRL_WORD(vrt_len);
+ buff->vrt_header[0] = (buff->vrt_header[0] & ~VRTH_PKT_SIZE_MASK) | (vrt_len & VRTH_PKT_SIZE_MASK);
+
// queue up another rx command when required
- if (streaming_p && --streaming_frame_count == 0){
+ if (auto_reload_command && --streaming_frame_count == 0){
streaming_frame_count = FRAMES_PER_CMD;
sr_rx_ctrl->time_secs = 0;
- sr_rx_ctrl->time_ticks = 0;
+ sr_rx_ctrl->time_ticks = 0; //enqueue last command
}
return false; // we didn't handle the packet
}
-#endif
inline static void
@@ -757,9 +760,9 @@ main(void)
#endif
output_regs->debug_mux_ctrl = 1;
-#if 0
- hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
- hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+#if DEBUG_MODE
+ hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
+ hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
#endif
@@ -774,16 +777,10 @@ main(void)
// initialize double buffering state machine for DSP RX -> Ethernet
- if (FW_SETS_SEQNO){
dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
&dsp_rx_recv_args, &dsp_rx_send_args,
fw_sets_seqno_inspector);
- }
- else {
- dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
- &dsp_rx_recv_args, &dsp_rx_send_args,
- dbsm_nop_inspector);
- }
+
// tell app_common that this dbsm could be sending to the ethernet
ac_could_be_sending_to_eth = &dsp_rx_sm;
@@ -818,7 +815,7 @@ main(void)
// FIXME Figure out how to handle this robustly.
// Any buffers that are emptying should be allowed to drain...
- if (streaming_p){
+ if (auto_reload_command){
// restart_streaming();
// FIXME report error
}
diff --git a/firmware/microblaze/lib/memory_map.h b/firmware/microblaze/lib/memory_map.h
index bb6a1036d..fed1e5259 100644
--- a/firmware/microblaze/lib/memory_map.h
+++ b/firmware/microblaze/lib/memory_map.h
@@ -525,8 +525,9 @@ typedef struct {
volatile uint32_t pad[7]; // Make each structure 16 elements long
} sr_rx_ctrl_t;
+#define MAX_SAMPLES_PER_CMD 0x3fffffff
#define MK_RX_CMD(nsamples, now, chain) \
- ((((now) & 0x1) << 31) | ((chain & 0x1) << 30) | ((nsamples) & 0x3fffffff))
+ ((((now) & 0x1) << 31) | (((chain) & 0x1) << 30) | ((nsamples) & 0x3fffffff))
#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL))
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index 2f5d03f7d..05d782abe 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -34,8 +34,9 @@ INCLUDE(CPack) #include after setting vars
########################################################################
SET(RUNTIME_DIR bin)
SET(LIBRARY_DIR lib)
-SET(RESOURCE_DIR share)
-SET(HEADER_DIR include)
+SET(INCLUDE_DIR include)
+SET(PKG_DATA_DIR share/uhd)
+MESSAGE(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}")
########################################################################
# Local Include Dir
@@ -63,10 +64,10 @@ IF(UNIX)
ENDIF(UNIX)
IF(WIN32)
- ADD_DEFINITIONS(-Dnot=! -Dand=&& -Dor=||) #logical operators
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) #minimum version required is windows xp
ADD_DEFINITIONS(-DNOMINMAX) #disables stupidity and enables std::min and std::max
ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS) #avoid warnings from boost::split
+ ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) #avoid warnings from std::getenv
ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) #setup boost auto-linking in msvc
ENDIF(WIN32)
@@ -74,7 +75,7 @@ ENDIF(WIN32)
# Setup Boost
########################################################################
SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42")
-FIND_PACKAGE(Boost 1.36 REQUIRED
+FIND_PACKAGE(Boost 1.36 REQUIRED COMPONENTS
date_time
filesystem
program_options
@@ -126,7 +127,8 @@ INSTALL(
########################################################################
# Add the subdirectories
########################################################################
-ADD_SUBDIRECTORY(apps)
+ADD_SUBDIRECTORY(examples)
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(lib)
ADD_SUBDIRECTORY(test)
+ADD_SUBDIRECTORY(utils)
diff --git a/host/README b/host/README
index f19275c41..cdca42cd0 100644
--- a/host/README
+++ b/host/README
@@ -6,21 +6,25 @@ The hardware driver for Ettus Research products.
########################################################################
# Supported USRP Motherboards
########################################################################
-USRP2 - gigabit ethernet
+USRP2 - udp over gigabit ethernet
########################################################################
# Supported USRP Daughterboards
########################################################################
Basic RX
Basic TX
+LF RX
+LF TX
########################################################################
# CMake Instructions
########################################################################
-cd <uhd_src_dir>
+cd uhd/host
mkdir build
cd build
cmake ../
make
make test
sudo make install
+
+For a custom prefix, use: cmake -DCMAKE_INSTALL_PREFIX=<myprefix> ../
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
new file mode 100644
index 000000000..242857625
--- /dev/null
+++ b/host/examples/CMakeLists.txt
@@ -0,0 +1,20 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+ADD_EXECUTABLE(rx_timed_samples rx_timed_samples.cpp)
+TARGET_LINK_LIBRARIES(rx_timed_samples uhd)
+INSTALL(TARGETS rx_timed_samples RUNTIME DESTINATION ${PKG_DATA_DIR}/examples)
diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp
new file mode 100644
index 000000000..88e112584
--- /dev/null
+++ b/host/examples/rx_timed_samples.cpp
@@ -0,0 +1,99 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/simple_device.hpp>
+#include <uhd/props.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+#include <complex>
+
+namespace po = boost::program_options;
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ //variables to be set by po
+ std::string transport_args;
+ int seconds_in_future;
+ size_t total_num_samps;
+
+ //setup the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&transport_args)->default_value(""), "simple uhd transport args")
+ ("secs", po::value<int>(&seconds_in_future)->default_value(3), "number of seconds in the future to receive")
+ ("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl;
+ return ~0;
+ }
+
+ //create a usrp device
+ std::cout << std::endl;
+ std::cout << boost::format("Creating the usrp device with: %s...")
+ % transport_args << std::endl;
+ uhd::simple_device::sptr sdev = uhd::simple_device::make(transport_args);
+ uhd::device::sptr dev = sdev->get_device();
+ std::cout << boost::format("Using Device: %s") % sdev->get_name() << std::endl;
+
+ //set properties on the device
+ double rx_rate = sdev->get_rx_rates()[4]; //pick some rate
+ std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl;
+ sdev->set_rx_rate(rx_rate);
+ std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
+ sdev->set_time_now(uhd::time_spec_t(0));
+
+ //setup streaming
+ std::cout << std::endl;
+ std::cout << boost::format("Begin streaming %u samples, %d seconds in the future...")
+ % total_num_samps % seconds_in_future << std::endl;
+ uhd::stream_cmd_t stream_cmd;
+ stream_cmd.stream_now = false;
+ stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future);
+ stream_cmd.continuous = false;
+ stream_cmd.num_samps = total_num_samps;
+ sdev->issue_stream_cmd(stream_cmd);
+
+ //loop until total number of samples reached
+ size_t num_acc_samps = 0; //number of accumulated samples
+ while(num_acc_samps < total_num_samps){
+ uhd::rx_metadata_t md;
+ std::complex<float> buff[1000];
+ size_t num_rx_samps = dev->recv(
+ boost::asio::buffer(buff, sizeof(buff)),
+ md, uhd::io_type_t::COMPLEX_FLOAT32
+ );
+ if (num_rx_samps == 0) continue; //wait for packets with contents
+
+ std::cout << boost::format("Got packet: %u samples, %u secs, %u ticks")
+ % num_rx_samps % md.time_spec.secs % md.time_spec.ticks << std::endl;
+
+ num_acc_samps += num_rx_samps;
+ }
+
+ //finished
+ std::cout << std::endl << "Done!" << std::endl << std::endl;
+
+ return 0;
+}
diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt
index 3d00462cf..b364f78cd 100644
--- a/host/include/uhd/CMakeLists.txt
+++ b/host/include/uhd/CMakeLists.txt
@@ -17,20 +17,15 @@
ADD_SUBDIRECTORY(transport)
+ADD_SUBDIRECTORY(types)
ADD_SUBDIRECTORY(usrp)
+ADD_SUBDIRECTORY(utils)
INSTALL(FILES
config.hpp
device.hpp
- device_addr.hpp
- dict.hpp
- gain_handler.hpp
- metadata.hpp
props.hpp
simple_device.hpp
- time_spec.hpp
- types.hpp
- utils.hpp
wax.hpp
- DESTINATION ${HEADER_DIR}/uhd
+ DESTINATION ${INCLUDE_DIR}/uhd
)
diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp
index 10f9c093f..941219ac7 100644
--- a/host/include/uhd/config.hpp
+++ b/host/include/uhd/config.hpp
@@ -1,76 +1,83 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_CONFIG_HPP
-#define INCLUDED_UHD_CONFIG_HPP
-
-// suppress warnings
-#include <boost/config.hpp>
-#ifdef BOOST_MSVC
-# pragma warning(push)
-//# pragma warning(disable: 4511) // copy constructor can't not be generated
-//# pragma warning(disable: 4512) // assignment operator can't not be generated
-//# pragma warning(disable: 4100) // unreferenced formal parameter
-//# pragma warning(disable: 4996) // <symbol> was declared deprecated
-//# pragma warning(disable: 4355) // 'this' : used in base member initializer list
-//# pragma warning(disable: 4706) // assignment within conditional expression
-# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B'
-//# pragma warning(disable: 4127) // conditional expression is constant
-//# pragma warning(disable: 4290) // C++ exception specification ignored except to ...
-//# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored
-# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ...
-//# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
-//# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated
-#endif
-
-// http://gcc.gnu.org/wiki/Visibility
-// Generic helper definitions for shared library support
-#if defined _WIN32 || defined __CYGWIN__
- #define UHD_HELPER_DLL_IMPORT __declspec(dllimport)
- #define UHD_HELPER_DLL_EXPORT __declspec(dllexport)
- #define UHD_HELPER_DLL_LOCAL
-#else
- #if __GNUC__ >= 4
- #define UHD_HELPER_DLL_IMPORT __attribute__ ((visibility("default")))
- #define UHD_HELPER_DLL_EXPORT __attribute__ ((visibility("default")))
- #define UHD_HELPER_DLL_LOCAL __attribute__ ((visibility("hidden")))
- #else
- #define UHD_HELPER_DLL_IMPORT
- #define UHD_HELPER_DLL_EXPORT
- #define UHD_HELPER_DLL_LOCAL
- #endif
-#endif
-
-// Now we use the generic helper definitions above to define UHD_API and UHD_LOCAL.
-// UHD_API is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build)
-// UHD_LOCAL is used for non-api symbols.
-
-#define UHD_DLL // defined here, put into configuration if we need to make static libs
-
-#ifdef UHD_DLL // defined if UHD is compiled as a DLL
- #ifdef UHD_DLL_EXPORTS // defined if we are building the UHD DLL (instead of using it)
- #define UHD_API UHD_HELPER_DLL_EXPORT
- #else
- #define UHD_API UHD_HELPER_DLL_IMPORT
- #endif // UHD_DLL_EXPORTS
- #define UHD_LOCAL UHD_HELPER_DLL_LOCAL
-#else // UHD_DLL is not defined: this means UHD is a static lib.
- #define UHD_API
- #define UHD_LOCAL
-#endif // UHD_DLL
-
-#endif /* INCLUDED_UHD_CONFIG_HPP */
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_CONFIG_HPP
+#define INCLUDED_UHD_CONFIG_HPP
+
+// suppress warnings
+#include <boost/config.hpp>
+#ifdef BOOST_MSVC
+//# pragma warning(push)
+//# pragma warning(disable: 4511) // copy constructor can't not be generated
+//# pragma warning(disable: 4512) // assignment operator can't not be generated
+//# pragma warning(disable: 4100) // unreferenced formal parameter
+//# pragma warning(disable: 4996) // <symbol> was declared deprecated
+//# pragma warning(disable: 4355) // 'this' : used in base member initializer list
+//# pragma warning(disable: 4706) // assignment within conditional expression
+# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B'
+//# pragma warning(disable: 4127) // conditional expression is constant
+//# pragma warning(disable: 4290) // C++ exception specification ignored except to ...
+//# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored
+# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ...
+//# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
+//# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated
+#endif
+
+//define logical operators
+#ifdef BOOST_MSVC
+ #define not !
+ #define and &&
+ #define or ||
+#endif
+
+// http://gcc.gnu.org/wiki/Visibility
+// Generic helper definitions for shared library support
+#if defined _WIN32 || defined __CYGWIN__
+ #define UHD_HELPER_DLL_IMPORT __declspec(dllimport)
+ #define UHD_HELPER_DLL_EXPORT __declspec(dllexport)
+ #define UHD_HELPER_DLL_LOCAL
+#else
+ #if __GNUC__ >= 4
+ #define UHD_HELPER_DLL_IMPORT __attribute__ ((visibility("default")))
+ #define UHD_HELPER_DLL_EXPORT __attribute__ ((visibility("default")))
+ #define UHD_HELPER_DLL_LOCAL __attribute__ ((visibility("hidden")))
+ #else
+ #define UHD_HELPER_DLL_IMPORT
+ #define UHD_HELPER_DLL_EXPORT
+ #define UHD_HELPER_DLL_LOCAL
+ #endif
+#endif
+
+// Now we use the generic helper definitions above to define UHD_API and UHD_LOCAL.
+// UHD_API is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build)
+// UHD_LOCAL is used for non-api symbols.
+
+#define UHD_DLL // defined here, put into configuration if we need to make static libs
+
+#ifdef UHD_DLL // defined if UHD is compiled as a DLL
+ #ifdef UHD_DLL_EXPORTS // defined if we are building the UHD DLL (instead of using it)
+ #define UHD_API UHD_HELPER_DLL_EXPORT
+ #else
+ #define UHD_API UHD_HELPER_DLL_IMPORT
+ #endif // UHD_DLL_EXPORTS
+ #define UHD_LOCAL UHD_HELPER_DLL_LOCAL
+#else // UHD_DLL is not defined: this means UHD is a static lib.
+ #define UHD_API
+ #define UHD_LOCAL
+#endif // UHD_DLL
+
+#endif /* INCLUDED_UHD_CONFIG_HPP */
diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp
index 13b40febe..4d4196d98 100644
--- a/host/include/uhd/device.hpp
+++ b/host/include/uhd/device.hpp
@@ -19,9 +19,9 @@
#define INCLUDED_UHD_DEVICE_HPP
#include <uhd/config.hpp>
-#include <uhd/device_addr.hpp>
-#include <uhd/props.hpp>
-#include <uhd/metadata.hpp>
+#include <uhd/types/device_addr.hpp>
+#include <uhd/types/metadata.hpp>
+#include <uhd/types/io_type.hpp>
#include <uhd/wax.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
@@ -38,22 +38,22 @@ class UHD_API device : boost::noncopyable, public wax::obj{
public:
typedef boost::shared_ptr<device> sptr;
- typedef boost::function<device_addrs_t(const device_addr_t &)> discover_t;
+ typedef boost::function<device_addrs_t(const device_addr_t &)> find_t;
typedef boost::function<sptr(const device_addr_t &)> make_t;
/*!
* Register a device into the discovery and factory system.
*
- * \param discover a function that discovers devices
+ * \param find a function that discovers devices
* \param make a factory function that makes a device
*/
static void register_device(
- const discover_t &discover,
+ const find_t &find,
const make_t &make
);
/*!
- * \brief Discover usrp devices attached to the host.
+ * \brief Find usrp devices attached to the host.
*
* The hint device address should be used to narrow down the search
* to particular transport types and/or transport arguments.
@@ -61,17 +61,17 @@ public:
* \param hint a partially (or fully) filled in device address
* \return a vector of device addresses for all usrps on the system
*/
- static device_addrs_t discover(const device_addr_t &hint);
+ static device_addrs_t find(const device_addr_t &hint);
/*!
* \brief Create a new usrp device from the device address hint.
*
- * The make routine will call discover and pick one of the results.
+ * The make routine will call find and pick one of the results.
* By default, the first result will be used to create a new device.
* Use the which parameter as an index into the list of results.
*
* \param hint a partially (or fully) filled in device address
- * \param which which address to use when multiple are discovered
+ * \param which which address to use when multiple are found
* \return a shared pointer to a new device instance
*/
static sptr make(const device_addr_t &hint, size_t which = 0);
@@ -91,13 +91,13 @@ public:
*
* \param buff a buffer pointing to some read-only memory
* \param metadata data describing the buffer's contents
- * \param the type of data loaded in the buffer (32fc, 16sc)
+ * \param io_type the type of data loaded in the buffer
* \return the number of samples sent
*/
virtual size_t send(
const boost::asio::const_buffer &buff,
const tx_metadata_t &metadata,
- const std::string &type = "32fc"
+ const io_type_t &io_type
) = 0;
/*!
@@ -123,13 +123,13 @@ public:
*
* \param buff the buffer to fill with IF data
* \param metadata data to fill describing the buffer
- * \param the type of data to fill into the buffer (32fc, 16sc)
+ * \param io_type the type of data to fill into the buffer
* \return the number of samples received
*/
virtual size_t recv(
const boost::asio::mutable_buffer &buff,
rx_metadata_t &metadata,
- const std::string &type = "32fc"
+ const io_type_t &io_type
) = 0;
};
diff --git a/host/include/uhd/device_addr.hpp b/host/include/uhd/device_addr.hpp
deleted file mode 100644
index 7673faff0..000000000
--- a/host/include/uhd/device_addr.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_DEVICE_ADDR_HPP
-#define INCLUDED_UHD_DEVICE_ADDR_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/dict.hpp>
-#include <boost/cstdint.hpp>
-#include <string>
-#include <iostream>
-#include <vector>
-
-namespace uhd{
-
- /*!
- * Wrapper for an ethernet mac address.
- * Provides conversion between string and binary formats.
- */
- struct UHD_API mac_addr_t{
- boost::uint8_t mac_addr[6];
- mac_addr_t(const std::string &mac_addr_str = "00:00:00:00:00:00");
- std::string to_string(void) const;
- };
-
- /*!
- * The device address args are just a mapping of key/value string pairs.
- * When left empty, the discovery routine will try to find all usrps.
- * The discovery can be narrowed down by specifying the transport type arguments.
- *
- * For example, to access a specific usrp2 one would specify the transport type
- * ("type", "udp") and the transport args ("addr", "<resolvable_hostname_or_addr>").
- */
- typedef dict<std::string, std::string> device_addr_t;
- typedef std::vector<device_addr_t> device_addrs_t;
-
- /*!
- * Function to turn a device address into a string.
- * Just having the operator<< below should be sufficient.
- * However, boost format seems to complain with the %
- * and this is just easier because it works.
- * \param device_addr a device address instance
- * \return the string representation
- */
- namespace device_addr{
- UHD_API std::string to_string(const device_addr_t &device_addr);
- }
-
-} //namespace uhd
-
-//ability to use types with stream operators
-UHD_API std::ostream& operator<<(std::ostream &, const uhd::device_addr_t &);
-UHD_API std::ostream& operator<<(std::ostream &, const uhd::mac_addr_t &);
-
-#endif /* INCLUDED_UHD_DEVICE_ADDR_HPP */
diff --git a/host/include/uhd/metadata.hpp b/host/include/uhd/metadata.hpp
deleted file mode 100644
index 6d80f070d..000000000
--- a/host/include/uhd/metadata.hpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_METADATA_HPP
-#define INCLUDED_UHD_METADATA_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/time_spec.hpp>
-
-namespace uhd{
-
-/*!
- * RX metadata structure for describing sent IF data.
- * Includes stream ID, time specification, and fragmentation flags.
- * The receive routines will convert IF data headers into metadata.
- */
-struct UHD_API rx_metadata_t{
- boost::uint32_t stream_id;
- time_spec_t time_spec;
- bool has_stream_id;
- bool has_time_spec;
- bool is_fragment;
-
- //default constructor
- rx_metadata_t(void);
-};
-
-/*!
- * TX metadata structure for describing received IF data.
- * Includes stream ID, time specification, and burst flags.
- * The send routines will convert the metadata to IF data headers.
- */
-struct UHD_API tx_metadata_t{
- boost::uint32_t stream_id;
- time_spec_t time_spec;
- bool has_stream_id;
- bool has_time_spec;
- bool start_of_burst;
- bool end_of_burst;
-
- //default constructor
- tx_metadata_t(void);
-};
-
-} //namespace uhd
-
-#endif /* INCLUDED_UHD_METADATA_HPP */
diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp
index 41e0eff63..01746f853 100644
--- a/host/include/uhd/props.hpp
+++ b/host/include/uhd/props.hpp
@@ -76,8 +76,6 @@ namespace uhd{
MBOARD_PROP_TX_DBOARD, //ro, wax::obj
MBOARD_PROP_TX_DBOARD_NAMES, //ro, prop_names_t
MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t
- MBOARD_PROP_PPS_SOURCE_NAMES, //ro, prop_names_t
- MBOARD_PROP_REF_SOURCE_NAMES, //ro, prop_names_t
MBOARD_PROP_TIME_NOW, //wo, time_spec_t
MBOARD_PROP_TIME_NEXT_PPS //wo, time_spec_t
};
diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp
index ad25eccdc..52928367a 100644
--- a/host/include/uhd/simple_device.hpp
+++ b/host/include/uhd/simple_device.hpp
@@ -20,7 +20,9 @@
#include <uhd/config.hpp>
#include <uhd/device.hpp>
-#include <uhd/types.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/tune_result.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <vector>
@@ -43,10 +45,15 @@ public:
virtual std::string get_name(void) = 0;
/*******************************************************************
+ * Timing
+ ******************************************************************/
+ virtual void set_time_now(const time_spec_t &time_spec) = 0;
+ virtual void set_time_next_pps(const time_spec_t &time_spec) = 0;
+
+ /*******************************************************************
* Streaming
******************************************************************/
- virtual void set_streaming(bool enb) = 0;
- virtual bool get_streaming(void) = 0;
+ virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0;
/*******************************************************************
* RX methods
diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt
index 7f5db2128..14b5ccd29 100644
--- a/host/include/uhd/transport/CMakeLists.txt
+++ b/host/include/uhd/transport/CMakeLists.txt
@@ -17,9 +17,10 @@
INSTALL(FILES
+ if_addrs.hpp
smart_buffer.hpp
udp_simple.hpp
udp_zero_copy.hpp
vrt.hpp
- DESTINATION ${HEADER_DIR}/uhd/transport
+ DESTINATION ${INCLUDE_DIR}/uhd/transport
)
diff --git a/host/lib/metadata.cpp b/host/include/uhd/transport/if_addrs.hpp
index 40fdb7c73..fbbb35e1d 100644
--- a/host/lib/metadata.cpp
+++ b/host/include/uhd/transport/if_addrs.hpp
@@ -15,23 +15,33 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/metadata.hpp>
-
-using namespace uhd;
-
-rx_metadata_t::rx_metadata_t(void){
- stream_id = 0;
- has_stream_id = false;
- time_spec = time_spec_t();
- has_time_spec = false;
- is_fragment = false;
-}
-
-tx_metadata_t::tx_metadata_t(void){
- stream_id = 0;
- has_stream_id = false;
- time_spec = time_spec_t();
- has_time_spec = false;
- start_of_burst = false;
- end_of_burst = false;
-}
+#ifndef INCLUDED_UHD_IFADDRS_HPP
+#define INCLUDED_UHD_IFADDRS_HPP
+
+#include <uhd/config.hpp>
+#include <string>
+#include <vector>
+
+namespace uhd{ namespace transport{
+
+ /*!
+ * The address for a network interface.
+ */
+ struct UHD_API if_addrs_t{
+ std::string inet;
+ std::string mask;
+ std::string bcast;
+ if_addrs_t(void);
+ };
+
+ /*!
+ * Get a list of network interface addresses.
+ * The internal implementation is system-dependent.
+ * \return a vector of if addrs
+ */
+ UHD_API std::vector<if_addrs_t> get_if_addrs(void);
+
+}} //namespace
+
+
+#endif /* INCLUDED_UHD_IFADDRS_HPP */
diff --git a/host/include/uhd/transport/smart_buffer.hpp b/host/include/uhd/transport/smart_buffer.hpp
index 9e1032feb..a9bc259e9 100644
--- a/host/include/uhd/transport/smart_buffer.hpp
+++ b/host/include/uhd/transport/smart_buffer.hpp
@@ -18,7 +18,7 @@
#ifndef INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP
#define INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP
-#include <boost/asio.hpp>
+#include <boost/asio/buffer.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp
index 40e60d091..793ec4fd7 100644
--- a/host/include/uhd/transport/udp_simple.hpp
+++ b/host/include/uhd/transport/udp_simple.hpp
@@ -19,7 +19,7 @@
#define INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP
#include <uhd/config.hpp>
-#include <boost/asio.hpp>
+#include <boost/asio/buffer.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp
index 03d89b3a5..0441a8e74 100644
--- a/host/include/uhd/transport/udp_zero_copy.hpp
+++ b/host/include/uhd/transport/udp_zero_copy.hpp
@@ -20,7 +20,7 @@
#include <uhd/config.hpp>
#include <uhd/transport/smart_buffer.hpp>
-#include <boost/asio.hpp>
+#include <boost/asio/buffer.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp
index db2c57eba..04945b347 100644
--- a/host/include/uhd/transport/vrt.hpp
+++ b/host/include/uhd/transport/vrt.hpp
@@ -19,7 +19,7 @@
#define INCLUDED_UHD_TRANSPORT_VRT_HPP
#include <uhd/config.hpp>
-#include <uhd/metadata.hpp>
+#include <uhd/types/metadata.hpp>
#include <cstddef>
namespace uhd{ namespace transport{
diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt
new file mode 100644
index 000000000..e4cdf2cef
--- /dev/null
+++ b/host/include/uhd/types/CMakeLists.txt
@@ -0,0 +1,32 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+
+INSTALL(FILES
+ clock_config.hpp
+ device_addr.hpp
+ dict.hpp
+ io_type.hpp
+ mac_addr.hpp
+ metadata.hpp
+ otw_type.hpp
+ ranges.hpp
+ stream_cmd.hpp
+ time_spec.hpp
+ tune_result.hpp
+ DESTINATION ${INCLUDE_DIR}/uhd/types
+)
diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp
new file mode 100644
index 000000000..42d74ad90
--- /dev/null
+++ b/host/include/uhd/types/clock_config.hpp
@@ -0,0 +1,50 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP
+#define INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP
+
+#include <uhd/config.hpp>
+
+namespace uhd{
+
+ /*!
+ * Clock configuration settings:
+ * The source for the 10MHz reference clock.
+ * The source and polarity for the PPS clock.
+ */
+ struct UHD_API clock_config_t{
+ enum ref_source_t {
+ REF_INT = 'i', //internal reference
+ REF_SMA = 's', //external sma port
+ REF_MIMO = 'm' //mimo cable (usrp2 only)
+ } ref_source;
+ enum pps_source_t {
+ PPS_INT = 'i', //there is no internal
+ PPS_SMA = 's', //external sma port
+ PPS_MIMO = 'm' //mimo cable (usrp2 only)
+ } pps_source;
+ enum pps_polarity_t {
+ PPS_NEG = 'n', //negative edge
+ PPS_POS = 'p' //positive edge
+ } pps_polarity;
+ clock_config_t(void);
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP */
diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp
new file mode 100644
index 000000000..1162884fb
--- /dev/null
+++ b/host/include/uhd/types/device_addr.hpp
@@ -0,0 +1,70 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP
+#define INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/dict.hpp>
+#include <vector>
+#include <string>
+
+namespace uhd{
+
+ /*!
+ * Mapping of key/value pairs for locating devices on the system.
+ * When left empty, the device discovery routines will search
+ * all available transports on the system (ethernet, usb...).
+ *
+ * To narrow down the discovery process to a particular device,
+ * specify a transport key/value pair specific to your device.
+ * Ex, to find a usrp2: my_dev_addr["addr"] = <resolvable_hostname_or_ip>
+ *
+ * The device address can also be used to pass arguments into
+ * the transport layer control to set (for example) buffer sizes.
+ */
+ class UHD_API device_addr_t : public dict<std::string, std::string>{
+ public:
+
+ /*!
+ * Convert a device address into a printable string.
+ * \return string good for use with std::cout <<
+ */
+ std::string to_string(void) const;
+
+ /*!
+ * Convert the device address into an args string.
+ * The args string contains delimiter symbols.
+ * \return a string with delimiter markup
+ */
+ std::string to_args_str(void) const;
+
+ /*!
+ * Make a device address from an args string.
+ * The args string contains delimiter symbols.
+ * \param args_str the arguments string
+ * \return the new device address
+ */
+ static device_addr_t from_args_str(const std::string &args_str);
+ };
+
+ //handy typedef for a vector of device addresses
+ typedef std::vector<device_addr_t> device_addrs_t;
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP */
diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/types/dict.hpp
index f08493952..7fb712e76 100644
--- a/host/include/uhd/dict.hpp
+++ b/host/include/uhd/types/dict.hpp
@@ -15,13 +15,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#ifndef INCLUDED_UHD_DICT_HPP
-#define INCLUDED_UHD_DICT_HPP
+#ifndef INCLUDED_UHD_TYPES_DICT_HPP
+#define INCLUDED_UHD_TYPES_DICT_HPP
-#include <list>
-#include <vector>
-#include <stdexcept>
+#include <uhd/config.hpp>
#include <boost/foreach.hpp>
+#include <stdexcept>
+#include <vector>
+#include <list>
namespace uhd{
@@ -151,4 +152,4 @@ namespace uhd{
} //namespace uhd
-#endif /* INCLUDED_UHD_DICT_HPP */
+#endif /* INCLUDED_UHD_TYPES_DICT_HPP */
diff --git a/host/include/uhd/types/io_type.hpp b/host/include/uhd/types/io_type.hpp
new file mode 100644
index 000000000..930394d1b
--- /dev/null
+++ b/host/include/uhd/types/io_type.hpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_IO_TYPE_HPP
+#define INCLUDED_UHD_TYPES_IO_TYPE_HPP
+
+#include <uhd/config.hpp>
+
+namespace uhd{
+
+ /*!
+ * Used to specify the IO type with device send/recv.
+ */
+ class UHD_API io_type_t{
+ public:
+
+ /*!
+ * Built in IO types known to the system.
+ */
+ enum tid_t{
+ CUSTOM_TYPE = '?',
+ COMPLEX_FLOAT32 = 'f',
+ COMPLEX_INT16 = 's',
+ COMPLEX_INT8 = 'b'
+ };
+
+ /*!
+ * The size of this io type in bytes.
+ */
+ const size_t size;
+
+ /*!
+ * The type id of this io type.
+ * Good for using with switch statements.
+ */
+ const tid_t tid;
+
+ /*!
+ * Create an io type from a built-in type id.
+ * \param tid a type id known to the system
+ */
+ io_type_t(tid_t tid);
+
+ /*!
+ * Create an io type from attributes.
+ * The tid will be set to custom.
+ * \param size the size in bytes
+ */
+ io_type_t(size_t size);
+
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */
diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp
new file mode 100644
index 000000000..3cd1fe86b
--- /dev/null
+++ b/host/include/uhd/types/mac_addr.hpp
@@ -0,0 +1,68 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_MAC_ADDR_HPP
+#define INCLUDED_UHD_TYPES_MAC_ADDR_HPP
+
+#include <uhd/config.hpp>
+#include <boost/cstdint.hpp>
+#include <string>
+
+namespace uhd{
+
+ /*!
+ * Wrapper for an ethernet mac address.
+ * Provides conversion between string and binary formats.
+ */
+ class UHD_API mac_addr_t{
+ public:
+ static const size_t hlen = 6;
+
+ /*!
+ * Create a mac address a byte array.
+ * \param bytes a pointer for the byte array
+ * \return a new mac address
+ */
+ static mac_addr_t from_bytes(const boost::uint8_t *bytes);
+
+ /*!
+ * Create a mac address from a string.
+ * \param mac_addr_str the string with delimiters
+ * \return a new mac address
+ */
+ static mac_addr_t from_string(const std::string &mac_addr_str);
+
+ /*!
+ * Get the byte representation of the mac address.
+ * \return a pointer to the internal byte array
+ */
+ const boost::uint8_t *to_bytes(void) const;
+
+ /*!
+ * Get the string representation of this mac address.
+ * \return a string with delimiters
+ */
+ std::string to_string(void) const;
+
+ private:
+ mac_addr_t(const boost::uint8_t *bytes); //private constructor
+ boost::uint8_t _bytes[hlen]; //internal representation
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_MAC_ADDR_HPP */
diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp
new file mode 100644
index 000000000..6e93040d9
--- /dev/null
+++ b/host/include/uhd/types/metadata.hpp
@@ -0,0 +1,61 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_METADATA_HPP
+#define INCLUDED_UHD_TYPES_METADATA_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/time_spec.hpp>
+
+namespace uhd{
+
+ /*!
+ * RX metadata structure for describing sent IF data.
+ * Includes stream ID, time specification, and fragmentation flags.
+ * The receive routines will convert IF data headers into metadata.
+ */
+ struct UHD_API rx_metadata_t{
+ boost::uint32_t stream_id;
+ time_spec_t time_spec;
+ bool has_stream_id;
+ bool has_time_spec;
+ bool is_fragment;
+
+ //default constructor
+ rx_metadata_t(void);
+ };
+
+ /*!
+ * TX metadata structure for describing received IF data.
+ * Includes stream ID, time specification, and burst flags.
+ * The send routines will convert the metadata to IF data headers.
+ */
+ struct UHD_API tx_metadata_t{
+ boost::uint32_t stream_id;
+ time_spec_t time_spec;
+ bool has_stream_id;
+ bool has_time_spec;
+ bool start_of_burst;
+ bool end_of_burst;
+
+ //default constructor
+ tx_metadata_t(void);
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_METADATA_HPP */
diff --git a/host/include/uhd/types/otw_type.hpp b/host/include/uhd/types/otw_type.hpp
new file mode 100644
index 000000000..f10664584
--- /dev/null
+++ b/host/include/uhd/types/otw_type.hpp
@@ -0,0 +1,63 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_OTW_TYPE_HPP
+#define INCLUDED_UHD_TYPES_OTW_TYPE_HPP
+
+#include <uhd/config.hpp>
+
+namespace uhd{
+
+ /*!
+ * Description for over-the-wire integers:
+ * The DSP units in the FPGA deal with signed 16-bit integers.
+ * The width and shift define the translation between OTW and DSP,
+ * defined by the following relation: otw_int = dsp_int >> shift
+ *
+ * Note: possible combinations of width, shift, and byteorder
+ * depend on the internals of the FPGA. Not all are supported!
+ */
+ struct UHD_API otw_type_t{
+
+ /*!
+ * Width of an over-the-wire integer in bits.
+ */
+ size_t width; //in bits
+
+ /*!
+ * Shift of an over-the-wire integer in bits.
+ * otw_int = dsp_int >> shift
+ * dsp_int = otw_int << shift
+ */
+ size_t shift; //in bits
+
+ /*!
+ * Constants for byte order (borrowed from numpy's dtype)
+ */
+ enum /*bo_t*/ {
+ BO_NATIVE = '=',
+ BO_LITTLE_ENDIAN = '<',
+ BO_BIG_ENDIAN = '>',
+ BO_NOT_APPLICABLE = '|'
+ } byteorder;
+
+ otw_type_t(void);
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */
diff --git a/host/include/uhd/types.hpp b/host/include/uhd/types/ranges.hpp
index 1439f57a1..a2057d1c8 100644
--- a/host/include/uhd/types.hpp
+++ b/host/include/uhd/types/ranges.hpp
@@ -15,17 +15,13 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#ifndef INCLUDED_UHD_TYPES_HPP
-#define INCLUDED_UHD_TYPES_HPP
+#ifndef INCLUDED_UHD_TYPES_RANGES_HPP
+#define INCLUDED_UHD_TYPES_RANGES_HPP
#include <uhd/config.hpp>
-#include <string>
namespace uhd{
- typedef float gain_t; //TODO REMOVE
- typedef double freq_t; //TODO REMOVE
-
/*!
* The gain range struct describes possible gain settings.
* The mimumum gain, maximum gain, and step size are in dB.
@@ -45,39 +41,6 @@ namespace uhd{
freq_range_t(double min = 0.0, double max = 0.0);
};
- /*!
- * The tune result struct holds result of a 2-phase tuning:
- * The struct hold the result of tuning the dboard as
- * the target and actual intermediate frequency.
- * The struct hold the result of tuning the DDC/DUC as
- * the target and actual digital converter frequency.
- * It also tell us weather or not the spectrum is inverted.
- */
- struct UHD_API tune_result_t{
- double target_inter_freq;
- double actual_inter_freq;
- double target_dxc_freq;
- double actual_dxc_freq;
- bool spectrum_inverted;
- tune_result_t(void);
- };
-
- /*!
- * Clock configuration settings:
- * The source for the 10MHz reference clock.
- * The source and polarity for the PPS clock.
- * Possible settings for the reference and pps source
- * are implementation specific motherboard properties.
- * See the MBOARD_PROP_XXX_SOURCE_NAMES properties.
- */
- struct clock_config_t{
- enum polarity_t {POLARITY_NEG, POLARITY_POS};
- std::string ref_source;
- std::string pps_source;
- polarity_t pps_polarity;
- clock_config_t(void);
- };
-
} //namespace uhd
-#endif /* INCLUDED_UHD_TYPES_HPP */
+#endif /* INCLUDED_UHD_TYPES_RANGES_HPP */
diff --git a/host/include/uhd/types/stream_cmd.hpp b/host/include/uhd/types/stream_cmd.hpp
new file mode 100644
index 000000000..97a6b73ce
--- /dev/null
+++ b/host/include/uhd/types/stream_cmd.hpp
@@ -0,0 +1,56 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_STREAM_CMD_HPP
+#define INCLUDED_UHD_TYPES_STREAM_CMD_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/time_spec.hpp>
+
+namespace uhd{
+
+ /*!
+ * Command struct for configuration and control of streaming:
+ *
+ * A stream command defines how the device sends samples to the host.
+ * Streaming is controlled by submitting a stream command to the rx dsp.
+ * Granular control over what the device streams to the host can be
+ * achieved through submission of multiple (carefully-crafted) commands.
+ *
+ * The stream_now parameter controls when the stream begins.
+ * When true, the device will begin streaming ASAP. When false,
+ * the device will begin streaming at a time specified by time_spec.
+ *
+ * The continuous parameter controls the number of samples received.
+ * When true, the device continues streaming indefinitely. When false,
+ * the device will stream the number of samples specified by num_samps.
+ *
+ * Standard usage case:
+ * To start continuous streaming, set stream_now to true and continuous to true.
+ * To end continuous streaming, set stream_now to true and continuous to false.
+ */
+ struct UHD_API stream_cmd_t{
+ bool stream_now;
+ time_spec_t time_spec;
+ bool continuous;
+ size_t num_samps;
+ stream_cmd_t(void);
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_STREAM_CMD_HPP */
diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/types/time_spec.hpp
index c1e7cf3a1..8c8f2bc25 100644
--- a/host/include/uhd/time_spec.hpp
+++ b/host/include/uhd/types/time_spec.hpp
@@ -15,8 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#ifndef INCLUDED_UHD_TIME_SPEC_HPP
-#define INCLUDED_UHD_TIME_SPEC_HPP
+#ifndef INCLUDED_UHD_TYPES_TIME_SPEC_HPP
+#define INCLUDED_UHD_TYPES_TIME_SPEC_HPP
#include <uhd/config.hpp>
#include <boost/cstdint.hpp>
@@ -35,17 +35,11 @@ namespace uhd{
boost::uint32_t ticks;
/*!
- * Create a time_spec_t that holds a wildcard time.
- * This will have implementation-specific meaning.
- */
- time_spec_t(void);
-
- /*!
* Create a time_spec_t from seconds and ticks.
- * \param new_secs the new seconds
+ * \param new_secs the new seconds (default = 0)
* \param new_ticks the new ticks (default = 0)
*/
- time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks = 0);
+ time_spec_t(boost::uint32_t new_secs = 0, boost::uint32_t new_ticks = 0);
/*!
* Create a time_spec_t from boost posix time.
@@ -58,4 +52,4 @@ namespace uhd{
} //namespace uhd
-#endif /* INCLUDED_UHD_TIME_SPEC_HPP */
+#endif /* INCLUDED_UHD_TYPES_TIME_SPEC_HPP */
diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp
new file mode 100644
index 000000000..31742e1af
--- /dev/null
+++ b/host/include/uhd/types/tune_result.hpp
@@ -0,0 +1,44 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_TUNE_RESULT_HPP
+#define INCLUDED_UHD_TYPES_TUNE_RESULT_HPP
+
+#include <uhd/config.hpp>
+
+namespace uhd{
+
+ /*!
+ * The tune result struct holds result of a 2-phase tuning:
+ * The struct hold the result of tuning the dboard as
+ * the target and actual intermediate frequency.
+ * The struct hold the result of tuning the DDC/DUC as
+ * the target and actual digital converter frequency.
+ * It also tell us weather or not the spectrum is inverted.
+ */
+ struct UHD_API tune_result_t{
+ double target_inter_freq;
+ double actual_inter_freq;
+ double target_dxc_freq;
+ double actual_dxc_freq;
+ bool spectrum_inverted;
+ tune_result_t(void);
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_TUNE_RESULT_HPP */
diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt
index 4e0a92365..bab01fdeb 100644
--- a/host/include/uhd/usrp/CMakeLists.txt
+++ b/host/include/uhd/usrp/CMakeLists.txt
@@ -23,5 +23,5 @@ INSTALL(FILES
dboard_manager.hpp
usrp1e.hpp
usrp2.hpp
- DESTINATION ${HEADER_DIR}/uhd/usrp
+ DESTINATION ${INCLUDE_DIR}/uhd/usrp
)
diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp
index 4b2392bee..afacaf8ff 100644
--- a/host/include/uhd/usrp/dboard_id.hpp
+++ b/host/include/uhd/usrp/dboard_id.hpp
@@ -26,8 +26,6 @@ namespace uhd{ namespace usrp{
typedef boost::uint16_t dboard_id_t;
-static const dboard_id_t ID_NONE = 0xffff; //TODO: REMOVE ME
-
namespace dboard_id{
static const dboard_id_t NONE = 0xffff;
UHD_API std::string to_string(const dboard_id_t &id);
diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp
index 6a105d1de..c7c091220 100644
--- a/host/include/uhd/usrp/dboard_manager.hpp
+++ b/host/include/uhd/usrp/dboard_manager.hpp
@@ -42,7 +42,7 @@ public:
/*!
* Register a dboard into the system.
- *
+ * For single subdevice boards, omit subdev_names.
* \param dboard_id the dboard id (rx or tx)
* \param dboard_ctor the dboard constructor function pointer
* \param name the canonical name for the dboard represented
@@ -52,7 +52,7 @@ public:
dboard_id_t dboard_id,
dboard_ctor_t dboard_ctor,
const std::string &name,
- const prop_names_t &subdev_names
+ const prop_names_t &subdev_names = prop_names_t(1, "")
);
/*!
diff --git a/host/include/uhd/usrp/usrp1e.hpp b/host/include/uhd/usrp/usrp1e.hpp
index f4cc39d8e..75da58453 100644
--- a/host/include/uhd/usrp/usrp1e.hpp
+++ b/host/include/uhd/usrp/usrp1e.hpp
@@ -29,12 +29,11 @@ namespace uhd{ namespace usrp{
class UHD_API usrp1e : public device{
public:
/*!
- * Discover usrp1e devices on the system via the device node.
- * This static method will be called by the device::discover.
+ * Find usrp1e devices on the system via the device node.
* \param hint a device addr with the usrp1e address filled in
* \return a vector of device addresses for all usrp1es found
*/
- static device_addrs_t discover(const device_addr_t &hint);
+ static device_addrs_t find(const device_addr_t &hint);
/*!
* Make a usrp1e from a device address.
diff --git a/host/include/uhd/usrp/usrp2.hpp b/host/include/uhd/usrp/usrp2.hpp
index 277ddc131..613b40ae3 100644
--- a/host/include/uhd/usrp/usrp2.hpp
+++ b/host/include/uhd/usrp/usrp2.hpp
@@ -29,17 +29,16 @@ namespace uhd{ namespace usrp{
class UHD_API usrp2 : public device{
public:
/*!
- * Discover usrp2 devices over the ethernet.
+ * Find usrp2 devices over the ethernet.
*
* Recommended key/value pairs for the device hint address:
* hint["addr"] = address, where address is a resolvable address
* or ip address, which may or may not be a broadcast address.
*
- * This static method will be called by the device::discover.
* \param hint a device addr with the usrp2 address filled in
* \return a vector of device addresses for all usrp2s found
*/
- static device_addrs_t discover(const device_addr_t &hint);
+ static device_addrs_t find(const device_addr_t &hint);
/*!
* Make a usrp2 from a device address.
diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt
new file mode 100644
index 000000000..1b673f44a
--- /dev/null
+++ b/host/include/uhd/utils/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+INSTALL(FILES
+ algorithm.hpp
+ assert.hpp
+ gain_handler.hpp
+ safe_main.hpp
+ static.hpp
+ tune_helper.hpp
+ DESTINATION ${INCLUDE_DIR}/uhd/utils
+)
diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp
new file mode 100644
index 000000000..6635c8a4a
--- /dev/null
+++ b/host/include/uhd/utils/algorithm.hpp
@@ -0,0 +1,60 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_UTILS_ALGORITHM_HPP
+#define INCLUDED_UHD_UTILS_ALGORITHM_HPP
+
+#include <algorithm>
+
+/*!
+ * Useful templated functions and classes that I like to pretend are part of stl
+ */
+namespace std{
+
+ template<class T, class InputIterator, class Function>
+ T reduce(InputIterator first, InputIterator last, Function fcn, T init = 0){
+ T tmp = init;
+ for ( ; first != last; ++first ){
+ tmp = fcn(tmp, *first);
+ }
+ return tmp;
+ }
+
+ template<class T, class Iterable, class Function>
+ T reduce(Iterable iterable, Function fcn, T init = 0){
+ return reduce(iterable.begin(), iterable.end(), fcn, init);
+ }
+
+ template<class T, class InputIterator>
+ bool has(InputIterator first, InputIterator last, const T &elem){
+ return last != std::find(first, last, elem);
+ }
+
+ template<class T, class Iterable>
+ bool has(const Iterable &iterable, const T &elem){
+ return has(iterable.begin(), iterable.end(), elem);
+ }
+
+ template<typename T> T signum(T n){
+ if (n < 0) return -1;
+ if (n > 0) return 1;
+ return 0;
+ }
+
+}//namespace std
+
+#endif /* INCLUDED_UHD_UTILS_ALGORITHM_HPP */
diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils/assert.hpp
index e5333539f..842ed8dfa 100644
--- a/host/include/uhd/utils.hpp
+++ b/host/include/uhd/utils/assert.hpp
@@ -15,85 +15,31 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#ifndef INCLUDED_UHD_UTILS_HPP
-#define INCLUDED_UHD_UTILS_HPP
+#ifndef INCLUDED_UHD_UTILS_ASSERT_HPP
+#define INCLUDED_UHD_UTILS_ASSERT_HPP
-#include <uhd/config.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <boost/format.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
#include <boost/current_function.hpp>
#include <stdexcept>
-#include <algorithm>
-
-/*!
- * Defines a function that implements the "construct on first use" idiom
- * \param _t the type definition for the instance
- * \param _x the name of the defined function
- * \return a reference to the lazy instance
- */
-#define STATIC_INSTANCE(_t, _x) static _t &_x(){static _t _x; return _x;}
-/*!
- * Defines a static code block that will be called before main()
- * \param _x the name of the defined struct (must be unique in file)
- */
-#define STATIC_BLOCK(_x) static struct _x{_x();}_x;_x::_x()
-
-/*!
- * Useful templated functions and classes that I like to pretend are part of stl
- */
-namespace std{
+namespace uhd{
class assert_error : public std::logic_error{
public:
- explicit assert_error(const string& what_arg) : logic_error(what_arg){
+ explicit assert_error(const std::string& what_arg) : logic_error(what_arg){
/* NOP */
}
};
#define ASSERT_THROW(_x) if (not (_x)) { \
- throw std::assert_error(str(boost::format( \
+ throw uhd::assert_error(str(boost::format( \
"Assertion Failed:\n %s:%d\n %s\n ---> %s <---" \
) % __FILE__ % __LINE__ % BOOST_CURRENT_FUNCTION % std::string(#_x))); \
}
- template<class T, class InputIterator, class Function>
- T reduce(InputIterator first, InputIterator last, Function fcn, T init = 0){
- T tmp = init;
- for ( ; first != last; ++first ){
- tmp = fcn(tmp, *first);
- }
- return tmp;
- }
-
- template<class T, class Iterable, class Function>
- T reduce(Iterable iterable, Function fcn, T init = 0){
- return reduce(iterable.begin(), iterable.end(), fcn, init);
- }
-
- template<class T, class InputIterator>
- bool has(InputIterator first, InputIterator last, const T &elem){
- return last != std::find(first, last, elem);
- }
-
- template<class T, class Iterable>
- bool has(const Iterable &iterable, const T &elem){
- return has(iterable.begin(), iterable.end(), elem);
- }
-
- template<typename T> T signum(T n){
- if (n < 0) return -1;
- if (n > 0) return 1;
- return 0;
- }
-
-}//namespace std
-
-#include <boost/format.hpp>
-#include <boost/foreach.hpp>
-#include <boost/lexical_cast.hpp>
-
-namespace uhd{
-
/*!
* Check that an element is found in a container.
* If not, throw a meaningful assertion error.
@@ -116,7 +62,7 @@ namespace uhd{
if (e != iterable.begin()[0]) possible_values += ", ";
possible_values += boost::lexical_cast<std::string>(e);
}
- throw std::assert_error(str(boost::format(
+ throw uhd::assert_error(str(boost::format(
"Error: %s is not a valid %s. "
"Possible values are: [%s]."
)
@@ -127,4 +73,4 @@ namespace uhd{
}//namespace uhd
-#endif /* INCLUDED_UHD_UTILS_HPP */
+#endif /* INCLUDED_UHD_UTILS_ASSERT_HPP */
diff --git a/host/include/uhd/gain_handler.hpp b/host/include/uhd/utils/gain_handler.hpp
index 65d6cecf9..f4629e6a7 100644
--- a/host/include/uhd/gain_handler.hpp
+++ b/host/include/uhd/utils/gain_handler.hpp
@@ -15,8 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#ifndef INCLUDED_UHD_GAIN_HANDLER_HPP
-#define INCLUDED_UHD_GAIN_HANDLER_HPP
+#ifndef INCLUDED_UHD_UTILS_GAIN_HANDLER_HPP
+#define INCLUDED_UHD_UTILS_GAIN_HANDLER_HPP
#include <uhd/config.hpp>
#include <uhd/wax.hpp>
@@ -86,5 +86,5 @@ public:
} //namespace uhd
-#endif /* INCLUDED_UHD_GAIN_HANDLER_HPP */
+#endif /* INCLUDED_UHD_UTILS_GAIN_HANDLER_HPP */
diff --git a/host/include/uhd/utils/safe_main.hpp b/host/include/uhd/utils/safe_main.hpp
new file mode 100644
index 000000000..b682aa540
--- /dev/null
+++ b/host/include/uhd/utils/safe_main.hpp
@@ -0,0 +1,44 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_UTILS_SAFE_MAIN_HPP
+#define INCLUDED_UHD_UTILS_SAFE_MAIN_HPP
+
+#include <uhd/config.hpp>
+#include <iostream>
+#include <stdexcept>
+
+/*!
+ * Defines a safe wrapper that places a catch-all around main.
+ * If an exception is thrown, it prints to stderr and returns.
+ * Usage: int UHD_SAFE_MAIN(int argc, char *argv[]){ main code here }
+ * \param _argc the declaration for argc
+ * \param _argv the declaration for argv
+ */
+#define UHD_SAFE_MAIN(_argc, _argv) _main(int, char*[]); \
+int main(int argc, char *argv[]){ \
+ try { \
+ return _main(argc, argv); \
+ } catch(const std::exception &e) { \
+ std::cerr << "Error: " << e.what() << std::endl; \
+ } catch(...) { \
+ std::cerr << "Error: unknown exception" << std::endl; \
+ } \
+ return ~0; \
+} int _main(_argc, _argv)
+
+#endif /* INCLUDED_UHD_UTILS_SAFE_MAIN_HPP */
diff --git a/host/include/uhd/utils/static.hpp b/host/include/uhd/utils/static.hpp
new file mode 100644
index 000000000..c61f10884
--- /dev/null
+++ b/host/include/uhd/utils/static.hpp
@@ -0,0 +1,37 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_UTILS_STATIC_HPP
+#define INCLUDED_UHD_UTILS_STATIC_HPP
+
+#include <uhd/config.hpp>
+
+/*!
+ * Defines a function that implements the "construct on first use" idiom
+ * \param _t the type definition for the instance
+ * \param _x the name of the defined function
+ * \return a reference to the lazy instance
+ */
+#define UHD_SINGLETON_FCN(_t, _x) static _t &_x(){static _t _x; return _x;}
+
+/*!
+ * Defines a static code block that will be called before main()
+ * \param _x the name of the defined struct (must be unique in file)
+ */
+#define UHD_STATIC_BLOCK(_x) static struct _x{_x();}_x;_x::_x()
+
+#endif /* INCLUDED_UHD_UTILS_STATIC_HPP */
diff --git a/host/include/uhd/utils/tune_helper.hpp b/host/include/uhd/utils/tune_helper.hpp
new file mode 100644
index 000000000..958d1eceb
--- /dev/null
+++ b/host/include/uhd/utils/tune_helper.hpp
@@ -0,0 +1,79 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_UTILS_TUNE_HELPER_HPP
+#define INCLUDED_UHD_UTILS_TUNE_HELPER_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/wax.hpp>
+#include <uhd/types/tune_result.hpp>
+
+namespace uhd{
+
+/*!
+ * Tune a rx chain to the desired frequency:
+ * The IF of the subdevice is set as close as possible to
+ * the given target frequency + the LO offset (when applicable).
+ * The ddc cordic is setup to bring the IF down to baseband.
+ * \param subdev the dboard subdevice object with properties
+ * \param ddc the ddc properties object (with "if_rate", "bb_rate", "freq")
+ * \param target_freq the desired center frequency
+ * \param lo_offset an offset for the subdevice IF from center
+ * \return a tune result struct
+ */
+UHD_API tune_result_t tune_rx_subdev_and_ddc(
+ wax::obj subdev, wax::obj ddc,
+ double target_freq, double lo_offset
+);
+
+/*!
+ * Tune a rx chain to the desired frequency:
+ * Same as the above, except the LO offset
+ * is calculated based on the subdevice and BW.
+ */
+UHD_API tune_result_t tune_rx_subdev_and_ddc(
+ wax::obj subdev, wax::obj ddc, double target_freq
+);
+
+/*!
+ * Tune a tx chain to the desired frequency:
+ * The IF of the subdevice is set as close as possible to
+ * the given target frequency + the LO offset (when applicable).
+ * The duc cordic is setup to bring the baseband up to IF.
+ * \param subdev the dboard subdevice object with properties
+ * \param duc the duc properties object (with "if_rate", "bb_rate", "freq")
+ * \param target_freq the desired center frequency
+ * \param lo_offset an offset for the subdevice IF from center
+ * \return a tune result struct
+ */
+UHD_API tune_result_t tune_tx_subdev_and_duc(
+ wax::obj subdev, wax::obj duc,
+ double target_freq, double lo_offset
+);
+
+/*!
+ * Tune a tx chain to the desired frequency:
+ * Same as the above, except the LO offset
+ * is calculated based on the subdevice and BW.
+ */
+UHD_API tune_result_t tune_tx_subdev_and_duc(
+ wax::obj subdev, wax::obj duc, double target_freq
+);
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_UTILS_TUNE_HELPER_HPP */
diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp
index 30645f491..14e6734a5 100644
--- a/host/include/uhd/wax.hpp
+++ b/host/include/uhd/wax.hpp
@@ -38,6 +38,10 @@
*
* Property nesting occurs when a WAX object gets another object's link.
* This special link is obtained through a call to my_obj.get_link().
+ *
+ * Note: Do not put a class derived from wax::obj into an stl container.
+ * MSVC will compile the code, but the binaries will crash at runtime.
+ * Rather, use pointers or smart pointers to instances of the derived class.
*/
namespace wax{
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 46cce729e..323b69b14 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -20,14 +20,13 @@
########################################################################
SET(libuhd_sources
device.cpp
- device_addr.cpp
gain_handler.cpp
load_modules.cpp
- metadata.cpp
simple_device.cpp
- time_spec.cpp
+ tune_helper.cpp
types.cpp
wax.cpp
+ transport/if_addrs.cpp
transport/udp_simple.cpp
transport/vrt.cpp
usrp/dboard/basic.cpp
@@ -83,22 +82,42 @@ ENDIF(HAS_USRP1E_REQUIRED_HEADERS)
########################################################################
# Setup defines for module loading
########################################################################
-INCLUDE(CheckIncludeFileCXX)
+MESSAGE(STATUS "Configuring module loading...")
+INCLUDE(CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H)
-CHECK_INCLUDE_FILE_CXX(Winbase.h HAVE_WINBASE_H)
+CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H)
IF(HAVE_DLFCN_H)
- MESSAGE(STATUS "Module loading supported through dlopen...")
+ MESSAGE(STATUS " Module loading supported through dlopen.")
ADD_DEFINITIONS(-DHAVE_DLFCN_H)
-ELSEIF(HAVE_WINBASE_H)
- MESSAGE(STATUS "Module loading supported through LoadLibrary...")
- ADD_DEFINITIONS(-DHAVE_WINBASE_H)
+ELSEIF(HAVE_WINDOWS_H)
+ MESSAGE(STATUS " Module loading supported through LoadLibrary.")
+ ADD_DEFINITIONS(-DHAVE_WINDOWS_H)
ELSE(HAVE_DLFCN_H)
- MESSAGE(STATUS "Module loading not supported...")
+ MESSAGE(STATUS " Module loading not supported.")
ENDIF(HAVE_DLFCN_H)
########################################################################
+# Setup defines for interface address discovery
+########################################################################
+MESSAGE(STATUS "Configuring interface address discovery...")
+
+INCLUDE(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H)
+CHECK_INCLUDE_FILE_CXX(winsock2.h HAVE_WINSOCK2_H)
+
+IF(HAVE_IFADDRS_H)
+ MESSAGE(STATUS " Interface address discovery supported through getifaddrs.")
+ ADD_DEFINITIONS(-DHAVE_IFADDRS_H)
+ELSEIF(HAVE_WINSOCK2_H)
+ MESSAGE(STATUS " Interface address discovery supported through SIO_GET_INTERFACE_LIST.")
+ ADD_DEFINITIONS(-DHAVE_WINSOCK2_H)
+ELSE(HAVE_IFADDRS_H)
+ MESSAGE(STATUS " Interface address discovery not supported.")
+ENDIF(HAVE_IFADDRS_H)
+
+########################################################################
# Setup libuhd library
########################################################################
ADD_LIBRARY(uhd SHARED ${libuhd_sources})
diff --git a/host/lib/device.cpp b/host/lib/device.cpp
index cd8a01ab4..27a365d34 100644
--- a/host/lib/device.cpp
+++ b/host/lib/device.cpp
@@ -16,8 +16,9 @@
//
#include <uhd/device.hpp>
-#include <uhd/dict.hpp>
-#include <uhd/utils.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/weak_ptr.hpp>
@@ -46,7 +47,7 @@ static size_t hash_device_addr(
//combine the hashes of sorted keys/value pairs
size_t hash = 0;
- BOOST_FOREACH(std::string key, keys){
+ BOOST_FOREACH(const std::string &key, keys){
boost::hash_combine(hash, key);
boost::hash_combine(hash, dev_addr[key]);
}
@@ -56,26 +57,26 @@ static size_t hash_device_addr(
/***********************************************************************
* Registration
**********************************************************************/
-typedef boost::tuple<device::discover_t, device::make_t> dev_fcn_reg_t;
+typedef boost::tuple<device::find_t, device::make_t> dev_fcn_reg_t;
// instantiate the device function registry container
-STATIC_INSTANCE(std::vector<dev_fcn_reg_t>, get_dev_fcn_regs)
+UHD_SINGLETON_FCN(std::vector<dev_fcn_reg_t>, get_dev_fcn_regs)
void device::register_device(
- const discover_t &discover,
+ const find_t &find,
const make_t &make
){
//std::cout << "registering device" << std::endl;
- get_dev_fcn_regs().push_back(dev_fcn_reg_t(discover, make));
+ get_dev_fcn_regs().push_back(dev_fcn_reg_t(find, make));
}
/***********************************************************************
* Discover
**********************************************************************/
-device_addrs_t device::discover(const device_addr_t &hint){
+device_addrs_t device::find(const device_addr_t &hint){
device_addrs_t device_addrs;
- BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){
+ BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){
device_addrs_t discovered_addrs = fcn.get<0>()(hint);
device_addrs.insert(
device_addrs.begin(),
@@ -94,11 +95,11 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
typedef boost::tuple<device_addr_t, make_t> dev_addr_make_t;
std::vector<dev_addr_make_t> dev_addr_makers;
- BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){
+ BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){
BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){
//copy keys that were in hint but not in dev_addr
//this way, we can pass additional transport arguments
- BOOST_FOREACH(std::string key, hint.get_keys()){
+ BOOST_FOREACH(const std::string &key, hint.get_keys()){
if (not dev_addr.has_key(key)) dev_addr[key] = hint[key];
}
//append the discovered address and its factory function
@@ -109,14 +110,14 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
//check that we found any devices
if (dev_addr_makers.size() == 0){
throw std::runtime_error(str(
- boost::format("No devices found for ----->\n%s") % device_addr::to_string(hint)
+ boost::format("No devices found for ----->\n%s") % hint.to_string()
));
}
//check that the which index is valid
if (dev_addr_makers.size() <= which){
throw std::runtime_error(str(
- boost::format("No device at index %d for ----->\n%s") % which % device_addr::to_string(hint)
+ boost::format("No device at index %d for ----->\n%s") % which % hint.to_string()
));
}
@@ -136,7 +137,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
return hash_to_device[dev_hash].lock();
}
//create and register a new device
- catch(const std::assert_error &){
+ catch(const uhd::assert_error &){
device::sptr dev = maker(dev_addr);
hash_to_device[dev_hash] = dev;
return dev;
diff --git a/host/lib/device_addr.cpp b/host/lib/device_addr.cpp
deleted file mode 100644
index d26bb4b9d..000000000
--- a/host/lib/device_addr.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/device_addr.hpp>
-#include <sstream>
-#include <cstring>
-#include <stdexcept>
-#include <boost/format.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/foreach.hpp>
-
-//----------------------- u2 mac addr wrapper ------------------------//
-uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){
- std::string mac_addr_str = (mac_addr_str_ == "")? "ff:ff:ff:ff:ff:ff" : mac_addr_str_;
-
- //ether_aton_r(str.c_str(), &mac_addr);
- boost::uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB
-
- try{
- //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx
- //the IAB above will fill in for the shorter pattern
- if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17)
- throw std::runtime_error("expected exactly 5 or 17 characters");
-
- //split the mac addr hex string at the colons
- std::vector<std::string> hex_strs;
- boost::split(hex_strs, mac_addr_str, boost::is_any_of(":"));
- for (size_t i = 0; i < hex_strs.size(); i++){
- int hex_num;
- std::istringstream iss(hex_strs[i]);
- iss >> std::hex >> hex_num;
- p[i] = boost::uint8_t(hex_num);
- }
-
- }
- catch(std::exception const& e){
- throw std::runtime_error(str(
- boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what()
- ));
- }
-
- memcpy(&mac_addr, p, sizeof(mac_addr));
-}
-
-std::string uhd::mac_addr_t::to_string(void) const{
- //ether_ntoa_r(&mac_addr, addr_buf);
- const boost::uint8_t *p = reinterpret_cast<const boost::uint8_t *>(&mac_addr);
- return str(
- boost::format("%02x:%02x:%02x:%02x:%02x:%02x")
- % int(p[0]) % int(p[1]) % int(p[2])
- % int(p[3]) % int(p[4]) % int(p[5])
- );
-}
-
-std::ostream& operator<<(std::ostream &os, const uhd::mac_addr_t &x){
- os << x.to_string();
- return os;
-}
-
-//----------------------- usrp device_addr_t wrapper -------------------------//
-std::string uhd::device_addr::to_string(const uhd::device_addr_t &device_addr){
- std::stringstream ss;
- BOOST_FOREACH(std::string key, device_addr.get_keys()){
- ss << boost::format("%s: %s") % key % device_addr[key] << std::endl;
- }
- return ss.str();
-}
-
-std::ostream& operator<<(std::ostream &os, const uhd::device_addr_t &device_addr){
- os << uhd::device_addr::to_string(device_addr);
- return os;
-}
diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp
index 7dd1547cb..daf629f0b 100644
--- a/host/lib/gain_handler.cpp
+++ b/host/lib/gain_handler.cpp
@@ -15,9 +15,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/gain_handler.hpp>
-#include <uhd/utils.hpp>
-#include <uhd/types.hpp>
+#include <uhd/utils/gain_handler.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/ranges.hpp>
#include <uhd/props.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
@@ -47,7 +47,7 @@ private:
is_equal_t _is_equal;
prop_names_t get_gain_names(void);
- gain_t get_overall_gain_val(void);
+ float get_overall_gain_val(void);
gain_range_t get_overall_gain_range(void);
template <class T> T get_named_prop(const wax::obj &prop, const std::string &name){
return _link[named_prop_t(prop, name)].as<T>();
@@ -90,21 +90,21 @@ prop_names_t gain_handler_impl::get_gain_names(void){
return _link[_props.names].as<prop_names_t>();
}
-gain_t gain_handler_impl::get_overall_gain_val(void){
- gain_t gain_val = 0;
+float gain_handler_impl::get_overall_gain_val(void){
+ float gain_val = 0;
BOOST_FOREACH(std::string name, get_gain_names()){
- gain_val += get_named_prop<gain_t>(_props.value, name);
+ gain_val += get_named_prop<float>(_props.value, name);
}
return gain_val;
}
gain_range_t gain_handler_impl::get_overall_gain_range(void){
- gain_t gain_min = 0, gain_max = 0, gain_step = 0;
+ float gain_min = 0, gain_max = 0, gain_step = 0;
BOOST_FOREACH(std::string name, get_gain_names()){
- gain_range_t gain_tmp = get_named_prop<gain_range_t>(_props.range, name);
- gain_min += gain_tmp.min;
- gain_max += gain_tmp.max;
- gain_step = std::max(gain_step, gain_tmp.step);
+ gain_range_t floatmp = get_named_prop<gain_range_t>(_props.range, name);
+ gain_min += floatmp.min;
+ gain_max += floatmp.max;
+ gain_step = std::max(gain_step, floatmp.step);
}
return gain_range_t(gain_min, gain_max, gain_step);
}
@@ -145,7 +145,7 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val)
//not a gain value key... dont handle
if (not _is_equal(key, _props.value)) return false;
- gain_t gain_val = val.as<gain_t>();
+ float gain_val = val.as<float>();
//not a wildcard... dont handle (but check name and range)
if (name != ""){
@@ -164,7 +164,7 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val)
gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name);
//clip g to be within the allowed range
- gain_t g = std::min(std::max(gain_val, gain.min), gain.max);
+ float g = std::min(std::max(gain_val, gain.min), gain.max);
//set g to be a multiple of the step size
g -= std::fmod(g, gain.step);
//set g to be the new gain
diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp
index 700afcd3f..babff1ca5 100644
--- a/host/lib/load_modules.cpp
+++ b/host/lib/load_modules.cpp
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/static.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
@@ -40,8 +40,8 @@ static void load_module(const std::string &file_name){
}
}
-#elif HAVE_WINBASE_H
-#include <Winbase.h>
+#elif HAVE_WINDOWS_H
+#include <windows.h>
static void load_module(const std::string &file_name){
if (LoadLibrary(file_name.c_str()) == NULL){
@@ -101,7 +101,7 @@ static void load_path(const fs::path &path){
* Load all the modules given by the module path enviroment variable.
* The path variable may be several paths split by path separators.
*/
-STATIC_BLOCK(load_modules){
+UHD_STATIC_BLOCK(load_modules){
//get the environment variable module path
char *env_module_path = std::getenv("UHD_MODULE_PATH");
if (env_module_path == NULL) return;
diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp
index ba1966e0d..25beb45a9 100644
--- a/host/lib/simple_device.cpp
+++ b/host/lib/simple_device.cpp
@@ -16,11 +16,9 @@
//
#include <uhd/simple_device.hpp>
-#include <uhd/device.hpp>
-#include <uhd/utils.hpp>
+#include <uhd/utils/tune_helper.hpp>
+#include <uhd/utils/assert.hpp>
#include <uhd/props.hpp>
-#include <uhd/types.hpp>
-#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <stdexcept>
@@ -28,89 +26,8 @@
using namespace uhd;
/***********************************************************************
- * Tune Helper Function
- **********************************************************************/
-static tune_result_t tune(
- double target_freq,
- double lo_offset,
- wax::obj subdev,
- wax::obj dxc,
- bool is_tx
-){
- wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
- bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
- bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>();
- wax::obj dxc_freq_proxy = dxc[std::string("freq")];
- double dxc_sample_rate = dxc[std::string("rate")].as<double>();
-
- // Ask the d'board to tune as closely as it can to target_freq+lo_offset
- double target_inter_freq = target_freq + lo_offset;
- subdev_freq_proxy = target_inter_freq;
- double actual_inter_freq = subdev_freq_proxy.as<double>();
-
- // Calculate the DDC setting that will downconvert the baseband from the
- // daughterboard to our target frequency.
- double delta_freq = target_freq - actual_inter_freq;
- double delta_sign = std::signum(delta_freq);
- delta_freq *= delta_sign;
- delta_freq = fmod(delta_freq, dxc_sample_rate);
- bool inverted = delta_freq > dxc_sample_rate/2.0;
- double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq);
- target_dxc_freq *= delta_sign;
-
- // If the spectrum is inverted, and the daughterboard doesn't do
- // quadrature downconversion, we can fix the inversion by flipping the
- // sign of the dxc_freq... (This only happens using the basic_rx board)
- if (subdev_spectrum_inverted){
- inverted = not inverted;
- }
- if (inverted and not subdev_quadrature){
- target_dxc_freq *= -1.0;
- inverted = not inverted;
- }
- // down conversion versus up conversion, fight!
- // your mother is ugly and your going down...
- target_dxc_freq *= (is_tx)? -1.0 : +1.0;
-
- dxc_freq_proxy = target_dxc_freq;
- double actual_dxc_freq = dxc_freq_proxy.as<double>();
-
- //return some kind of tune result tuple/struct
- tune_result_t tune_result;
- tune_result.target_inter_freq = target_inter_freq;
- tune_result.actual_inter_freq = actual_inter_freq;
- tune_result.target_dxc_freq = target_dxc_freq;
- tune_result.actual_dxc_freq = actual_dxc_freq;
- tune_result.spectrum_inverted = inverted;
- return tune_result;
-}
-
-/***********************************************************************
* Helper Functions
**********************************************************************/
-static std::string trim(const std::string &in){
- return boost::algorithm::trim_copy(in);
-}
-
-device_addr_t args_to_device_addr(const std::string &args){
- device_addr_t addr;
-
- //split the args at the semi-colons
- std::vector<std::string> pairs;
- boost::split(pairs, args, boost::is_any_of(";"));
- BOOST_FOREACH(std::string pair, pairs){
- if (trim(pair) == "") continue;
-
- //split the key value pairs at the equals
- std::vector<std::string> key_val;
- boost::split(key_val, pair, boost::is_any_of("="));
- if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args);
- addr[trim(key_val[0])] = trim(key_val[1]);
- }
-
- return addr;
-}
-
static std::vector<double> get_xx_rates(wax::obj decerps, wax::obj rate){
std::vector<double> rates;
BOOST_FOREACH(size_t decerp, decerps.as<std::vector<size_t> >()){
@@ -154,42 +71,42 @@ public:
}
/*******************************************************************
- * Streaming
+ * Timing
******************************************************************/
- void set_streaming(bool enb){
- _rx_ddc[std::string("enabled")] = enb;
+ void set_time_now(const time_spec_t &time_spec){
+ _mboard[MBOARD_PROP_TIME_NOW] = time_spec;
}
- bool get_streaming(void){
- return _rx_ddc[std::string("enabled")].as<bool>();
+ void set_time_next_pps(const time_spec_t &time_spec){
+ _mboard[MBOARD_PROP_TIME_NEXT_PPS] = time_spec;
+ }
+
+ /*******************************************************************
+ * Streaming
+ ******************************************************************/
+ void issue_stream_cmd(const stream_cmd_t &stream_cmd){
+ _rx_ddc[std::string("stream_cmd")] = stream_cmd;
}
/*******************************************************************
* RX methods
******************************************************************/
void set_rx_rate(double rate){
- double samp_rate = _rx_ddc[std::string("rate")].as<double>();
+ double samp_rate = _rx_ddc[std::string("if_rate")].as<double>();
assert_has(get_rx_rates(), rate, "simple device rx rate");
_rx_ddc[std::string("decim")] = size_t(samp_rate/rate);
}
double get_rx_rate(void){
- double samp_rate = _rx_ddc[std::string("rate")].as<double>();
- size_t decim = _rx_ddc[std::string("decim")].as<size_t>();
- return samp_rate/decim;
+ return _rx_ddc[std::string("bb_rate")].as<double>();
}
std::vector<double> get_rx_rates(void){
- return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("rate")]);
+ return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("if_rate")]);
}
tune_result_t set_rx_freq(double target_freq){
- double lo_offset = 0.0;
- //if the local oscillator will be in the passband, use an offset
- if (_rx_subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
- lo_offset = get_rx_rate()*2.0;
- }
- return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */);
+ return tune_rx_subdev_and_ddc(_rx_subdev, _rx_ddc, target_freq);
}
freq_range_t get_rx_freq_range(void){
@@ -201,7 +118,7 @@ public:
}
float get_rx_gain(void){
- return _rx_subdev[SUBDEV_PROP_GAIN].as<gain_t>();
+ return _rx_subdev[SUBDEV_PROP_GAIN].as<float>();
}
gain_range_t get_rx_gain_range(void){
@@ -224,28 +141,21 @@ public:
* TX methods
******************************************************************/
void set_tx_rate(double rate){
- double samp_rate = _tx_duc[std::string("rate")].as<double>();
+ double samp_rate = _tx_duc[std::string("if_rate")].as<double>();
assert_has(get_tx_rates(), rate, "simple device tx rate");
_tx_duc[std::string("interp")] = size_t(samp_rate/rate);
}
double get_tx_rate(void){
- double samp_rate = _tx_duc[std::string("rate")].as<double>();
- size_t interp = _tx_duc[std::string("interp")].as<size_t>();
- return samp_rate/interp;
+ return _tx_duc[std::string("bb_rate")].as<double>();
}
std::vector<double> get_tx_rates(void){
- return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("rate")]);
+ return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("if_rate")]);
}
tune_result_t set_tx_freq(double target_freq){
- double lo_offset = 0.0;
- //if the local oscillator will be in the passband, use an offset
- if (_tx_subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
- lo_offset = get_tx_rate()*2.0;
- }
- return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */);
+ return tune_tx_subdev_and_duc(_tx_subdev, _tx_duc, target_freq);
}
freq_range_t get_tx_freq_range(void){
@@ -257,7 +167,7 @@ public:
}
float get_tx_gain(void){
- return _tx_subdev[SUBDEV_PROP_GAIN].as<gain_t>();
+ return _tx_subdev[SUBDEV_PROP_GAIN].as<float>();
}
gain_range_t get_tx_gain_range(void){
@@ -289,5 +199,5 @@ private:
* The Make Function
**********************************************************************/
simple_device::sptr simple_device::make(const std::string &args){
- return sptr(new simple_device_impl(args_to_device_addr(args)));
+ return sptr(new simple_device_impl(device_addr_t::from_args_str(args)));
}
diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp
deleted file mode 100644
index 210010394..000000000
--- a/host/lib/time_spec.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/time_spec.hpp>
-
-using namespace uhd;
-
-time_spec_t::time_spec_t(void){
- secs = ~0;
- ticks = ~0;
-}
-
-time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){
- secs = new_secs;
- ticks = new_ticks;
-}
-
-static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
-static double time_tick_rate = double(boost::posix_time::time_duration::ticks_per_second());
-
-time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){
- boost::posix_time::time_duration td = time - epoch;
- secs = boost::uint32_t(td.total_seconds());
- double time_ticks_per_device_ticks = time_tick_rate/tick_rate;
- ticks = boost::uint32_t(td.fractional_seconds()/time_ticks_per_device_ticks);
-}
diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py
new file mode 100755
index 000000000..918de3ad7
--- /dev/null
+++ b/host/lib/transport/gen_vrt.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""
+The vrt packer/unpacker code generator:
+
+This script will generate the pack and unpack routines that convert
+metatdata into vrt headers and vrt headers into metadata.
+
+The generated code infers jump tables to speed-up the parsing time.
+"""
+
+TMPL_TEXT = """
+#import time
+
+########################################################################
+## setup predicates
+########################################################################
+#set $sid_p = 0b00001
+#set $cid_p = 0b00010
+#set $tsi_p = 0b00100
+#set $tsf_p = 0b01000
+#set $tlr_p = 0b10000
+
+/***********************************************************************
+ * This file was generated by $file on $time.strftime("%c")
+ **********************************************************************/
+
+\#include <uhd/transport/vrt.hpp>
+\#include <boost/asio.hpp> //endianness conversion
+\#include <stdexcept>
+
+using namespace uhd;
+using namespace uhd::transport;
+
+void vrt::pack(
+ const tx_metadata_t &metadata, //input
+ boost::uint32_t *header_buff, //output
+ size_t &num_header_words32, //output
+ size_t num_payload_words32, //input
+ size_t &num_packet_words32, //output
+ size_t packet_count //input
+){
+ boost::uint32_t vrt_hdr_flags;
+
+ boost::uint8_t pred = 0;
+ if (metadata.has_stream_id) pred |= $hex($sid_p);
+ if (metadata.has_time_spec) pred |= $hex($tsi_p | $tsf_p);
+
+ switch(pred){
+ #for $pred in range(2**5)
+ case $pred:
+ #set $num_header_words = 1
+ #set $flags = 0
+ ########## Stream ID ##########
+ #if $pred & $sid_p
+ header_buff[$num_header_words] = htonl(metadata.stream_id);
+ #set $num_header_words += 1
+ #set $flags |= (0x1 << 28);
+ #end if
+ ########## Class ID ##########
+ #if $pred & $cid_p
+ header_buff[$num_header_words] = htonl(0);
+ #set $num_header_words += 1
+ header_buff[$num_header_words] = htonl(0);
+ #set $num_header_words += 1
+ #set $flags |= (0x1 << 27);
+ #end if
+ ########## Integer Time ##########
+ #if $pred & $tsi_p
+ header_buff[$num_header_words] = htonl(metadata.time_spec.secs);
+ #set $num_header_words += 1
+ #set $flags |= (0x3 << 22);
+ #end if
+ ########## Fractional Time ##########
+ #if $pred & $tsf_p
+ header_buff[$num_header_words] = htonl(0);
+ #set $num_header_words += 1
+ header_buff[$num_header_words] = htonl(metadata.time_spec.ticks);
+ #set $num_header_words += 1
+ #set $flags |= (0x1 << 20);
+ #end if
+ ########## Trailer ##########
+ #if $pred & $tlr_p
+ #set $flags |= (0x1 << 26);
+ #set $num_trailer_words = 1;
+ #else
+ #set $num_trailer_words = 0;
+ #end if
+ ########## Variables ##########
+ num_header_words32 = $num_header_words;
+ num_packet_words32 = $($num_header_words + $num_trailer_words) + num_payload_words32;
+ vrt_hdr_flags = $hex($flags);
+ break;
+ #end for
+ }
+
+ //set the burst flags
+ if (metadata.start_of_burst) vrt_hdr_flags |= $hex(0x1 << 25);
+ if (metadata.end_of_burst) vrt_hdr_flags |= $hex(0x1 << 24);
+
+ //fill in complete header word
+ header_buff[0] = htonl(vrt_hdr_flags |
+ ((packet_count & 0xf) << 16) |
+ (num_packet_words32 & 0xffff)
+ );
+}
+
+void vrt::unpack(
+ rx_metadata_t &metadata, //output
+ const boost::uint32_t *header_buff, //input
+ size_t &num_header_words32, //output
+ size_t &num_payload_words32, //output
+ size_t num_packet_words32, //input
+ size_t &packet_count //output
+){
+ //clear the metadata
+ metadata = rx_metadata_t();
+
+ //extract vrt header
+ boost::uint32_t vrt_hdr_word = ntohl(header_buff[0]);
+ size_t packet_words32 = vrt_hdr_word & 0xffff;
+ packet_count = (vrt_hdr_word >> 16) & 0xf;
+
+ //failure cases
+ if (packet_words32 == 0 or num_packet_words32 < packet_words32)
+ throw std::runtime_error("bad vrt header or packet fragment");
+ if (vrt_hdr_word & (0x7 << 29))
+ throw std::runtime_error("unsupported vrt packet type");
+
+ boost::uint8_t pred = 0;
+ if(vrt_hdr_word & $hex(0x1 << 28)) pred |= $hex($sid_p);
+ if(vrt_hdr_word & $hex(0x1 << 27)) pred |= $hex($cid_p);
+ if(vrt_hdr_word & $hex(0x3 << 22)) pred |= $hex($tsi_p);
+ if(vrt_hdr_word & $hex(0x3 << 20)) pred |= $hex($tsf_p);
+ if(vrt_hdr_word & $hex(0x1 << 26)) pred |= $hex($tlr_p);
+
+ switch(pred){
+ #for $pred in range(2**5)
+ case $pred:
+ #set $set_has_time_spec = False
+ #set $num_header_words = 1
+ ########## Stream ID ##########
+ #if $pred & $sid_p
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[$num_header_words]);
+ #set $num_header_words += 1
+ #end if
+ ########## Class ID ##########
+ #if $pred & $cid_p
+ #set $num_header_words += 1
+ #set $num_header_words += 1
+ #end if
+ ########## Integer Time ##########
+ #if $pred & $tsi_p
+ metadata.has_time_spec = true;
+ #set $set_has_time_spec = True
+ metadata.time_spec.secs = ntohl(header_buff[$num_header_words]);
+ #set $num_header_words += 1
+ #end if
+ ########## Fractional Time ##########
+ #if $pred & $tsf_p
+ #if not $set_has_time_spec
+ metadata.has_time_spec = true;
+ #set $set_has_time_spec = True
+ #end if
+ #set $num_header_words += 1
+ metadata.time_spec.ticks = ntohl(header_buff[$num_header_words]);
+ #set $num_header_words += 1
+ #end if
+ ########## Trailer ##########
+ #if $pred & $tlr_p
+ #set $num_trailer_words = 1;
+ #else
+ #set $num_trailer_words = 0;
+ #end if
+ ########## Variables ##########
+ num_header_words32 = $num_header_words;
+ num_payload_words32 = packet_words32 - $($num_header_words + $num_trailer_words);
+ break;
+ #end for
+ }
+}
+"""
+
+from Cheetah import Template
+def parse_str(_tmpl_text, **kwargs): return str(Template.Template(_tmpl_text, kwargs))
+
+if __name__ == '__main__':
+ from Cheetah import Template
+ print parse_str(TMPL_TEXT, file=__file__)
diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp
new file mode 100644
index 000000000..5c8c8a176
--- /dev/null
+++ b/host/lib/transport/if_addrs.cpp
@@ -0,0 +1,109 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/transport/if_addrs.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/cstdint.hpp>
+#include <iostream>
+
+uhd::transport::if_addrs_t::if_addrs_t(void){
+ /* NOP */
+}
+
+/***********************************************************************
+ * Interface address discovery through ifaddrs api
+ **********************************************************************/
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+
+static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){
+ return boost::asio::ip::address_v4(ntohl(
+ reinterpret_cast<sockaddr_in*>(addr)->sin_addr.s_addr
+ ));
+}
+
+std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
+ std::vector<if_addrs_t> if_addrs;
+ struct ifaddrs *ifap;
+ if (getifaddrs(&ifap) == 0){
+ for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next){
+ //ensure that the entries are valid
+ if (iter->ifa_addr->sa_family != AF_INET) continue;
+ if (iter->ifa_netmask->sa_family != AF_INET) continue;
+ if (iter->ifa_broadaddr->sa_family != AF_INET) continue;
+
+ //append a new set of interface addresses
+ if_addrs_t if_addr;
+ if_addr.inet = sockaddr_to_ip_addr(iter->ifa_addr).to_string();
+ if_addr.mask = sockaddr_to_ip_addr(iter->ifa_netmask).to_string();
+ if_addr.bcast = sockaddr_to_ip_addr(iter->ifa_broadaddr).to_string();
+ if_addrs.push_back(if_addr);
+ }
+ freeifaddrs(ifap);
+ }
+ return if_addrs;
+}
+
+/***********************************************************************
+ * Interface address discovery through windows api (TODO)
+ **********************************************************************/
+#elif HAVE_WINSOCK2_H
+#include <winsock2.h>
+
+std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
+ std::vector<if_addrs_t> if_addrs;
+ SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
+ if (sd == SOCKET_ERROR) {
+ std::cerr << "Failed to get a socket. Error " << WSAGetLastError() <<
+ std::endl; return if_addrs;
+ }
+
+ INTERFACE_INFO InterfaceList[20];
+ unsigned long nBytesReturned;
+ if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
+ sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) {
+ std::cerr << "Failed calling WSAIoctl: error " << WSAGetLastError() <<
+ std::endl;
+ return if_addrs;
+ }
+
+ int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
+ for (int i = 0; i < nNumInterfaces; ++i) {
+ boost::uint32_t iiAddress = ntohl(reinterpret_cast<sockaddr_in&>(InterfaceList[i].iiAddress).sin_addr.s_addr);
+ boost::uint32_t iiNetmask = ntohl(reinterpret_cast<sockaddr_in&>(InterfaceList[i].iiNetmask).sin_addr.s_addr);
+ boost::uint32_t iiBroadcastAddress = (iiAddress & iiNetmask) | ~iiNetmask;
+
+ if_addrs_t if_addr;
+ if_addr.inet = boost::asio::ip::address_v4(iiAddress).to_string();
+ if_addr.mask = boost::asio::ip::address_v4(iiNetmask).to_string();
+ if_addr.bcast = boost::asio::ip::address_v4(iiBroadcastAddress).to_string();
+ if_addrs.push_back(if_addr);
+ }
+
+ return if_addrs;
+}
+
+/***********************************************************************
+ * Interface address discovery not included
+ **********************************************************************/
+#else /* HAVE_IFADDRS_H */
+
+std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
+ return std::vector<if_addrs_t>();
+}
+
+#endif /* HAVE_IFADDRS_H */
diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp
index 3c8ecb70d..f339127ad 100644
--- a/host/lib/transport/udp_simple.cpp
+++ b/host/lib/transport/udp_simple.cpp
@@ -16,6 +16,7 @@
//
#include <uhd/transport/udp_simple.hpp>
+#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index 219ae8720..1fc8ce14a 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -17,6 +17,7 @@
#include <uhd/transport/udp_zero_copy.hpp>
#include <boost/cstdint.hpp>
+#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
@@ -115,7 +116,7 @@ smart_buffer::sptr udp_zero_copy_impl::recv(void){
//implement timeout through polling and sleeping
boost::asio::deadline_timer timer(_socket->get_io_service());
- timer.expires_from_now(boost::posix_time::milliseconds(50));
+ timer.expires_from_now(boost::posix_time::milliseconds(100));
while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp
index a06b5bf21..bebca5db9 100644
--- a/host/lib/transport/vrt.cpp
+++ b/host/lib/transport/vrt.cpp
@@ -1,19 +1,9 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
+
+
+
+/***********************************************************************
+ * This file was generated by ./gen_vrt.py on Fri Mar 26 15:33:00 2010
+ **********************************************************************/
#include <uhd/transport/vrt.hpp>
#include <boost/asio.hpp> //endianness conversion
@@ -30,26 +20,274 @@ void vrt::pack(
size_t &num_packet_words32, //output
size_t packet_count //input
){
- boost::uint32_t vrt_hdr_flags = 0;
- num_header_words32 = 1;
+ boost::uint32_t vrt_hdr_flags;
- //load the vrt header and flags
- if(metadata.has_stream_id){
- vrt_hdr_flags |= (0x1 << 28); //IF Data packet with Stream Identifier
- header_buff[num_header_words32++] = htonl(metadata.stream_id);
- }
+ boost::uint8_t pred = 0;
+ if (metadata.has_stream_id) pred |= 0x1;
+ if (metadata.has_time_spec) pred |= 0xc;
- if(metadata.has_time_spec){
- vrt_hdr_flags |= (0x3 << 22) | (0x1 << 20); //TSI: Other, TSF: Sample Count Timestamp
- header_buff[num_header_words32++] = htonl(metadata.time_spec.secs);
- header_buff[num_header_words32++] = htonl(metadata.time_spec.ticks);
- header_buff[num_header_words32++] = 0; //unused part of fractional seconds
+ switch(pred){
+ case 0:
+ num_header_words32 = 1;
+ num_packet_words32 = 1 + num_payload_words32;
+ vrt_hdr_flags = 0x0;
+ break;
+ case 1:
+ header_buff[1] = htonl(metadata.stream_id);
+ num_header_words32 = 2;
+ num_packet_words32 = 2 + num_payload_words32;
+ vrt_hdr_flags = 0x10000000;
+ break;
+ case 2:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ num_header_words32 = 3;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x8000000;
+ break;
+ case 3:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x18000000;
+ break;
+ case 4:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 2;
+ num_packet_words32 = 2 + num_payload_words32;
+ vrt_hdr_flags = 0xc00000;
+ break;
+ case 5:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 3;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x10c00000;
+ break;
+ case 6:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x8c00000;
+ break;
+ case 7:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 5;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x18c00000;
+ break;
+ case 8:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 3;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x100000;
+ break;
+ case 9:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x10100000;
+ break;
+ case 10:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x8100000;
+ break;
+ case 11:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x18100000;
+ break;
+ case 12:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0xd00000;
+ break;
+ case 13:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x10d00000;
+ break;
+ case 14:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x8d00000;
+ break;
+ case 15:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ header_buff[5] = htonl(0);
+ header_buff[6] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 7;
+ num_packet_words32 = 7 + num_payload_words32;
+ vrt_hdr_flags = 0x18d00000;
+ break;
+ case 16:
+ num_header_words32 = 1;
+ num_packet_words32 = 2 + num_payload_words32;
+ vrt_hdr_flags = 0x4000000;
+ break;
+ case 17:
+ header_buff[1] = htonl(metadata.stream_id);
+ num_header_words32 = 2;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x14000000;
+ break;
+ case 18:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ num_header_words32 = 3;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0xc000000;
+ break;
+ case 19:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x1c000000;
+ break;
+ case 20:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 2;
+ num_packet_words32 = 3 + num_payload_words32;
+ vrt_hdr_flags = 0x4c00000;
+ break;
+ case 21:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 3;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x14c00000;
+ break;
+ case 22:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0xcc00000;
+ break;
+ case 23:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ num_header_words32 = 5;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x1cc00000;
+ break;
+ case 24:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 3;
+ num_packet_words32 = 4 + num_payload_words32;
+ vrt_hdr_flags = 0x4100000;
+ break;
+ case 25:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x14100000;
+ break;
+ case 26:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0xc100000;
+ break;
+ case 27:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 7 + num_payload_words32;
+ vrt_hdr_flags = 0x1c100000;
+ break;
+ case 28:
+ header_buff[1] = htonl(metadata.time_spec.secs);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 4;
+ num_packet_words32 = 5 + num_payload_words32;
+ vrt_hdr_flags = 0x4d00000;
+ break;
+ case 29:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(metadata.time_spec.secs);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 5;
+ num_packet_words32 = 6 + num_payload_words32;
+ vrt_hdr_flags = 0x14d00000;
+ break;
+ case 30:
+ header_buff[1] = htonl(0);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(metadata.time_spec.secs);
+ header_buff[4] = htonl(0);
+ header_buff[5] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 6;
+ num_packet_words32 = 7 + num_payload_words32;
+ vrt_hdr_flags = 0xcd00000;
+ break;
+ case 31:
+ header_buff[1] = htonl(metadata.stream_id);
+ header_buff[2] = htonl(0);
+ header_buff[3] = htonl(0);
+ header_buff[4] = htonl(metadata.time_spec.secs);
+ header_buff[5] = htonl(0);
+ header_buff[6] = htonl(metadata.time_spec.ticks);
+ num_header_words32 = 7;
+ num_packet_words32 = 8 + num_payload_words32;
+ vrt_hdr_flags = 0x1cd00000;
+ break;
}
- vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0;
- vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0;
-
- num_packet_words32 = num_header_words32 + num_payload_words32;
+ //set the burst flags
+ if (metadata.start_of_burst) vrt_hdr_flags |= 0x2000000;
+ if (metadata.end_of_burst) vrt_hdr_flags |= 0x1000000;
//fill in complete header word
header_buff[0] = htonl(vrt_hdr_flags |
@@ -80,30 +318,230 @@ void vrt::unpack(
if (vrt_hdr_word & (0x7 << 29))
throw std::runtime_error("unsupported vrt packet type");
- //parse the header flags
- num_header_words32 = 1;
-
- if (vrt_hdr_word & (0x1 << 28)){ //stream id
- metadata.has_stream_id = true;
- metadata.stream_id = ntohl(header_buff[num_header_words32++]);
- }
-
- if (vrt_hdr_word & (0x1 << 27)){ //class id (we dont use)
- num_header_words32 += 2;
- }
-
- if (vrt_hdr_word & (0x3 << 22)){ //integer time
- metadata.has_time_spec = true;
- metadata.time_spec.secs = ntohl(header_buff[num_header_words32++]);
- }
+ boost::uint8_t pred = 0;
+ if(vrt_hdr_word & 0x10000000) pred |= 0x1;
+ if(vrt_hdr_word & 0x8000000) pred |= 0x2;
+ if(vrt_hdr_word & 0xc00000) pred |= 0x4;
+ if(vrt_hdr_word & 0x300000) pred |= 0x8;
+ if(vrt_hdr_word & 0x4000000) pred |= 0x10;
- if (vrt_hdr_word & (0x3 << 20)){ //fractional time
- metadata.has_time_spec = true;
- metadata.time_spec.ticks = ntohl(header_buff[num_header_words32++]);
- num_header_words32++; //unused part of fractional seconds
+ switch(pred){
+ case 0:
+ num_header_words32 = 1;
+ num_payload_words32 = packet_words32 - 1;
+ break;
+ case 1:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 2;
+ break;
+ case 2:
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 3:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 4:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 2;
+ break;
+ case 5:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 6:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 7:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 8:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 9:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 10:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 11:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 12:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 13:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 14:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 15:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ metadata.time_spec.ticks = ntohl(header_buff[6]);
+ num_header_words32 = 7;
+ num_payload_words32 = packet_words32 - 7;
+ break;
+ case 16:
+ num_header_words32 = 1;
+ num_payload_words32 = packet_words32 - 2;
+ break;
+ case 17:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 18:
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 19:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 20:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ num_header_words32 = 2;
+ num_payload_words32 = packet_words32 - 3;
+ break;
+ case 21:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 22:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 23:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 24:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[2]);
+ num_header_words32 = 3;
+ num_payload_words32 = packet_words32 - 4;
+ break;
+ case 25:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 26:
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 27:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 7;
+ break;
+ case 28:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[1]);
+ metadata.time_spec.ticks = ntohl(header_buff[3]);
+ num_header_words32 = 4;
+ num_payload_words32 = packet_words32 - 5;
+ break;
+ case 29:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[2]);
+ metadata.time_spec.ticks = ntohl(header_buff[4]);
+ num_header_words32 = 5;
+ num_payload_words32 = packet_words32 - 6;
+ break;
+ case 30:
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[3]);
+ metadata.time_spec.ticks = ntohl(header_buff[5]);
+ num_header_words32 = 6;
+ num_payload_words32 = packet_words32 - 7;
+ break;
+ case 31:
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[4]);
+ metadata.time_spec.ticks = ntohl(header_buff[6]);
+ num_header_words32 = 7;
+ num_payload_words32 = packet_words32 - 8;
+ break;
}
-
- size_t num_trailer_words32 = (vrt_hdr_word & (0x1 << 26))? 1 : 0;
-
- num_payload_words32 = packet_words32 - num_header_words32 - num_trailer_words32;
}
+
diff --git a/host/lib/tune_helper.cpp b/host/lib/tune_helper.cpp
new file mode 100644
index 000000000..1e5c4cd0d
--- /dev/null
+++ b/host/lib/tune_helper.cpp
@@ -0,0 +1,125 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/tune_helper.hpp>
+#include <uhd/utils/algorithm.hpp>
+#include <uhd/props.hpp>
+#include <cmath>
+
+using namespace uhd;
+
+/***********************************************************************
+ * Tune Helper Function
+ **********************************************************************/
+static tune_result_t tune_xx_subdev_and_dxc(
+ bool is_tx,
+ wax::obj subdev, wax::obj dxc,
+ double target_freq, double lo_offset
+){
+ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
+ bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
+ bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>();
+ wax::obj dxc_freq_proxy = dxc[std::string("freq")];
+ double dxc_sample_rate = dxc[std::string("if_rate")].as<double>();
+
+ // Ask the d'board to tune as closely as it can to target_freq+lo_offset
+ double target_inter_freq = target_freq + lo_offset;
+ subdev_freq_proxy = target_inter_freq;
+ double actual_inter_freq = subdev_freq_proxy.as<double>();
+
+ // Calculate the DDC setting that will downconvert the baseband from the
+ // daughterboard to our target frequency.
+ double delta_freq = target_freq - actual_inter_freq;
+ double delta_sign = std::signum(delta_freq);
+ delta_freq *= delta_sign;
+ delta_freq = std::fmod(delta_freq, dxc_sample_rate);
+ bool inverted = delta_freq > dxc_sample_rate/2.0;
+ double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq);
+ target_dxc_freq *= delta_sign;
+
+ // If the spectrum is inverted, and the daughterboard doesn't do
+ // quadrature downconversion, we can fix the inversion by flipping the
+ // sign of the dxc_freq... (This only happens using the basic_rx board)
+ if (subdev_spectrum_inverted){
+ inverted = not inverted;
+ }
+ if (inverted and not subdev_quadrature){
+ target_dxc_freq *= -1.0;
+ inverted = not inverted;
+ }
+ // down conversion versus up conversion, fight!
+ // your mother is ugly and your going down...
+ target_dxc_freq *= (is_tx)? -1.0 : +1.0;
+
+ dxc_freq_proxy = target_dxc_freq;
+ double actual_dxc_freq = dxc_freq_proxy.as<double>();
+
+ //return some kind of tune result tuple/struct
+ tune_result_t tune_result;
+ tune_result.target_inter_freq = target_inter_freq;
+ tune_result.actual_inter_freq = actual_inter_freq;
+ tune_result.target_dxc_freq = target_dxc_freq;
+ tune_result.actual_dxc_freq = actual_dxc_freq;
+ tune_result.spectrum_inverted = inverted;
+ return tune_result;
+}
+
+/***********************************************************************
+ * RX Tune
+ **********************************************************************/
+tune_result_t uhd::tune_rx_subdev_and_ddc(
+ wax::obj subdev, wax::obj ddc,
+ double target_freq, double lo_offset
+){
+ bool is_tx = false;
+ return tune_xx_subdev_and_dxc(is_tx, subdev, ddc, target_freq, lo_offset);
+}
+
+tune_result_t uhd::tune_rx_subdev_and_ddc(
+ wax::obj subdev, wax::obj ddc,
+ double target_freq
+){
+ double lo_offset = 0.0;
+ //if the local oscillator will be in the passband, use an offset
+ if (subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
+ lo_offset = 2.0*ddc[std::string("bb_rate")].as<double>();
+ }
+ return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset);
+}
+
+/***********************************************************************
+ * TX Tune
+ **********************************************************************/
+tune_result_t uhd::tune_tx_subdev_and_duc(
+ wax::obj subdev, wax::obj duc,
+ double target_freq, double lo_offset
+){
+ bool is_tx = true;
+ return tune_xx_subdev_and_dxc(is_tx, subdev, duc, target_freq, lo_offset);
+}
+
+tune_result_t uhd::tune_tx_subdev_and_duc(
+ wax::obj subdev, wax::obj duc,
+ double target_freq
+){
+ double lo_offset = 0.0;
+ //if the local oscillator will be in the passband, use an offset
+ if (subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
+ lo_offset = 2.0*duc[std::string("bb_rate")].as<double>();
+ }
+ return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset);
+}
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index f8a9a9b36..bf9f8b895 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -15,12 +15,27 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/types.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/types/tune_result.hpp>
+#include <uhd/types/clock_config.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/metadata.hpp>
+#include <uhd/types/time_spec.hpp>
+#include <uhd/types/device_addr.hpp>
+#include <uhd/types/mac_addr.hpp>
+#include <uhd/types/otw_type.hpp>
+#include <uhd/types/io_type.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <boost/cstdint.hpp>
+#include <stdexcept>
+#include <complex>
using namespace uhd;
/***********************************************************************
- * gain range
+ * ranges
**********************************************************************/
gain_range_t::gain_range_t(float min_, float max_, float step_){
min = min_;
@@ -28,9 +43,6 @@ gain_range_t::gain_range_t(float min_, float max_, float step_){
step = step_;
}
-/***********************************************************************
- * freq range
- **********************************************************************/
freq_range_t::freq_range_t(double min_, double max_){
min = min_;
max = max_;
@@ -51,7 +63,185 @@ tune_result_t::tune_result_t(void){
* clock config
**********************************************************************/
clock_config_t::clock_config_t(void){
- ref_source = ""; //not a valid setting
- pps_source = ""; //not a valid setting
- pps_polarity = POLARITY_NEG;
+ ref_source = REF_INT,
+ pps_source = PPS_INT,
+ pps_polarity = PPS_NEG;
+}
+
+/***********************************************************************
+ * stream command
+ **********************************************************************/
+stream_cmd_t::stream_cmd_t(void){
+ stream_now = true;
+ continuous = false;
+ num_samps = 0;
+}
+
+/***********************************************************************
+ * metadata
+ **********************************************************************/
+rx_metadata_t::rx_metadata_t(void){
+ stream_id = 0;
+ has_stream_id = false;
+ time_spec = time_spec_t();
+ has_time_spec = false;
+ is_fragment = false;
+}
+
+tx_metadata_t::tx_metadata_t(void){
+ stream_id = 0;
+ has_stream_id = false;
+ time_spec = time_spec_t();
+ has_time_spec = false;
+ start_of_burst = false;
+ end_of_burst = false;
+}
+
+/***********************************************************************
+ * time spec
+ **********************************************************************/
+time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){
+ secs = new_secs;
+ ticks = new_ticks;
+}
+
+static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
+static double time_tick_rate = double(boost::posix_time::time_duration::ticks_per_second());
+
+time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){
+ boost::posix_time::time_duration td = time - epoch;
+ secs = boost::uint32_t(td.total_seconds());
+ double time_ticks_per_device_ticks = time_tick_rate/tick_rate;
+ ticks = boost::uint32_t(td.fractional_seconds()/time_ticks_per_device_ticks);
+}
+
+/***********************************************************************
+ * device addr
+ **********************************************************************/
+std::string device_addr_t::to_string(void) const{
+ const device_addr_t &device_addr = *this;
+ std::stringstream ss;
+ BOOST_FOREACH(std::string key, device_addr.get_keys()){
+ ss << boost::format("%s: %s") % key % device_addr[key] << std::endl;
+ }
+ return ss.str();
+}
+
+static const std::string arg_delim = ";";
+static const std::string pair_delim = "=";
+
+static std::string trim(const std::string &in){
+ return boost::algorithm::trim_copy(in);
+}
+
+std::string device_addr_t::to_args_str(void) const{
+ std::string args_str;
+ const device_addr_t &device_addr = *this;
+ BOOST_FOREACH(const std::string &key, device_addr.get_keys()){
+ args_str += key + pair_delim + device_addr[key] + arg_delim;
+ }
+ return args_str;
+}
+
+device_addr_t device_addr_t::from_args_str(const std::string &args_str){
+ device_addr_t addr;
+
+ //split the args at the semi-colons
+ std::vector<std::string> pairs;
+ boost::split(pairs, args_str, boost::is_any_of(arg_delim));
+ BOOST_FOREACH(const std::string &pair, pairs){
+ if (trim(pair) == "") continue;
+
+ //split the key value pairs at the equals
+ std::vector<std::string> key_val;
+ boost::split(key_val, pair, boost::is_any_of(pair_delim));
+ if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args_str);
+ addr[trim(key_val[0])] = trim(key_val[1]);
+ }
+
+ return addr;
+}
+
+/***********************************************************************
+ * mac addr
+ **********************************************************************/
+mac_addr_t::mac_addr_t(const boost::uint8_t *bytes){
+ std::copy(bytes, bytes+hlen, _bytes);
+}
+
+mac_addr_t mac_addr_t::from_bytes(const boost::uint8_t *bytes){
+ return mac_addr_t(bytes);
+}
+
+mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
+
+ boost::uint8_t p[hlen] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB
+
+ try{
+ //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx
+ //the IAB above will fill in for the shorter pattern
+ if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17)
+ throw std::runtime_error("expected exactly 5 or 17 characters");
+
+ //split the mac addr hex string at the colons
+ std::vector<std::string> hex_strs;
+ boost::split(hex_strs, mac_addr_str, boost::is_any_of(":"));
+ for (size_t i = 0; i < hex_strs.size(); i++){
+ int hex_num;
+ std::istringstream iss(hex_strs[i]);
+ iss >> std::hex >> hex_num;
+ p[i] = boost::uint8_t(hex_num);
+ }
+
+ }
+ catch(std::exception const& e){
+ throw std::runtime_error(str(
+ boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what()
+ ));
+ }
+
+ return from_bytes(p);
+}
+
+const boost::uint8_t *mac_addr_t::to_bytes(void) const{
+ return _bytes;
+}
+
+std::string mac_addr_t::to_string(void) const{
+ return str(
+ boost::format("%02x:%02x:%02x:%02x:%02x:%02x")
+ % int(to_bytes()[0]) % int(to_bytes()[1]) % int(to_bytes()[2])
+ % int(to_bytes()[3]) % int(to_bytes()[4]) % int(to_bytes()[5])
+ );
+}
+
+/***********************************************************************
+ * otw type
+ **********************************************************************/
+otw_type_t::otw_type_t(void){
+ width = 0;
+ shift = 0;
+ byteorder = BO_NATIVE;
+}
+
+/***********************************************************************
+ * io type
+ **********************************************************************/
+static size_t tid_to_size(io_type_t::tid_t tid){
+ switch(tid){
+ case io_type_t::COMPLEX_FLOAT32: return sizeof(std::complex<float>);
+ case io_type_t::COMPLEX_INT16: return sizeof(std::complex<boost::int16_t>);
+ case io_type_t::COMPLEX_INT8: return sizeof(std::complex<boost::int8_t>);
+ default: throw std::runtime_error("unknown io type tid");
+ }
+}
+
+io_type_t::io_type_t(tid_t tid)
+: size(tid_to_size(tid)), tid(tid){
+ /* NOP */
+}
+
+io_type_t::io_type_t(size_t size)
+: size(size), tid(CUSTOM_TYPE){
+ /* NOP */
}
diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp
index 82485ae6a..2f29c8e0c 100644
--- a/host/lib/usrp/dboard/basic.cpp
+++ b/host/lib/usrp/dboard/basic.cpp
@@ -15,9 +15,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
#include <uhd/props.hpp>
-#include <uhd/types.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <boost/assign/list_of.hpp>
@@ -33,26 +34,26 @@ using namespace boost::assign;
**********************************************************************/
class basic_rx : public rx_dboard_base{
public:
- basic_rx(ctor_args_t const& args, freq_t max_freq);
+ basic_rx(ctor_args_t const& args, double max_freq);
~basic_rx(void);
void rx_get(const wax::obj &key, wax::obj &val);
void rx_set(const wax::obj &key, const wax::obj &val);
private:
- freq_t _max_freq;
+ double _max_freq;
};
class basic_tx : public tx_dboard_base{
public:
- basic_tx(ctor_args_t const& args, freq_t max_freq);
+ basic_tx(ctor_args_t const& args, double max_freq);
~basic_tx(void);
void tx_get(const wax::obj &key, wax::obj &val);
void tx_set(const wax::obj &key, const wax::obj &val);
private:
- freq_t _max_freq;
+ double _max_freq;
};
/***********************************************************************
@@ -74,17 +75,17 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){
return dboard_base::sptr(new basic_tx(args, 32e6));
}
-STATIC_BLOCK(reg_dboards){
- dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX", list_of(""));
+UHD_STATIC_BLOCK(reg_dboards){
+ dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX");
dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("ab")("a")("b"));
- dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX", list_of(""));
+ dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX");
dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("ab")("a")("b"));
}
/***********************************************************************
* Basic and LF RX dboard
**********************************************************************/
-basic_rx::basic_rx(ctor_args_t const& args, freq_t max_freq) : rx_dboard_base(args){
+basic_rx::basic_rx(ctor_args_t const& args, double max_freq) : rx_dboard_base(args){
_max_freq = max_freq;
// set the gpios to safe values (all inputs)
get_interface()->set_gpio_ddr(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff);
@@ -112,7 +113,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = gain_t(0);
+ val = float(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -124,7 +125,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_FREQ:
- val = freq_t(0);
+ val = double(0);
return;
case SUBDEV_PROP_FREQ_RANGE:
@@ -163,7 +164,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- ASSERT_THROW(val.as<gain_t>() == gain_t(0));
+ ASSERT_THROW(val.as<float>() == float(0));
return;
case SUBDEV_PROP_ANTENNA:
@@ -195,7 +196,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
/***********************************************************************
* Basic and LF TX dboard
**********************************************************************/
-basic_tx::basic_tx(ctor_args_t const& args, freq_t max_freq) : tx_dboard_base(args){
+basic_tx::basic_tx(ctor_args_t const& args, double max_freq) : tx_dboard_base(args){
_max_freq = max_freq;
// set the gpios to safe values (all inputs)
get_interface()->set_gpio_ddr(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff);
@@ -220,7 +221,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = gain_t(0);
+ val = float(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -232,7 +233,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_FREQ:
- val = freq_t(0);
+ val = double(0);
return;
case SUBDEV_PROP_FREQ_RANGE:
@@ -271,7 +272,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- ASSERT_THROW(val.as<gain_t>() == gain_t(0));
+ ASSERT_THROW(val.as<float>() == float(0));
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp
index 6dd41cfd8..09d3bbfd4 100644
--- a/host/lib/usrp/dboard_base.cpp
+++ b/host/lib/usrp/dboard_base.cpp
@@ -52,15 +52,15 @@ dboard_id_t dboard_base::get_tx_id(void){
* xcvr dboard dboard_base class
**********************************************************************/
xcvr_dboard_base::xcvr_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_rx_id() == ID_NONE){
+ if (get_rx_id() == dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create xcvr board when the rx id is \"%s\""
- ) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(dboard_id::NONE)));
}
- if (get_tx_id() == ID_NONE){
+ if (get_tx_id() == dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create xcvr board when the tx id is \"%s\""
- ) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(dboard_id::NONE)));
}
}
@@ -72,11 +72,11 @@ xcvr_dboard_base::~xcvr_dboard_base(void){
* rx dboard dboard_base class
**********************************************************************/
rx_dboard_base::rx_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_tx_id() != ID_NONE){
+ if (get_tx_id() != dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create rx board when the tx id is \"%s\""
" -> expected a tx id of \"%s\""
- ) % dboard_id::to_string(get_tx_id()) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(get_tx_id()) % dboard_id::to_string(dboard_id::NONE)));
}
}
@@ -96,11 +96,11 @@ void rx_dboard_base::tx_set(const wax::obj &, const wax::obj &){
* tx dboard dboard_base class
**********************************************************************/
tx_dboard_base::tx_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_rx_id() != ID_NONE){
+ if (get_rx_id() != dboard_id::NONE){
throw std::runtime_error(str(boost::format(
"cannot create tx board when the rx id is \"%s\""
" -> expected a rx id of \"%s\""
- ) % dboard_id::to_string(get_rx_id()) % dboard_id::to_string(ID_NONE)));
+ ) % dboard_id::to_string(get_rx_id()) % dboard_id::to_string(dboard_id::NONE)));
}
}
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index 6ca15e98c..424626023 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -16,9 +16,10 @@
//
#include <uhd/usrp/dboard_manager.hpp>
-#include <uhd/gain_handler.hpp>
-#include <uhd/utils.hpp>
-#include <uhd/dict.hpp>
+#include <uhd/utils/gain_handler.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/dict.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
@@ -35,7 +36,7 @@ typedef boost::tuple<dboard_manager::dboard_ctor_t, std::string, prop_names_t> a
//map a dboard id to a dboard constructor
typedef uhd::dict<dboard_id_t, args_t> id_to_args_map_t;
-STATIC_INSTANCE(id_to_args_map_t, get_id_to_args_map)
+UHD_SINGLETON_FCN(id_to_args_map_t, get_id_to_args_map)
void dboard_manager::register_dboard(
dboard_id_t dboard_id,
@@ -163,12 +164,12 @@ static args_t get_dboard_args(
std::string const& xx_type
){
//special case, its rx and the none id (0xffff)
- if (xx_type == "rx" and dboard_id == ID_NONE){
+ if (xx_type == "rx" and dboard_id == dboard_id::NONE){
return get_dboard_args(0x0001, xx_type);
}
//special case, its tx and the none id (0xffff)
- if (xx_type == "tx" and dboard_id == ID_NONE){
+ if (xx_type == "tx" and dboard_id == dboard_id::NONE){
return get_dboard_args(0x0000, xx_type);
}
@@ -203,7 +204,7 @@ dboard_manager_impl::dboard_manager_impl(
//make xcvr subdevs (make one subdev for both rx and tx dboards)
if (rx_dboard_ctor == tx_dboard_ctor){
ASSERT_THROW(rx_subdevs == tx_subdevs);
- BOOST_FOREACH(std::string subdev, rx_subdevs){
+ BOOST_FOREACH(const std::string &subdev, rx_subdevs){
dboard_base::sptr xcvr_dboard = rx_dboard_ctor(
dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, tx_dboard_id)
);
@@ -221,9 +222,9 @@ dboard_manager_impl::dboard_manager_impl(
//make tx and rx subdevs (separate subdevs for rx and tx dboards)
else{
//make the rx subdevs
- BOOST_FOREACH(std::string subdev, rx_subdevs){
+ BOOST_FOREACH(const std::string &subdev, rx_subdevs){
dboard_base::sptr rx_dboard = rx_dboard_ctor(
- dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, ID_NONE)
+ dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, dboard_id::NONE)
);
//create a rx proxy for this rx board
_rx_dboards[subdev] = subdev_proxy::sptr(
@@ -231,9 +232,9 @@ dboard_manager_impl::dboard_manager_impl(
);
}
//make the tx subdevs
- BOOST_FOREACH(std::string subdev, tx_subdevs){
+ BOOST_FOREACH(const std::string &subdev, tx_subdevs){
dboard_base::sptr tx_dboard = tx_dboard_ctor(
- dboard_base::ctor_args_t(subdev, interface, ID_NONE, tx_dboard_id)
+ dboard_base::ctor_args_t(subdev, interface, dboard_id::NONE, tx_dboard_id)
);
//create a tx proxy for this tx board
_tx_dboards[subdev] = subdev_proxy::sptr(
diff --git a/host/lib/usrp/usrp1e/usrp1e_none.cpp b/host/lib/usrp/usrp1e/usrp1e_none.cpp
index ac0b12a75..94243523d 100644
--- a/host/lib/usrp/usrp1e/usrp1e_none.cpp
+++ b/host/lib/usrp/usrp1e/usrp1e_none.cpp
@@ -25,7 +25,7 @@ using namespace uhd::usrp;
* when the required kernel module headers are not present.
*/
-device_addrs_t usrp1e::discover(const device_addr_t &){
+device_addrs_t usrp1e::find(const device_addr_t &){
return device_addrs_t(); //return empty list
}
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 66e02d469..fd72aeaa4 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -15,7 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/clock_config.hpp>
#include <boost/format.hpp>
#include "usrp2_impl.hpp"
diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp
index d20465147..8fc7864b0 100644
--- a/host/lib/usrp/usrp2/dboard_interface.cpp
+++ b/host/lib/usrp/usrp2/dboard_interface.cpp
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
#include "usrp2_impl.hpp"
using namespace uhd::usrp;
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 34cce0afb..0d43fac0e 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
#include <boost/format.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/math/special_functions/round.hpp>
@@ -35,7 +35,7 @@ template <class T> T log2(T num){
/***********************************************************************
* DDC Helper Methods
**********************************************************************/
-static boost::uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t clock_freq){
+static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq, double clock_freq){
double scale_factor = std::pow(2.0, 32);
//calculate the freq register word
@@ -63,9 +63,8 @@ void usrp2_impl::init_ddc_config(void){
_ddc_freq = 0;
update_ddc_config();
- _ddc_stream_at = time_spec_t();
- _ddc_enabled = false;
- update_ddc_enabled();
+ //initial command that kills streaming (in case if was left on)
+ //issue_ddc_stream_cmd(TODO)
}
void usrp2_impl::update_ddc_config(void){
@@ -86,21 +85,19 @@ void usrp2_impl::update_ddc_config(void){
ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE);
}
-void usrp2_impl::update_ddc_enabled(void){
+void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
//setup the out data
usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO);
- out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0;
- out_data.data.streaming.secs = htonl(_ddc_stream_at.secs);
- out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks);
- out_data.data.streaming.samples = htonl(_max_rx_samples_per_packet);
+ out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO);
+ out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0;
+ out_data.data.stream_cmd.continuous = (stream_cmd.continuous)? 1 : 0;
+ out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs);
+ out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.ticks);
+ out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps);
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
- ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE);
-
- //clear the stream at time spec (it must be set for the next round of enable/disable)
- _ddc_stream_at = time_spec_t();
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE);
}
/***********************************************************************
@@ -116,12 +113,12 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
case DSP_PROP_OTHERS:{
prop_names_t others = boost::assign::list_of
- ("rate")
+ ("if_rate")
+ ("bb_rate")
("decim")
("decims")
("freq")
- ("enabled")
- ("stream_at")
+ ("stream_cmd")
;
val = others;
}
@@ -131,10 +128,14 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
//handle string-based properties specific to this dsp
std::string key_name = key.as<std::string>();
- if (key_name == "rate"){
+ if (key_name == "if_rate"){
val = get_master_clock_freq();
return;
}
+ else if (key_name == "bb_rate"){
+ val = get_master_clock_freq()/_ddc_decim;
+ return;
+ }
else if (key_name == "decim"){
val = _ddc_decim;
return;
@@ -147,10 +148,6 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
val = _ddc_freq;
return;
}
- else if (key_name == "enabled"){
- val = _ddc_enabled;
- return;
- }
throw std::invalid_argument(str(
boost::format("error getting: unknown key with name %s") % key_name
@@ -171,23 +168,15 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){
return;
}
else if (key_name == "freq"){
- freq_t new_freq = val.as<freq_t>();
+ double new_freq = val.as<double>();
ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
_ddc_freq = new_freq; //shadow
update_ddc_config();
return;
}
- else if (key_name == "enabled"){
- bool new_enabled = val.as<bool>();
- _ddc_enabled = new_enabled; //shadow
- update_ddc_enabled();
- return;
- }
- else if (key_name == "stream_at"){
- time_spec_t new_stream_at = val.as<time_spec_t>();
- _ddc_stream_at = new_stream_at; //shadow
- //update_ddc_enabled(); //dont update from here
+ else if (key_name == "stream_cmd"){
+ issue_ddc_stream_cmd(val.as<stream_cmd_t>());
return;
}
@@ -250,7 +239,8 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
case DSP_PROP_OTHERS:{
prop_names_t others = boost::assign::list_of
- ("rate")
+ ("if_rate")
+ ("bb_rate")
("interp")
("interps")
("freq")
@@ -263,10 +253,14 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
//handle string-based properties specific to this dsp
std::string key_name = key.as<std::string>();
- if (key_name == "rate"){
+ if (key_name == "if_rate"){
val = get_master_clock_freq();
return;
}
+ else if (key_name == "bb_rate"){
+ val = get_master_clock_freq()/_duc_interp;
+ return;
+ }
else if (key_name == "interp"){
val = _duc_interp;
return;
@@ -299,7 +293,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){
return;
}
else if (key_name == "freq"){
- freq_t new_freq = val.as<freq_t>();
+ double new_freq = val.as<double>();
ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
_duc_freq = new_freq; //shadow
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 7fcae6fb2..30fee6c32 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -32,6 +32,9 @@ extern "C" {
#define _SINS_
#endif
+//used to differentiate control packets over data port
+#define USRP2_INVALID_VRT_HEADER 0
+
// size of the vrt header and trailer to the host
#define USRP2_HOST_RX_VRT_HEADER_WORDS32 5
#define USRP2_HOST_RX_VRT_TRAILER_WORDS32 1 //FIXME fpga sets wrong header size when no trailer present
@@ -90,8 +93,8 @@ typedef enum{
USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO,
USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE,
- USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO,
- USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE,
+ USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO,
+ USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE,
USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO,
USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE,
@@ -186,12 +189,13 @@ typedef struct{
_SINS_ uint32_t scale_iq;
} ddc_args;
struct {
- _SINS_ uint8_t enabled;
- _SINS_ uint8_t _pad[3];
+ _SINS_ uint8_t now; //stream now?
+ _SINS_ uint8_t continuous; //auto-reload commmands?
+ _SINS_ uint8_t _pad[2];
_SINS_ uint32_t secs;
_SINS_ uint32_t ticks;
- _SINS_ uint32_t samples;
- } streaming;
+ _SINS_ uint32_t num_samps;
+ } stream_cmd;
struct {
_SINS_ uint32_t freq_word;
_SINS_ uint32_t interp;
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index dc8eea243..c87884ebb 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -16,7 +16,6 @@
//
#include <complex>
-#include <algorithm>
#include <boost/format.hpp>
#include "usrp2_impl.hpp"
@@ -42,20 +41,22 @@ void usrp2_impl::io_init(void){
_rx_copy_buff = asio::buffer("", 0);
//send a small data packet so the usrp2 knows the udp source port
- boost::uint32_t zero_data = 0;
- _data_transport->send(asio::buffer(&zero_data, sizeof(zero_data)));
+ //and the maximum number of lines (32 bit words) per packet
+ boost::uint32_t data[2] = {
+ htonl(USRP2_INVALID_VRT_HEADER),
+ htonl(_max_rx_samples_per_packet)
+ };
+ _data_transport->send(asio::buffer(&data, sizeof(data)));
}
-#define unrolled_loop(__i, __len, __inst) {\
+#define unrolled_loop(__inst, __len){ \
size_t __i = 0; \
- while(__i < (__len & ~0x7)){ \
- __inst; __i++; __inst; __i++; \
- __inst; __i++; __inst; __i++; \
- __inst; __i++; __inst; __i++; \
- __inst; __i++; __inst; __i++; \
+ for(; __i < (__len & ~0x3); __i+= 4){ \
+ __inst(__i+0); __inst(__i+1); \
+ __inst(__i+2); __inst(__i+3); \
} \
- while(__i < __len){ \
- __inst; __i++;\
+ for(; __i < __len; __i++){ \
+ __inst(__i); \
} \
}
@@ -71,11 +72,12 @@ static inline void host_floats_to_usrp2_items(
const fc32_t *host_floats,
size_t num_samps
){
- unrolled_loop(i, num_samps,{
- boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float);
- boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float);
- usrp2_items[i] = htonl((real << 16) | (imag << 0));
- });
+ #define host_floats_to_usrp2_items_i(i){ \
+ boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \
+ boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \
+ usrp2_items[i] = htonl((real << 16) | (imag << 0)); \
+ }
+ unrolled_loop(host_floats_to_usrp2_items_i, num_samps);
}
static inline void usrp2_items_to_host_floats(
@@ -83,12 +85,13 @@ static inline void usrp2_items_to_host_floats(
const boost::uint32_t *usrp2_items,
size_t num_samps
){
- unrolled_loop(i, num_samps,{
- boost::uint32_t item = ntohl(usrp2_items[i]);
- boost::int16_t real = boost::uint16_t(item >> 16);
- boost::int16_t imag = boost::uint16_t(item >> 0);
- host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short));
- });
+ #define usrp2_items_to_host_floats_i(i){ \
+ boost::uint32_t item = ntohl(usrp2_items[i]); \
+ boost::int16_t real = boost::uint16_t(item >> 16); \
+ boost::int16_t imag = boost::uint16_t(item >> 0); \
+ host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \
+ }
+ unrolled_loop(usrp2_items_to_host_floats_i, num_samps);
}
static inline void host_items_to_usrp2_items(
@@ -96,11 +99,12 @@ static inline void host_items_to_usrp2_items(
const boost::uint32_t *host_items,
size_t num_samps
){
+ #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i])
if (is_big_endian){
std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t));
}
else{
- unrolled_loop(i, num_samps, usrp2_items[i] = htonl(host_items[i]));
+ unrolled_loop(host_items_to_usrp2_items_i, num_samps);
}
}
@@ -109,11 +113,12 @@ static inline void usrp2_items_to_host_items(
const boost::uint32_t *usrp2_items,
size_t num_samps
){
+ #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i])
if (is_big_endian){
std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t));
}
else{
- unrolled_loop(i, num_samps, host_items[i] = ntohl(usrp2_items[i]));
+ unrolled_loop(usrp2_items_to_host_items_i, num_samps);
}
}
@@ -167,46 +172,43 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){
size_t usrp2_impl::send(
const asio::const_buffer &buff,
const tx_metadata_t &metadata,
- const std::string &type
+ const io_type_t &io_type
){
boost::uint32_t tx_mem[_mtu/sizeof(boost::uint32_t)];
- boost::uint32_t *items = tx_mem + vrt::max_header_words32; //offset for data
- size_t num_samps = _max_tx_samples_per_packet;
-
- //calculate the number of samples to be copied
- //and copy the samples into the send buffer
- if (type == "32fc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps);
- host_floats_to_usrp2_items(items, asio::buffer_cast<const fc32_t*>(buff), num_samps);
- }
- else if (type == "16sc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps);
- host_items_to_usrp2_items(items, asio::buffer_cast<const boost::uint32_t*>(buff), num_samps);
- }
- else{
- throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type));
- }
+ size_t num_samps = std::min(
+ asio::buffer_size(buff)/io_type.size,
+ size_t(_max_tx_samples_per_packet)
+ );
- boost::uint32_t vrt_hdr[vrt::max_header_words32];
size_t num_header_words32, num_packet_words32;
size_t packet_count = _tx_stream_id_to_packet_seq[metadata.stream_id]++;
//pack metadata into a vrt header
vrt::pack(
metadata, //input
- vrt_hdr, //output
+ tx_mem, //output
num_header_words32, //output
num_samps, //input
num_packet_words32, //output
packet_count //input
);
- //copy in the vrt header (yes we left space)
- items -= num_header_words32;
- std::memcpy(items, vrt_hdr, num_header_words32*sizeof(boost::uint32_t));
+ boost::uint32_t *items = tx_mem + num_header_words32; //offset for data
+
+ //copy the samples into the send buffer
+ switch(io_type.tid){
+ case io_type_t::COMPLEX_FLOAT32:
+ host_floats_to_usrp2_items(items, asio::buffer_cast<const fc32_t*>(buff), num_samps);
+ break;
+ case io_type_t::COMPLEX_INT16:
+ host_items_to_usrp2_items(items, asio::buffer_cast<const boost::uint32_t*>(buff), num_samps);
+ break;
+ default:
+ throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%c\"") % io_type.tid));
+ }
//send and return number of samples
- _data_transport->send(asio::buffer(items, num_packet_words32*sizeof(boost::uint32_t)));
+ _data_transport->send(asio::buffer(tx_mem, num_packet_words32*sizeof(boost::uint32_t)));
return num_samps;
}
@@ -216,7 +218,7 @@ size_t usrp2_impl::send(
size_t usrp2_impl::recv(
const asio::mutable_buffer &buff,
rx_metadata_t &metadata,
- const std::string &type
+ const io_type_t &io_type
){
//perform a receive if no rx data is waiting to be copied
if (asio::buffer_size(_rx_copy_buff) == 0){
@@ -232,21 +234,22 @@ size_t usrp2_impl::recv(
//and a pointer into the usrp2 received items memory
size_t bytes_to_copy = asio::buffer_size(_rx_copy_buff);
if (bytes_to_copy == 0) return 0; //nothing to receive
- size_t num_samps = bytes_to_copy/sizeof(boost::uint32_t);
+ size_t num_samps = std::min(
+ asio::buffer_size(buff)/io_type.size,
+ bytes_to_copy/sizeof(boost::uint32_t)
+ );
const boost::uint32_t *items = asio::buffer_cast<const boost::uint32_t*>(_rx_copy_buff);
- //calculate the number of samples to be copied
- //and copy the samples from the recv buffer
- if (type == "32fc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps);
+ //copy the samples from the recv buffer
+ switch(io_type.tid){
+ case io_type_t::COMPLEX_FLOAT32:
usrp2_items_to_host_floats(asio::buffer_cast<fc32_t*>(buff), items, num_samps);
- }
- else if (type == "16sc"){
- num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps);
+ break;
+ case io_type_t::COMPLEX_INT16:
usrp2_items_to_host_items(asio::buffer_cast<boost::uint32_t*>(buff), items, num_samps);
- }
- else{
- throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type));
+ break;
+ default:
+ throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%c\"") % io_type.tid));
}
//update the rx copy buffer to reflect the bytes copied
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index cbca8eec7..35dfd6287 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -15,7 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/mac_addr.hpp>
#include "usrp2_impl.hpp"
using namespace uhd;
@@ -35,27 +36,10 @@ void usrp2_impl::mboard_init(void){
}
void usrp2_impl::init_clock_config(void){
- //init the ref source clock config
- _ref_source_dict = boost::assign::map_list_of
- ("int", USRP2_REF_SOURCE_INT)
- ("sma", USRP2_REF_SOURCE_SMA)
- ("mimo", USRP2_REF_SOURCE_MIMO)
- ;
- _clock_config.ref_source = "int";
-
- //init the pps source clock config
- _pps_source_dict = boost::assign::map_list_of
- ("sma", USRP2_PPS_SOURCE_SMA)
- ("mimo", USRP2_PPS_SOURCE_MIMO)
- ;
- _clock_config.pps_source = "sma";
-
- //init the pps polarity clock config
- _pps_polarity_dict = boost::assign::map_list_of
- (clock_config_t::POLARITY_POS, USRP2_PPS_POLARITY_POS)
- (clock_config_t::POLARITY_NEG, USRP2_PPS_POLARITY_NEG)
- ;
- _clock_config.pps_polarity = clock_config_t::POLARITY_NEG;
+ //setup the clock configuration settings
+ _clock_config.ref_source = clock_config_t::REF_INT;
+ _clock_config.pps_source = clock_config_t::PPS_SMA;
+ _clock_config.pps_polarity = clock_config_t::PPS_NEG;
//update the clock config (sends a control packet)
update_clock_config();
@@ -65,9 +49,35 @@ void usrp2_impl::update_clock_config(void){
//setup the out data
usrp2_ctrl_data_t out_data;
out_data.id = htonl(USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO);
- out_data.data.clock_config.ref_source = _ref_source_dict [_clock_config.ref_source];
- out_data.data.clock_config.pps_source = _pps_source_dict [_clock_config.pps_source];
- out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_clock_config.pps_polarity];
+
+ //translate ref source enums
+ switch(_clock_config.ref_source){
+ case clock_config_t::REF_INT:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_INT; break;
+ case clock_config_t::REF_SMA:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_SMA; break;
+ case clock_config_t::REF_MIMO:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_MIMO; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration ref source");
+ }
+
+ //translate pps source enums
+ switch(_clock_config.pps_source){
+ case clock_config_t::PPS_SMA:
+ out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_SMA; break;
+ case clock_config_t::PPS_MIMO:
+ out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_MIMO; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration pps source");
+ }
+
+ //translate pps polarity enums
+ switch(_clock_config.pps_polarity){
+ case clock_config_t::PPS_POS:
+ out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_POS; break;
+ case clock_config_t::PPS_NEG:
+ out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_NEG; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration pps polarity");
+ }
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
@@ -106,7 +116,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE);
//extract the address
- val = reinterpret_cast<mac_addr_t*>(in_data.data.mac_addr)->to_string();
+ val = mac_addr_t::from_bytes(in_data.data.mac_addr).to_string();
return;
}
@@ -159,7 +169,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
return;
case MBOARD_PROP_CLOCK_RATE:
- val = freq_t(get_master_clock_freq());
+ val = double(get_master_clock_freq());
return;
case MBOARD_PROP_RX_DSP:
@@ -184,14 +194,6 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
val = _clock_config;
return;
- case MBOARD_PROP_PPS_SOURCE_NAMES:
- val = prop_names_t(_pps_source_dict.get_keys());
- return;
-
- case MBOARD_PROP_REF_SOURCE_NAMES:
- val = prop_names_t(_ref_source_dict.get_keys());
- return;
-
case MBOARD_PROP_TIME_NOW:
case MBOARD_PROP_TIME_NEXT_PPS:
throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard");
@@ -209,8 +211,8 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
//setup the out data
usrp2_ctrl_data_t out_data;
out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO);
- mac_addr_t mac_addr(val.as<std::string>());
- std::memcpy(out_data.data.mac_addr, &mac_addr, sizeof(mac_addr_t));
+ mac_addr_t mac_addr = mac_addr_t::from_string(val.as<std::string>());
+ std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr);
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
@@ -234,13 +236,9 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
- case MBOARD_PROP_CLOCK_CONFIG:{
- clock_config_t clock_config = val.as<clock_config_t>();
- assert_has(_pps_source_dict.get_keys(), clock_config.pps_source, "usrp2 pps source");
- assert_has(_ref_source_dict.get_keys(), clock_config.ref_source, "usrp2 ref source");
- _clock_config = clock_config; //shadow
- update_clock_config();
- }
+ case MBOARD_PROP_CLOCK_CONFIG:
+ _clock_config = val.as<clock_config_t>();
+ update_clock_config();
return;
case MBOARD_PROP_TIME_NOW:{
@@ -264,8 +262,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_RX_DBOARD_NAMES:
case MBOARD_PROP_TX_DBOARD:
case MBOARD_PROP_TX_DBOARD_NAMES:
- case MBOARD_PROP_PPS_SOURCE_NAMES:
- case MBOARD_PROP_REF_SOURCE_NAMES:
throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard");
}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 85d73e83a..67fbdf8d2 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -15,9 +15,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <uhd/transport/if_addrs.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
#include <boost/format.hpp>
+#include <boost/foreach.hpp>
#include <boost/bind.hpp>
-#include <uhd/utils.hpp>
#include <iostream>
#include "usrp2_impl.hpp"
@@ -27,16 +30,33 @@ using namespace uhd::transport;
namespace asio = boost::asio;
STATIC_BLOCK(register_usrp2_device){
- device::register_device(&usrp2::discover, &usrp2::make);
+ device::register_device(&usrp2::find, &usrp2::make);
}
/***********************************************************************
* Discovery over the udp transport
**********************************************************************/
-uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){
+uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
device_addrs_t usrp2_addrs;
- if (not hint.has_key("addr")) return usrp2_addrs;
+ //if no address was specified, send a broadcast on each interface
+ if (not hint.has_key("addr")){
+ BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){
+ //avoid the loopback device
+ if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue;
+
+ //create a new hint with this broadcast address
+ device_addr_t new_hint = hint;
+ new_hint["addr"] = if_addrs.bcast;
+
+ //call discover with the new hint and append results
+ device_addrs_t new_usrp2_addrs = usrp2::find(new_hint);
+ usrp2_addrs.insert(usrp2_addrs.begin(),
+ new_usrp2_addrs.begin(), new_usrp2_addrs.end()
+ );
+ }
+ return usrp2_addrs;
+ }
//create a udp transport to communicate
//TODO if an addr is not provided, search all interfaces?
@@ -63,7 +83,6 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){
boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr));
device_addr_t new_addr;
new_addr["name"] = "USRP2";
- new_addr["transport"] = "udp";
new_addr["addr"] = ip_addr.to_string();
usrp2_addrs.push_back(new_addr);
//dont break here, it will exit the while loop
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 55ac0b192..3468a0cf1 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -19,9 +19,10 @@
#define INCLUDED_USRP2_IMPL_HPP
#include <uhd/usrp/usrp2.hpp>
-#include <uhd/dict.hpp>
-#include <uhd/types.hpp>
-#include <uhd/time_spec.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/clock_config.hpp>
+#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
@@ -105,8 +106,8 @@ public:
double get_master_clock_freq(void);
//the io interface
- size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &);
- size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &);
+ size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &);
+ size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &);
private:
//device properties interface
@@ -146,11 +147,6 @@ private:
void update_clock_config(void);
void set_time_spec(const uhd::time_spec_t &time_spec, bool now);
- //mappings from clock config strings to over the wire enums
- uhd::dict<std::string, usrp2_ref_source_t> _ref_source_dict;
- uhd::dict<std::string, usrp2_pps_source_t> _pps_source_dict;
- uhd::dict<uhd::clock_config_t::polarity_t, usrp2_pps_polarity_t> _pps_polarity_dict;
-
//rx and tx dboard methods and objects
uhd::usrp::dboard_manager::sptr _dboard_manager;
void dboard_init(void);
@@ -177,16 +173,14 @@ private:
//methods and shadows for the ddc dsp
std::vector<size_t> _allowed_decim_and_interp_rates;
size_t _ddc_decim;
- uhd::freq_t _ddc_freq;
- bool _ddc_enabled;
- uhd::time_spec_t _ddc_stream_at;
+ double _ddc_freq;
void init_ddc_config(void);
void update_ddc_config(void);
- void update_ddc_enabled(void);
+ void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd);
//methods and shadows for the duc dsp
size_t _duc_interp;
- uhd::freq_t _duc_freq;
+ double _duc_freq;
void init_duc_config(void);
void update_duc_config(void);
diff --git a/host/test/addr_test.cpp b/host/test/addr_test.cpp
index 148aee015..a5d2d4c06 100644
--- a/host/test/addr_test.cpp
+++ b/host/test/addr_test.cpp
@@ -16,13 +16,52 @@
//
#include <boost/test/unit_test.hpp>
-#include <uhd/device_addr.hpp>
+#include <uhd/types/mac_addr.hpp>
+#include <uhd/types/device_addr.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
+#include <algorithm>
+#include <iostream>
BOOST_AUTO_TEST_CASE(test_mac_addr){
std::cout << "Testing mac addr..." << std::endl;
const std::string mac_addr_str("00:01:23:45:67:89");
- uhd::mac_addr_t mac_addr(mac_addr_str);
+ uhd::mac_addr_t mac_addr = uhd::mac_addr_t::from_string(mac_addr_str);
std::cout << "Input: " << mac_addr_str << std::endl;
- std::cout << "Output: " << mac_addr << std::endl;
+ std::cout << "Output: " << mac_addr.to_string() << std::endl;
BOOST_CHECK_EQUAL(mac_addr_str, mac_addr.to_string());
}
+
+BOOST_AUTO_TEST_CASE(test_device_addr){
+ std::cout << "Testing device addr..." << std::endl;
+
+ //load the device address with something
+ uhd::device_addr_t dev_addr;
+ dev_addr["key1"] = "val1";
+ dev_addr["key2"] = "val2";
+
+ //convert to and from args string
+ std::cout << "Pretty Print: " << std::endl << dev_addr.to_string();
+ std::string args_str = dev_addr.to_args_str();
+ std::cout << "Args String: " << args_str << std::endl;
+ uhd::device_addr_t new_dev_addr = uhd::device_addr_t::from_args_str(args_str);
+
+ //they should be the same size
+ BOOST_CHECK_EQUAL(dev_addr.size(), new_dev_addr.size());
+
+ //the keys should match
+ std::vector<std::string> old_dev_addr_keys = dev_addr.get_keys();
+ std::vector<std::string> new_dev_addr_keys = new_dev_addr.get_keys();
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ old_dev_addr_keys.begin(), old_dev_addr_keys.end(),
+ new_dev_addr_keys.begin(), new_dev_addr_keys.end()
+ );
+
+ //the vals should match
+ std::vector<std::string> old_dev_addr_vals = dev_addr.get_vals();
+ std::vector<std::string> new_dev_addr_vals = new_dev_addr.get_vals();
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ old_dev_addr_vals.begin(), old_dev_addr_vals.end(),
+ new_dev_addr_vals.begin(), new_dev_addr_vals.end()
+ );
+}
diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp
index 47acb30f0..76b065ce2 100644
--- a/host/test/gain_handler_test.cpp
+++ b/host/test/gain_handler_test.cpp
@@ -16,10 +16,10 @@
//
#include <boost/test/unit_test.hpp>
-#include <uhd/gain_handler.hpp>
-#include <uhd/types.hpp>
+#include <uhd/utils/gain_handler.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/types/dict.hpp>
#include <uhd/props.hpp>
-#include <uhd/dict.hpp>
#include <boost/bind.hpp>
#include <iostream>
@@ -46,8 +46,8 @@ public:
);
_gain_values["g0"] = 0;
_gain_values["g1"] = 0;
- _gain_ranges["g0"] = gain_range_t(-10, 0, .1);
- _gain_ranges["g1"] = gain_range_t(0, 100, 1.5);
+ _gain_ranges["g0"] = gain_range_t(-10, 0, float(.1));
+ _gain_ranges["g1"] = gain_range_t(0, 100, float(1.5));
}
~gainful_obj(void){}
@@ -84,7 +84,7 @@ private:
//handle the get request conditioned on the key
switch(key.as<prop_t>()){
case PROP_GAIN_VALUE:
- _gain_values[name] = val.as<gain_t>();
+ _gain_values[name] = val.as<float>();
return;
case PROP_GAIN_RANGE:
@@ -94,7 +94,7 @@ private:
}
gain_handler::sptr _gain_handler;
- uhd::dict<std::string, gain_t> _gain_values;
+ uhd::dict<std::string, float> _gain_values;
uhd::dict<std::string, gain_range_t> _gain_ranges;
};
@@ -104,18 +104,18 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){
gainful_obj go0;
BOOST_CHECK_THROW(
- go0[named_prop_t(PROP_GAIN_VALUE, "fail")].as<gain_t>(),
+ go0[named_prop_t(PROP_GAIN_VALUE, "fail")].as<float>(),
std::exception
);
std::cout << "verifying the overall min, max, step" << std::endl;
gain_range_t gain = go0[PROP_GAIN_RANGE].as<gain_range_t>();
- BOOST_CHECK_EQUAL(gain.min, gain_t(-10));
- BOOST_CHECK_EQUAL(gain.max, gain_t(100));
- BOOST_CHECK_EQUAL(gain.step, gain_t(1.5));
+ BOOST_CHECK_EQUAL(gain.min, float(-10));
+ BOOST_CHECK_EQUAL(gain.max, float(100));
+ BOOST_CHECK_EQUAL(gain.step, float(1.5));
std::cout << "verifying the overall gain" << std::endl;
- go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = gain_t(-5);
- go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = gain_t(30);
- BOOST_CHECK_EQUAL(go0[PROP_GAIN_VALUE].as<gain_t>(), gain_t(25));
+ go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = float(-5);
+ go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = float(30);
+ BOOST_CHECK_EQUAL(go0[PROP_GAIN_VALUE].as<float>(), float(25));
}
diff --git a/host/test/module_test.cpp b/host/test/module_test.cpp
index 71721ef90..47a0e1af9 100644
--- a/host/test/module_test.cpp
+++ b/host/test/module_test.cpp
@@ -15,10 +15,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/utils.hpp>
+#include <uhd/utils/static.hpp>
#include <iostream>
-STATIC_BLOCK(module_test){
+UHD_STATIC_BLOCK(module_test){
std::cout << "---------------------------------------" << std::endl;
std::cout << "-- Good news, everyone!" << std::endl;
std::cout << "-- The test module has been loaded." << std::endl;
diff --git a/host/test/wax_test.cpp b/host/test/wax_test.cpp
index cb3b12052..731f470ed 100644
--- a/host/test/wax_test.cpp
+++ b/host/test/wax_test.cpp
@@ -16,6 +16,7 @@
//
#include <boost/test/unit_test.hpp>
+#include <boost/shared_ptr.hpp>
#include <uhd/wax.hpp>
#include <iostream>
@@ -32,26 +33,29 @@ BOOST_AUTO_TEST_CASE(test_enums){
* demo class for wax framework
**********************************************************************/
class wax_demo : public wax::obj{
-private:
- std::vector<float> d_nums;
- std::vector<wax_demo> d_subs;
public:
+ typedef boost::shared_ptr<wax_demo> sptr;
+
wax_demo(size_t sub_demos, size_t len){
d_nums = std::vector<float>(len);
if (sub_demos != 0){
for (size_t i = 0; i < len; i++){
- d_subs.push_back(wax_demo(sub_demos-1, len));
+ d_subs.push_back(sptr(new wax_demo(sub_demos-1, len)));
}
}
}
~wax_demo(void){
/* NOP */
}
+private:
+ std::vector<float> d_nums;
+ std::vector<sptr> d_subs;
+
void get(const wax::obj &key, wax::obj &value){
if (d_subs.size() == 0){
value = d_nums[key.as<size_t>()];
}else{
- value = d_subs[key.as<size_t>()].get_link();
+ value = d_subs[key.as<size_t>()]->get_link();
}
}
void set(const wax::obj &key, const wax::obj &value){
@@ -63,9 +67,8 @@ public:
}
};
-static wax_demo wd(2, 10);
-
BOOST_AUTO_TEST_CASE(test_chaining){
+ wax_demo wd(2, 1);
std::cout << "chain 1" << std::endl;
wd[size_t(0)];
std::cout << "chain 2" << std::endl;
@@ -75,6 +78,7 @@ BOOST_AUTO_TEST_CASE(test_chaining){
}
BOOST_AUTO_TEST_CASE(test_set_get){
+ wax_demo wd(2, 10);
std::cout << "set and get all" << std::endl;
for (size_t i = 0; i < 10; i++){
for (size_t j = 0; j < 10; j++){
@@ -89,6 +93,7 @@ BOOST_AUTO_TEST_CASE(test_set_get){
}
BOOST_AUTO_TEST_CASE(test_proxy){
+ wax_demo wd(2, 1);
std::cout << "store proxy" << std::endl;
wax::obj p = wd[size_t(0)][size_t(0)];
p[size_t(0)] = float(5);
diff --git a/host/uhd.pc.in b/host/uhd.pc.in
index 59ba623f5..2a34e9cfd 100644
--- a/host/uhd.pc.in
+++ b/host/uhd.pc.in
@@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${prefix}/@LIBRARY_DIR@
-includedir=${prefix}/@HEADER_DIR@
+includedir=${prefix}/@INCLUDE_DIR@
Name: @CPACK_PACKAGE_NAME@
Description: Universal Hardware Driver
diff --git a/host/apps/CMakeLists.txt b/host/utils/CMakeLists.txt
index 58f73fcd6..99e648d8a 100644
--- a/host/apps/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -15,12 +15,15 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-ADD_EXECUTABLE(discover_usrps discover_usrps.cpp)
-TARGET_LINK_LIBRARIES(discover_usrps uhd)
-INSTALL(TARGETS discover_usrps RUNTIME DESTINATION ${RUNTIME_DIR})
+ADD_EXECUTABLE(uhd_find_devices uhd_find_devices.cpp)
+TARGET_LINK_LIBRARIES(uhd_find_devices uhd)
+INSTALL(TARGETS uhd_find_devices RUNTIME DESTINATION ${RUNTIME_DIR})
ADD_EXECUTABLE(usrp1e_load_fpga usrp1e_load_fpga.cpp)
TARGET_LINK_LIBRARIES(usrp1e_load_fpga uhd)
ADD_EXECUTABLE(usrp2_burner usrp2_burner.cpp)
TARGET_LINK_LIBRARIES(usrp2_burner uhd)
+INSTALL(TARGETS usrp2_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils)
+
+INSTALL(PROGRAMS usrp2_recovery.py DESTINATION ${PKG_DATA_DIR}/utils)
diff --git a/host/apps/discover_usrps.cpp b/host/utils/uhd_find_devices.cpp
index d670d1651..b328216d0 100644
--- a/host/apps/discover_usrps.cpp
+++ b/host/utils/uhd_find_devices.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <uhd/utils/safe_main.hpp>
#include <uhd/device.hpp>
#include <uhd/props.hpp>
#include <boost/program_options.hpp>
@@ -23,7 +24,7 @@
namespace po = boost::program_options;
-int main(int argc, char *argv[]){
+int UHD_SAFE_MAIN(int argc, char *argv[]){
po::options_description desc("Allowed options");
desc.add_options()
("help", "help message")
@@ -33,11 +34,11 @@ int main(int argc, char *argv[]){
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
+ po::notify(vm);
//print the help message
if (vm.count("help")){
- std::cout << boost::format("Discover USRPs %s") % desc << std::endl;
+ std::cout << boost::format("UHD Find Devices %s") % desc << std::endl;
return ~0;
}
@@ -51,18 +52,18 @@ int main(int argc, char *argv[]){
}
//discover the usrps and print the results
- uhd::device_addrs_t device_addrs = uhd::device::discover(device_addr);
+ uhd::device_addrs_t device_addrs = uhd::device::find(device_addr);
if (device_addrs.size() == 0){
- std::cerr << "No USRP Devices Found" << std::endl;
+ std::cerr << "No UHD Devices Found" << std::endl;
return ~0;
}
for (size_t i = 0; i < device_addrs.size(); i++){
std::cout << "--------------------------------------------------" << std::endl;
- std::cout << "-- USRP Device " << i << std::endl;
+ std::cout << "-- UHD Device " << i << std::endl;
std::cout << "--------------------------------------------------" << std::endl;
- std::cout << device_addrs[i] << std::endl << std::endl;
+ std::cout << device_addrs[i].to_string() << std::endl << std::endl;
uhd::device::make(device_addrs[i]); //test make
}
diff --git a/host/apps/usrp2_burner.cpp b/host/utils/usrp2_burner.cpp
index 941e71d0c..b24425316 100644
--- a/host/apps/usrp2_burner.cpp
+++ b/host/utils/usrp2_burner.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <uhd/utils/safe_main.hpp>
#include <uhd/usrp/usrp2.hpp>
#include <uhd/props.hpp>
#include <boost/program_options.hpp>
@@ -23,7 +24,7 @@
namespace po = boost::program_options;
-int main(int argc, char *argv[]){
+int UHD_SAFE_MAIN(int argc, char *argv[]){
po::options_description desc("Allowed options");
desc.add_options()
("help", "help message")
@@ -56,27 +57,32 @@ int main(int argc, char *argv[]){
uhd::device::sptr u2_dev = uhd::usrp::usrp2::make(device_addr);
//FIXME usees the default mboard for now (until the mimo link is supported)
wax::obj u2_mb = (*u2_dev)[uhd::DEVICE_PROP_MBOARD];
+ std::cout << std::endl;
+
+ //fetch and print current settings
+ std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl;
+ std::string curr_ip = u2_mb[std::string("ip-addr")].as<std::string>();
+ std::cout << boost::format(" Current IP Address: %s") % curr_ip << std::endl;
+ std::string curr_mac = u2_mb[std::string("mac-addr")].as<std::string>();
+ std::cout << boost::format(" Current MAC Address: %s") % curr_mac << std::endl;
+ std::cout << " Done" << std::endl << std::endl;
//try to set the new ip (if provided)
if (vm.count("new-ip")){
std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl;
- std::string old_ip = u2_mb[std::string("ip-addr")].as<std::string>();
- std::cout << boost::format(" Old IP Address: %s") % old_ip << std::endl;
std::string new_ip = vm["new-ip"].as<std::string>();
std::cout << boost::format(" New IP Address: %s") % new_ip << std::endl;
u2_mb[std::string("ip-addr")] = new_ip;
- std::cout << " Done" << std::endl;
+ std::cout << " Done" << std::endl << std::endl;
}
//try to set the new mac (if provided)
if (vm.count("new-mac")){
std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl;
- std::string old_mac = u2_mb[std::string("mac-addr")].as<std::string>();
- std::cout << boost::format(" Old MAC Address: %s") % old_mac << std::endl;
std::string new_mac = vm["new-mac"].as<std::string>();
std::cout << boost::format(" New MAC Address: %s") % new_mac << std::endl;
u2_mb[std::string("mac-addr")] = new_mac;
- std::cout << " Done" << std::endl;
+ std::cout << " Done" << std::endl << std::endl;
}
std::cout << "Power-cycle the usrp2 for the changes to take effect." << std::endl;
diff --git a/host/apps/usrp2_recovery.py b/host/utils/usrp2_recovery.py
index 48c1121cb..5654e93d3 100755
--- a/host/apps/usrp2_recovery.py
+++ b/host/utils/usrp2_recovery.py
@@ -1,4 +1,20 @@
#!/usr/bin/env python
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
"""
The usrp2 recovery app: