aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Foster <nick@nerdnetworks.org>2010-08-18 14:48:35 -0700
committerNick Foster <nick@nerdnetworks.org>2010-08-18 14:48:35 -0700
commit2da87fa5082c507d324dce743d63667a6d21fd80 (patch)
treeead6d4b7e9af0a403d6079134f9fa992dc52102c
parent40faee2e6d87f7364a0c0c2cf310f1483c0331cf (diff)
parent8740197dfed997bb235b73ec649edb803d544326 (diff)
downloaduhd-2da87fa5082c507d324dce743d63667a6d21fd80.tar.gz
uhd-2da87fa5082c507d324dce743d63667a6d21fd80.tar.bz2
uhd-2da87fa5082c507d324dce743d63667a6d21fd80.zip
Merge branch 'master' of ettus.sourcerepo.com:ettus/uhdpriv into usrp2p
-rw-r--r--firmware/microblaze/apps/txrx_uhd.c76
-rw-r--r--firmware/microblaze/lib/dbsm.c8
-rw-r--r--firmware/microblaze/lib/i2c.c185
-rw-r--r--firmware/microblaze/lib/i2c.h18
-rw-r--r--firmware/microblaze/lib/spi.c47
-rw-r--r--firmware/microblaze/lib/spi.h7
-rw-r--r--firmware/microblaze/lib/u2_init.c14
-rw-r--r--fpga/usrp2/vrt/vita_rx_framer.v2
-rw-r--r--host/config/Version.cmake2
-rw-r--r--host/docs/CMakeLists.txt1
-rw-r--r--host/docs/images.rst104
-rw-r--r--host/docs/index.rst1
-rw-r--r--host/docs/usrp2.rst36
-rw-r--r--host/include/uhd/usrp/CMakeLists.txt2
-rw-r--r--host/include/uhd/usrp/dboard_iface.hpp29
-rw-r--r--host/include/uhd/usrp/dboard_manager.hpp2
-rw-r--r--host/include/uhd/usrp/dsp_utils.hpp99
-rw-r--r--host/include/uhd/usrp/misc_utils.hpp68
-rw-r--r--host/include/uhd/utils/algorithm.hpp21
-rw-r--r--host/include/uhd/utils/props.hpp33
-rw-r--r--host/lib/CMakeLists.txt11
-rw-r--r--host/lib/constants.hpp.in7
-rw-r--r--host/lib/types.cpp19
-rw-r--r--host/lib/usrp/CMakeLists.txt3
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp12
-rw-r--r--host/lib/usrp/dboard/db_dbsrx.cpp60
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp26
-rw-r--r--host/lib/usrp/dboard/db_unknown.cpp12
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp32
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp32
-rw-r--r--host/lib/usrp/dsp_utils.cpp124
-rw-r--r--host/lib/usrp/dsp_utils.hpp187
-rw-r--r--host/lib/usrp/misc_utils.cpp85
-rw-r--r--host/lib/usrp/misc_utils.hpp35
-rw-r--r--host/lib/usrp/subdev_spec.cpp15
-rw-r--r--host/lib/usrp/usrp2/codec_impl.cpp8
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp7
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp22
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp11
-rw-r--r--host/lib/usrp/usrp2/fw_common.h2
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp37
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp17
-rw-r--r--host/lib/utils/paths.cpp18
-rw-r--r--host/lib/utils/props.cpp9
-rw-r--r--host/lib/utils/warning.cpp8
-rw-r--r--host/utils/uhd_usrp_probe.cpp4
46 files changed, 1028 insertions, 530 deletions
diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c
index 9cf4c163f..1c6e0624f 100644
--- a/firmware/microblaze/apps/txrx_uhd.c
+++ b/firmware/microblaze/apps/txrx_uhd.c
@@ -172,6 +172,33 @@ void handle_udp_data_packet(
#define OTW_GPIO_BANK_TO_NUM(bank) \
(((bank) == USRP2_DIR_RX)? (GPIO_RX_BANK) : (GPIO_TX_BANK))
+//setup the output data
+static usrp2_ctrl_data_t ctrl_data_out;
+static struct socket_address i2c_src;
+static struct socket_address spi_src;
+
+static volatile bool i2c_done = false;
+void i2c_read_done_callback(void) {
+ //printf("I2C read done callback\n");
+ i2c_async_data_ready(ctrl_data_out.data.i2c_args.data);
+ i2c_done = true;
+ i2c_register_callback(0);
+}
+
+void i2c_write_done_callback(void) {
+ //printf("I2C write done callback\n");
+ i2c_done = true;
+ i2c_register_callback(0);
+}
+
+static volatile bool spi_done = false;
+static volatile uint32_t spi_readback_data;
+void get_spi_readback_data(void) {
+ ctrl_data_out.data.spi_args.data = spi_get_data();
+ spi_done = true;
+ spi_register_callback(0);
+}
+
void handle_udp_ctrl_packet(
struct socket_address src, struct socket_address dst,
unsigned char *payload, int payload_len
@@ -197,11 +224,9 @@ void handle_udp_ctrl_packet(
}
//setup the output data
- usrp2_ctrl_data_t ctrl_data_out = {
- .proto_ver = USRP2_FW_COMPAT_NUM,
- .id=USRP2_CTRL_ID_HUH_WHAT,
- .seq=ctrl_data_in->seq
- };
+ ctrl_data_out.proto_ver = USRP2_FW_COMPAT_NUM;
+ ctrl_data_out.id=USRP2_CTRL_ID_HUH_WHAT;
+ ctrl_data_out.seq=ctrl_data_in->seq;
//handle the data based on the id
switch(ctrl_data_in_id){
@@ -212,6 +237,7 @@ void handle_udp_ctrl_packet(
case USRP2_CTRL_ID_WAZZUP_BRO:
ctrl_data_out.id = USRP2_CTRL_ID_WAZZUP_DUDE;
memcpy(&ctrl_data_out.data.ip_addr, get_ip_addr(), sizeof(struct ip_addr));
+ send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));
break;
/*******************************************************************
@@ -219,19 +245,21 @@ void handle_udp_ctrl_packet(
******************************************************************/
case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{
//transact
- uint32_t result = spi_transact(
- (ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX,
+ bool success = spi_async_transact(
+ //(ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX,
ctrl_data_in->data.spi_args.dev, //which device
ctrl_data_in->data.spi_args.data, //32 bit data
ctrl_data_in->data.spi_args.num_bits, //length in bits
- (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE |
- (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL
+ (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | //flags
+ (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL,
+ get_spi_readback_data //callback
);
//load output
- ctrl_data_out.data.spi_args.data = result;
ctrl_data_out.id = USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE;
+ spi_src = src;
}
+// send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));
break;
/*******************************************************************
@@ -239,11 +267,13 @@ void handle_udp_ctrl_packet(
******************************************************************/
case USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO:{
uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes;
- i2c_read(
+ i2c_register_callback(i2c_read_done_callback);
+ i2c_async_read(
ctrl_data_in->data.i2c_args.addr,
- ctrl_data_out.data.i2c_args.data,
num_bytes
);
+ i2c_src = src;
+// i2c_dst = dst;
ctrl_data_out.id = USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE;
ctrl_data_out.data.i2c_args.bytes = num_bytes;
}
@@ -251,11 +281,14 @@ void handle_udp_ctrl_packet(
case USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO:{
uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes;
- i2c_write(
+ i2c_register_callback(i2c_read_done_callback);
+ i2c_async_write(
ctrl_data_in->data.i2c_args.addr,
ctrl_data_in->data.i2c_args.data,
num_bytes
);
+ i2c_src = src;
+// i2c_dst = dst;
ctrl_data_out.id = USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE;
ctrl_data_out.data.i2c_args.bytes = num_bytes;
}
@@ -287,6 +320,7 @@ void handle_udp_ctrl_packet(
}
ctrl_data_out.id = USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE;
+ send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));
break;
case USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO:
@@ -309,6 +343,7 @@ void handle_udp_ctrl_packet(
}
ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE;
+ send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));
break;
case USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO:{
@@ -335,9 +370,9 @@ void handle_udp_ctrl_packet(
default:
ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT;
-
+ send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));
}
- send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));
+
}
/*
@@ -503,6 +538,17 @@ main(void)
buffer_irq_handler(0);
+ if(i2c_done) {
+ i2c_done = false;
+ send_udp_pkt(USRP2_UDP_CTRL_PORT, i2c_src, &ctrl_data_out, sizeof(ctrl_data_out));
+ //printf("Sending UDP packet from main loop for I2C...\n");
+ }
+
+ if(spi_done) {
+ spi_done = false;
+ send_udp_pkt(USRP2_UDP_CTRL_PORT, spi_src, &ctrl_data_out, sizeof(ctrl_data_out));
+ }
+
int pending = pic_regs->pending; // poll for under or overrun
if (pending & PIC_UNDERRUN_INT){
diff --git a/firmware/microblaze/lib/dbsm.c b/firmware/microblaze/lib/dbsm.c
index d495860fd..cee343eaa 100644
--- a/firmware/microblaze/lib/dbsm.c
+++ b/firmware/microblaze/lib/dbsm.c
@@ -160,12 +160,12 @@ dbsm_process_status(dbsm_t *sm, uint32_t status)
putchar('E');
// Most likely an ethernet Rx error. We just restart the transfer.
if (status & (BPS_ERROR(sm->buf0)))
- //dbsm_error_helper(sm, sm->buf0);
- dbsm_process_helper(sm, sm->buf0); //forward errors
+ dbsm_error_helper(sm, sm->buf0);
+ //dbsm_process_helper(sm, sm->buf0); //forward errors
if (status & (BPS_ERROR(sm->buf0 ^ 1)))
- //dbsm_error_helper(sm, sm->buf0 ^ 1);
- dbsm_process_helper(sm, sm->buf0 ^ 1); //forward errors
+ dbsm_error_helper(sm, sm->buf0 ^ 1);
+ //dbsm_process_helper(sm, sm->buf0 ^ 1); //forward errors
}
if (status & BPS_DONE(sm->buf0))
diff --git a/firmware/microblaze/lib/i2c.c b/firmware/microblaze/lib/i2c.c
index 3f738733b..177341267 100644
--- a/firmware/microblaze/lib/i2c.c
+++ b/firmware/microblaze/lib/i2c.c
@@ -19,12 +19,15 @@
#include "i2c.h"
#include "memory_map.h"
#include "stdint.h"
+#include <string.h>
+#include "pic.h"
+#include "nonstdio.h"
#define MAX_WB_DIV 4 // maximum wishbone divisor (from 100 MHz MASTER_CLK)
// prescaler divisor values for 100 kHz I2C [uses 5 * SCLK internally]
-#define PRESCALER(wb_div) (((MASTER_CLK_RATE/(wb_div)) / (5 * 100000)) - 1)
+#define PRESCALER(wb_div) (((MASTER_CLK_RATE/(wb_div)) / (5 * 400000)) - 1)
static uint16_t prescaler_values[MAX_WB_DIV+1] = {
0xffff, // 0: can't happen
@@ -34,6 +37,18 @@ static uint16_t prescaler_values[MAX_WB_DIV+1] = {
PRESCALER(4), // 4: 25 MHz
};
+//asynchronous (interrupt-driven) i2c state variables
+volatile uint8_t i2c_buf[17]; //tx/rx data transfer buffer
+volatile uint8_t *volatile i2c_bufptr = i2c_buf; //ptr to current position
+volatile uint8_t i2c_len = 0; //length remaining in current transfer
+volatile i2c_state_t i2c_state = I2C_STATE_IDLE; //current I2C transfer state
+i2c_dir_t i2c_dir; //I2C transfer direction
+
+void (*volatile i2c_callback)(void); //function pointer to i2c callback to be called when transaction is complete
+
+static void i2c_irq_handler(unsigned irq);
+inline void i2c_async_err(void);
+
void
i2c_init(void)
{
@@ -47,9 +62,10 @@ i2c_init(void)
i2c_regs->prescaler_lo = prescaler_values[wb_div] & 0xff;
i2c_regs->prescaler_hi = (prescaler_values[wb_div] >> 8) & 0xff;
- i2c_regs->ctrl = I2C_CTRL_EN; // enable core
+ i2c_regs->ctrl = I2C_CTRL_EN; //| I2C_CTRL_IE; // enable core
- // FIXME interrupt driven?
+ // FIXME interrupt driven?
+ pic_register_handler(IRQ_I2C, i2c_irq_handler);
}
static inline void
@@ -107,7 +123,7 @@ i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len)
i2c_regs->data = (i2c_addr << 1) | 0; // 7 bit address and write bit (0)
// generate START and write addr (and maybe STOP)
- i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START | (len == 0 ? I2C_CMD_STOP : 0);
+ i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START | (len == 0 ? I2C_CMD_STOP : 0);
if (!wait_chk_ack())
goto fail;
@@ -124,4 +140,163 @@ i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len)
return false;
}
-
+static void i2c_irq_handler(unsigned irq) {
+//i2c state machine.
+
+ //printf("I2C irq handler\n");
+ //first let's make sure nothing is f'ed up
+ //TODO: uncomment this error checking when we have some way to handle errors
+// if(((i2c_regs->cmd_status & I2C_ST_RXACK) != 0) && i2c_dir == I2C_DIR_WRITE) { //we got a NACK and we didn't send it
+// printf("\tNACK received\n");
+// i2c_async_err();
+// return;
+// }// else printf("\tACK received, proceeding\n");
+
+ if(i2c_regs->cmd_status & I2C_ST_AL) {
+ printf("\tArbitration lost!\n");
+ i2c_async_err();
+ return;
+ }
+
+ if(i2c_regs->cmd_status & I2C_ST_TIP) {
+ //printf("\tI2C still busy in interrupt\n");
+ return;
+ }
+
+ //now decide what to do
+ switch(i2c_state) {
+
+ case I2C_STATE_IDLE:
+ //this is an error. in idle state, we shouldn't be transferring data, and the fact that the IRQ fired is terrible bad.
+ printf("AAAAAHHHHH INTERRUPT IN THE IDLE STATE AAAHHHHHHHHH\n");
+ i2c_async_err();
+ break;
+
+ case I2C_STATE_CONTROL_BYTE_SENT: //here we've sent the control byte, and we're either clocking data in or out now, but we haven't received a byte yet.
+ case I2C_STATE_DATA: //here we're sending/receiving data and if we're receiving there's data in the data reg
+
+ //if(i2c_state == I2C_STATE_DATA) printf("\tI2C in state DATA with dir=%d and len=%d\n", i2c_dir, i2c_len);
+ //else printf("\tI2C in state CONTROL_BYTE_SENT with dir=%d and len=%d\n", i2c_dir, i2c_len);
+
+ if(i2c_dir == I2C_DIR_READ) {
+ if(i2c_state == I2C_STATE_DATA) *(i2c_bufptr++) = i2c_regs->data;
+ //printf("\tRead %x\n", *(i2c_bufptr-1));
+ //set up another data byte
+ if(i2c_len > 1) //only one more byte to transfer
+ i2c_regs->cmd_status = I2C_CMD_RD;
+ else
+ i2c_regs->cmd_status = I2C_CMD_RD | I2C_CMD_NACK | I2C_CMD_STOP;
+ }
+ else if(i2c_dir == I2C_DIR_WRITE) {
+ //write a byte
+ //printf("\tWriting %x\n", *i2c_bufptr);
+ i2c_regs->data = *(i2c_bufptr++);
+ if(i2c_len > 1)
+ i2c_regs->cmd_status = I2C_CMD_WR;
+ else {
+ //printf("\tGenerating STOP\n");
+ i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_STOP;
+ }
+ };
+ i2c_len--;
+ if(i2c_len == 0) i2c_state = I2C_STATE_LAST_BYTE;
+ else i2c_state = I2C_STATE_DATA; //takes care of the addr_sent->data transition
+ break;
+
+
+ case I2C_STATE_LAST_BYTE: //here we've already sent the last read request and the last data is waiting for us.
+ //printf("\tI2C in state LAST BYTE\n");
+
+ if(i2c_dir == I2C_DIR_READ) {
+ *(i2c_bufptr++) = i2c_regs->data;
+ //printf("\tRead %x\n", *(i2c_bufptr-1));
+ i2c_state = I2C_STATE_DATA_READY;
+ } else {
+ i2c_state = I2C_STATE_IDLE;
+ }
+ i2c_regs->ctrl &= ~I2C_CTRL_IE; //disable interrupts until next time
+
+ if(i2c_callback) {
+ i2c_callback(); //if we registered a callback, call it!
+ }
+
+ break;
+
+
+ default: //terrible things have happened.
+ break;
+ }
+
+}
+
+void i2c_register_callback(void (*volatile callback)(void)) {
+ i2c_callback = callback;
+}
+
+inline void i2c_async_err(void) {
+ i2c_state = I2C_STATE_IDLE;
+ i2c_regs->ctrl &= ~I2C_CTRL_IE;
+ printf("I2C error\n");
+//TODO: set an error flag instead of just dropping things on the floor
+ i2c_regs->cmd_status = I2C_CMD_STOP;
+}
+
+bool i2c_async_read(uint8_t addr, unsigned int len) {
+ //printf("Starting async read\n");
+ if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle
+ if(len == 0) return true; //just idiot-proofing
+ if(len > sizeof(i2c_buf)) return false;
+
+ //disable I2C interrupts and clear pending interrupts on the I2C device
+ i2c_regs->ctrl &= ~I2C_CTRL_IE;
+ i2c_regs->cmd_status |= I2C_CMD_IACK;
+
+ i2c_len = len;
+ i2c_dir = I2C_DIR_READ;
+ i2c_bufptr = i2c_buf;
+ //then set up the transfer by issuing the control byte
+ i2c_regs->ctrl |= I2C_CTRL_IE;
+ i2c_regs->data = (addr << 1) | 0x01; //7 bit addr and read bit
+ i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr
+ //update the state so the irq handler knows what's going on
+ i2c_state = I2C_STATE_CONTROL_BYTE_SENT;
+ return true;
+}
+
+bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len) {
+ //printf("Starting async write\n");
+ if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle
+ if(len > sizeof(i2c_buf)) return false;
+
+ //disable I2C interrupts and clear pending interrupts on the I2C device
+ i2c_regs->ctrl &= ~I2C_CTRL_IE;
+ i2c_regs->cmd_status |= I2C_CMD_IACK;
+
+ //copy the buffer into our own if writing
+ memcpy((void *)i2c_buf, buf, len);
+
+ i2c_len = len;
+ i2c_dir = I2C_DIR_WRITE;
+ i2c_bufptr = i2c_buf;
+ //then set up the transfer by issuing the control byte
+ i2c_regs->ctrl |= I2C_CTRL_IE;
+ i2c_regs->data = (addr << 1) | 0x00; //7 bit addr and read bit
+ i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr
+ //update the state so the irq handler knows what's going on
+ i2c_state = I2C_STATE_CONTROL_BYTE_SENT;
+
+ return true;
+}
+
+//TODO: determine if it's better to read sequentially into the user's buffer, copy on transfer complete, or copy on request (shown below). probably best to copy on request.
+bool i2c_async_data_ready(void *buf) {
+ if(i2c_state == I2C_STATE_DATA_READY) {
+ i2c_state = I2C_STATE_IDLE;
+ memcpy(buf, (void *)i2c_buf, (i2c_bufptr - i2c_buf)); //TODO: not really comfortable with this
+ //printf("Copying %d bytes to user buffer\n", i2c_bufptr-i2c_buf);
+ return true;
+ }
+ return false;
+}
+
+
diff --git a/firmware/microblaze/lib/i2c.h b/firmware/microblaze/lib/i2c.h
index ecb6aa0d2..77129e922 100644
--- a/firmware/microblaze/lib/i2c.h
+++ b/firmware/microblaze/lib/i2c.h
@@ -20,20 +20,38 @@
#define INCLUDED_I2C_H
#include <stdbool.h>
+#include "stdint.h"
+
+typedef enum { I2C_STATE_IDLE,
+ I2C_STATE_CONTROL_BYTE_SENT,
+ I2C_STATE_DATA,
+ I2C_STATE_LAST_BYTE,
+ I2C_STATE_DATA_READY,
+ I2C_STATE_ERROR
+ } i2c_state_t;
+
+typedef enum { I2C_DIR_WRITE=0, I2C_DIR_READ=1 } i2c_dir_t;
void i2c_init(void);
bool i2c_read (unsigned char i2c_addr, unsigned char *buf, unsigned int len);
bool i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len);
+bool i2c_async_read(uint8_t addr, unsigned int len);
+bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len);
+bool i2c_async_data_ready(void *);
+//static void i2c_irq_handler(unsigned irq);
+void i2c_register_callback(void (*callback)(void));
// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
// Which EEPROM is determined by i2c_addr. See i2c_addr.h
bool eeprom_write (int i2c_addr, int eeprom_offset, const void *buf, int len);
+bool eeprom_write_async (int i2c_addr, int eeprom_offset, const void *buf, int len, void (*callback)(void));
// Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
// Which EEPROM is determined by i2c_addr. See i2c_addr.h
bool eeprom_read (int i2c_addr, int eeprom_offset, void *buf, int len);
+bool eeprom_read_async(int i2c_addr, int eeprom_offset, void *buf, int len, void (*callback)(void));
#endif /* INCLUDED_I2C_H */
diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c
index bef808e57..2a41a1bfa 100644
--- a/firmware/microblaze/lib/spi.c
+++ b/firmware/microblaze/lib/spi.c
@@ -17,6 +17,12 @@
#include "spi.h"
#include "memory_map.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+void (*volatile spi_callback)(void); //SPI callback when xfer complete.
+
+static void spi_irq_handler(unsigned irq);
void
spi_init(void)
@@ -59,3 +65,44 @@ spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags
else
return 0;
}
+
+void spi_register_callback(void (*volatile callback)(void)) {
+ spi_callback = callback;
+}
+
+static void spi_irq_handler(unsigned irq) {
+// printf("SPI IRQ handler\n");
+// uint32_t wat = spi_regs->ctrl; //read a register just to clear the interrupt
+ //spi_regs->ctrl &= ~SPI_CTRL_IE;
+ if(spi_callback) spi_callback(); //we could just use the PIC to register the user's callback, but this provides the ability to do other things later
+}
+
+uint32_t spi_get_data(void) {
+ return spi_regs->txrx0;
+}
+
+bool
+spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)) {
+ flags &= (SPI_CTRL_TXNEG | SPI_CTRL_RXNEG);
+ int ctrl = SPI_CTRL_ASS | SPI_CTRL_IE | (SPI_CTRL_CHAR_LEN_MASK & length) | flags;
+
+ if(spi_regs->ctrl & SPI_CTRL_GO_BSY) {
+ printf("Async SPI busy!\n");
+ return false; //we don't wait on busy, we just return failure. we count on the host to not set up another transaction before the last one finishes.
+ }
+
+ // Tell it which SPI slave device to access
+ spi_regs->ss = slave & 0xffff;
+
+ // Data we will send
+ spi_regs->txrx0 = data;
+
+ spi_register_callback(callback);
+ pic_register_handler(IRQ_SPI, spi_irq_handler);
+
+ // Run it -- write once and rewrite with GO set
+ spi_regs->ctrl = ctrl;
+ spi_regs->ctrl = ctrl | SPI_CTRL_GO_BSY;
+
+ return true;
+}
diff --git a/firmware/microblaze/lib/spi.h b/firmware/microblaze/lib/spi.h
index 01e4d26fd..54618cedd 100644
--- a/firmware/microblaze/lib/spi.h
+++ b/firmware/microblaze/lib/spi.h
@@ -48,6 +48,13 @@ void spi_wait(void);
uint32_t
spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags);
+uint32_t spi_get_data(void);
+//static void spi_irq_handler(unsigned irq);
+void spi_register_callback(void (*volatile callback)(void));
+
+bool
+spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void));
+
// ----------------------------------------------------------------
// Routines that manipulate the FLASH SPI BUS
// ----------------------------------------------------------------
diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c
index 75bc40859..8d666b76b 100644
--- a/firmware/microblaze/lib/u2_init.c
+++ b/firmware/microblaze/lib/u2_init.c
@@ -45,22 +45,26 @@ get_hw_rev(void)
bool
u2_init(void)
{
+ hal_disable_ints();
hal_io_init();
// init spi, so that we can switch over to the high-speed clock
spi_init();
- // init i2c so we can read our rev
- i2c_init();
- get_hw_rev();
-
// set up the default clocks
clocks_init();
+ hal_uart_init();
+
+ // init i2c so we can read our rev
pic_init(); // progammable interrupt controller
+ i2c_init();
+ hal_enable_ints();
+ get_hw_rev();
+
bp_init(); // buffer pool
- hal_enable_ints();
+
// flash all leds to let us know board is alive
hal_set_leds(0x0, 0x1f);
diff --git a/fpga/usrp2/vrt/vita_rx_framer.v b/fpga/usrp2/vrt/vita_rx_framer.v
index fd82263d0..235817941 100644
--- a/fpga/usrp2/vrt/vita_rx_framer.v
+++ b/fpga/usrp2/vrt/vita_rx_framer.v
@@ -128,7 +128,7 @@ module vita_rx_framer
VITA_ERR_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]};
VITA_ERR_TICS : pkt_fifo_line <= {2'b00,32'd0};
VITA_ERR_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]};
- VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b11,28'd0,flags_fifo_o};
+ VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b10,28'd0,flags_fifo_o};
//VITA_ERR_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer};
default : pkt_fifo_line <= 34'h0_FFFF_FFFF;
diff --git a/host/config/Version.cmake b/host/config/Version.cmake
index a592a4565..9e4b6b306 100644
--- a/host/config/Version.cmake
+++ b/host/config/Version.cmake
@@ -42,7 +42,7 @@ ELSE(${GIT} STREQUAL "GIT-NOTFOUND")
#extract the timestamp from the git log entry
EXECUTE_PROCESS(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- COMMAND ${PYTHON_EXECUTABLE} -c "import re; print re.match('^.*Date:\\s*(\\d*).*$', '''${_git_log}''', re.MULTILINE | re.DOTALL).groups()[0]"
+ COMMAND ${PYTHON_EXECUTABLE} -c "import re; print re.match('^.*Date:\\s*(\\d*).*$', ''' ${_git_log} ''', re.MULTILINE | re.DOTALL).groups()[0]"
OUTPUT_VARIABLE _git_timestamp OUTPUT_STRIP_TRAILING_WHITESPACE
)
diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt
index d0041f71c..b4383f88d 100644
--- a/host/docs/CMakeLists.txt
+++ b/host/docs/CMakeLists.txt
@@ -24,6 +24,7 @@ SET(manual_sources
coding.rst
dboards.rst
general.rst
+ images.rst
usrp2.rst
)
diff --git a/host/docs/images.rst b/host/docs/images.rst
new file mode 100644
index 000000000..ff5c5404e
--- /dev/null
+++ b/host/docs/images.rst
@@ -0,0 +1,104 @@
+========================================================================
+UHD - Firmware and FPGA Image Application Notes
+========================================================================
+
+.. contents:: Table of Contents
+
+------------------------------------------------------------------------
+Images Overview
+------------------------------------------------------------------------
+Every USRP device must be loaded with special firmware and FPGA images.
+The methods of loading images into the device varies among devices:
+
+* **USRP1:** The host code will automatically load the firmware and FPGA at runtime.
+* **USRP2:** The user must manually write the images onto the USRP2 SD card.
+
+------------------------------------------------------------------------
+Pre-built images
+------------------------------------------------------------------------
+
+Pre-built images are available for download.
+See the UHD wiki for the download link.
+
+The pre-built images come in platform-specific installer packages
+and platform-independent archive files:
+
+* **Linux:** DEB or RPM installer
+* **Windows:** not available yet...
+* **Macintosh:** not available yet...
+* **Platform-independent:** ZIP or TAR.GZ archive
+
+^^^^^^^^^^^^^^^^^^
+Linux installers
+^^^^^^^^^^^^^^^^^^
+The Linux-based installers will install the images into /usr/share/uhd/images.
+On a Linux system, the UHD will always search this path for image files.
+
+Commands to install a linux rpm or deb package:
+
+::
+
+ sudo rpm -i <linux-images-installer>.rpm
+
+ -- OR --
+
+ sudo dpkg -i <linux-images-installer>.deb
+
+^^^^^^^^^^^^^^^^^^^^^^
+Archive install
+^^^^^^^^^^^^^^^^^^^^^^
+When installing images from an archive, there are two options:
+
+**Option 1:**
+
+Unpack the archive into the UHD installation prefix.
+The UHD will always search <prefix>/share/uhd/images for image files.
+Where <prefix> was set by the CMAKE_INSTALL_PREFIX at configure-time.
+
+**Option 2:**
+
+Unpack the archive anywhere and set the UHD_IMAGE_PATH environment variable.
+The UHD_IMAGE_PATH may contain a list of directories to search for image files,
+or paths to specific image files.
+
+------------------------------------------------------------------------
+Building images
+------------------------------------------------------------------------
+
+The UHD source repository comes with the source code necessary to build
+both firmware and FPGA images for all supported devices.
+The build commands for a particular image can be found in <uhd-repo-path>/images/Makefile.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Xilinx FPGA builds
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Xilinx ISE 12.x and up is required to build the Xilinx FPGA images.
+The build requires that you have a unix-like environment with make.
+Make sure that xtclsh from the Xilinx ISE bin directory is in your $PATH.
+
+See <uhd-repo-path>/fpga/usrp2/top/*
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Microblaze firmware builds
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The Microblaze GCC compiler from the Xilinx EDK is required to build the Microblaze firmware images.
+The build requires that you have a unix-like environment with autotools and make.
+Make sure that mb-gcc from the Xilinx EDK/microblaze directory is in your $PATH.
+
+See <uhd-repo-path>/firmware/microblaze
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Altera FPGA builds
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Quartus is required to build the Altera FPGA images.
+Pre-built images can also be found in <uhd-repo-path>/fpga/usrp1/rbf
+
+See <uhd-repo-path>/fpga/usrp1/toplevel/*
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+FX2 firmware builds
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The sdcc compiler is required to build the FX2 firmware images.
+The build requires that you have a unix-like environment with autotools and make.
+
+See <uhd-repo-path>/firmware/fx2
diff --git a/host/docs/index.rst b/host/docs/index.rst
index b31a3d0ac..6973ede19 100644
--- a/host/docs/index.rst
+++ b/host/docs/index.rst
@@ -21,6 +21,7 @@ Building the UHD
Application Notes
^^^^^^^^^^^^^^^^^^^^^
* `General App Notes <./general.html>`_
+* `Firmware and FPGA Image Notes <./images.html>`_
* `USRP2 App Notes <./usrp2.html>`_
* `Daughterboard App Notes <./dboards.html>`_
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index bc4ea0e44..3ac326f58 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -5,42 +5,6 @@ UHD - USRP2 Application Notes
.. contents:: Table of Contents
------------------------------------------------------------------------
-Building firmware and FPGA images
-------------------------------------------------------------------------
-
-^^^^^^^^^^^^^^^^^^
-FPGA Image
-^^^^^^^^^^^^^^^^^^
-Xilinx ISE 10.1 and up is required to build the FPGA image for the USRP2.
-The build requires that you have a unix-like environment with make.
-Make sure that xtclsh from the Xilinx ISE bin directory is in your $PATH.
-
-Run the following commands:
-::
-
- cd <uhd-repo-path>/fpga/usrp2/top/u2_rev3
- make -f Makefile.udp bin
-
-*The image file will be ./build/u2_rev3.bin*
-
-^^^^^^^^^^^^^^^^^^
-Firmware Image
-^^^^^^^^^^^^^^^^^^
-The Microblaze GCC compiler from the Xilinx EDK is required to build the firmware.
-The build requires that you have a unix-like environment with autotools and make.
-Make sure that mb-gcc from the Xilinx EDK/microblaze directory is in your $PATH.
-
-Run the following commands:
-::
-
- cd <uhd-repo-path>/firmware/microblaze
- ./boostrap
- ./configure --host=mb
- make
-
-*The image file will be ./usrp2/usrp2_txrx_uhd.bin*
-
-------------------------------------------------------------------------
Load the images onto the SD card
------------------------------------------------------------------------
**Warning!**
diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt
index 76ee24e5f..130956f8a 100644
--- a/host/include/uhd/usrp/CMakeLists.txt
+++ b/host/include/uhd/usrp/CMakeLists.txt
@@ -33,6 +33,8 @@ INSTALL(FILES
dboard_manager.hpp
### utilities ###
+ dsp_utils.hpp
+ misc_utils.hpp
subdev_spec.hpp
tune_helper.hpp
diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp
index fc7ea3052..e776ecc42 100644
--- a/host/include/uhd/usrp/dboard_iface.hpp
+++ b/host/include/uhd/usrp/dboard_iface.hpp
@@ -65,11 +65,34 @@ public:
AUX_ADC_B = 'b'
};
+ //! Special properties that differentiate this daughterboard slot
+ struct special_props_t{
+ /*!
+ * Soft clock divider:
+ * When a motherboard cannot provided a divided dboard clock,
+ * it may provided a "soft" divided clock over an FPGA GPIO.
+ * The implementation must know the type of clock provided.
+ */
+ bool soft_clock_divider;
+
+ /*!
+ * Mangle i2c addresses:
+ * When i2c is shared across multiple daugterboard slots,
+ * the i2c addresses will be mangled on the secondary slot
+ * to avoid conflicts between slots in the i2c address space.
+ * The mangling is daguhterboard specific so the implementation
+ * needs to know whether it should use mangled addresses or not.
+ */
+ bool mangle_i2c_addrs;
+ };
+
/*!
- * Get the motherboard name of the form: usrp1, usrp2...
- * \return string representing the motherboard name
+ * Get special properties information for this dboard slot.
+ * This call helps the dboard code to handle implementation
+ * differences between different motherboards and dboard slots.
+ * \return the special properties struct
*/
- virtual std::string get_mboard_name(void) = 0;
+ virtual special_props_t get_special_props(void) = 0;
/*!
* Write to an aux dac.
diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp
index e5831d4cf..c68f069f0 100644
--- a/host/include/uhd/usrp/dboard_manager.hpp
+++ b/host/include/uhd/usrp/dboard_manager.hpp
@@ -51,7 +51,7 @@ public:
const dboard_id_t &dboard_id,
dboard_ctor_t dboard_ctor,
const std::string &name,
- const prop_names_t &subdev_names = prop_names_t(1, "")
+ const prop_names_t &subdev_names = prop_names_t(1, "0")
);
/*!
diff --git a/host/include/uhd/usrp/dsp_utils.hpp b/host/include/uhd/usrp/dsp_utils.hpp
new file mode 100644
index 000000000..8ec04dd2f
--- /dev/null
+++ b/host/include/uhd/usrp/dsp_utils.hpp
@@ -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/>.
+//
+
+#ifndef INCLUDED_UHD_USRP_DSP_UTILS_HPP
+#define INCLUDED_UHD_USRP_DSP_UTILS_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/usrp/subdev_props.hpp>
+#include <boost/cstdint.hpp>
+
+namespace uhd{ namespace usrp{
+
+namespace dsp_type1{
+
+ /*!
+ * Calculate the rx mux word from properties.
+ * \param subdev_conn the subdev connection type
+ * \return the 32-bit rx mux control word
+ */
+ UHD_API boost::uint32_t calc_rx_mux_word(subdev_conn_t subdev_conn);
+
+ /*!
+ * Calculate the tx mux word from properties.
+ * \param subdev_conn the subdev connection type
+ * \return the 32-bit tx mux control word
+ */
+ UHD_API boost::uint32_t calc_tx_mux_word(subdev_conn_t subdev_conn);
+
+ /*!
+ * Calculate the cordic word from the frequency and clock rate.
+ * The frequency will be set to the actual (possible) frequency.
+ *
+ * \param freq the requested frequency in Hz
+ * \param codec_rate the dsp codec rate in Hz
+ * \return the 32-bit cordic control word
+ */
+ UHD_API boost::uint32_t calc_cordic_word_and_update(
+ double &freq, double codec_rate
+ );
+
+ /*!
+ * Calculate the CIC filter word from the rate.
+ * Check if requested decim/interp rate is:
+ * multiple of 4, enable two halfband filters
+ * multiple of 2, enable one halfband filter
+ * handle remainder in CIC
+ *
+ * \param rate the requested rate in Sps
+ * \return the 32-bit cic filter control word
+ */
+ UHD_API boost::uint32_t calc_cic_filter_word(unsigned rate);
+
+ /*!
+ * Calculate the IQ scale factor word from I and Q components.
+ * \param i the I component of the scalar
+ * \param q the Q component of the scalar
+ * \return the 32-bit scale factor control word
+ */
+ UHD_API boost::uint32_t calc_iq_scale_word(
+ boost::int16_t i, boost::int16_t q
+ );
+
+ /*!
+ * Calculate the IQ scale factor word from the rate.
+ * \param rate the requested rate in Sps
+ * \return the 32-bit scale factor control word
+ */
+ UHD_API boost::uint32_t calc_iq_scale_word(unsigned rate);
+
+ /*!
+ * Calculate the stream command word from the stream command struct.
+ * \param stream_cmd the requested stream command with mode, flags, timestamp
+ * \param num_samps_continuous number of samples to request in continuous mode
+ * \return the 32-bit stream command word
+ */
+ UHD_API boost::uint32_t calc_stream_cmd_word(
+ const stream_cmd_t &stream_cmd, size_t num_samps_continuous
+ );
+
+} //namespace dsp_type1
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_USRP_DSP_UTILS_HPP */
diff --git a/host/include/uhd/usrp/misc_utils.hpp b/host/include/uhd/usrp/misc_utils.hpp
new file mode 100644
index 000000000..2af9f5b40
--- /dev/null
+++ b/host/include/uhd/usrp/misc_utils.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_USRP_MISC_UTILS_HPP
+#define INCLUDED_UHD_USRP_MISC_UTILS_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/wax.hpp>
+#include <uhd/usrp/subdev_spec.hpp>
+#include <uhd/utils/gain_group.hpp>
+
+namespace uhd{ namespace usrp{
+
+ /*!
+ * Different policies for gain group prioritization.
+ */
+ enum gain_group_policy_t{
+ GAIN_GROUP_POLICY_RX = 'R',
+ GAIN_GROUP_POLICY_TX = 'T'
+ };
+
+ /*!
+ * Create a gain group that represents the subdevice and its codec.
+ * \param subdev the object with subdevice properties
+ * \param codec the object with codec properties
+ * \param gain_group_policy the policy to use
+ */
+ UHD_API gain_group::sptr make_gain_group(
+ wax::obj subdev, wax::obj codec,
+ gain_group_policy_t gain_group_policy
+ );
+
+ /*!
+ * Verify the rx subdevice specification.
+ * If the subdev spec if empty, automatically fill it.
+ * \param subdev_spec the subdev spec to verify/fill
+ * \param mboard the motherboard properties object
+ * \throw exception when the subdev spec is invalid
+ */
+ UHD_API void verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard);
+
+ /*!
+ * Verify the tx subdevice specification.
+ * If the subdev spec if empty, automatically fill it.
+ * \param subdev_spec the subdev spec to verify/fill
+ * \param mboard the motherboard properties object
+ * \throw exception when the subdev spec is invalid
+ */
+ UHD_API void verify_tx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard);
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_USRP_MISC_UTILS_HPP */
+
diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp
index 1b5eacfa9..53c571e4e 100644
--- a/host/include/uhd/utils/algorithm.hpp
+++ b/host/include/uhd/utils/algorithm.hpp
@@ -22,6 +22,9 @@
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
+#include <boost/algorithm/string.hpp>
+#include <vector>
+#include <string>
/*! \file algorithm.hpp
* Useful templated functions and classes that I like to pretend are part of stl.
@@ -30,6 +33,24 @@
namespace std{
/*!
+ * Split a string at the separation characters.
+ * \param string the string to split
+ * \param sep the separator characters
+ * \return a range of strings
+ */
+ inline std::vector<std::string> split_string(
+ const std::string &string, const std::string &sep = "\t "
+ ){
+ std::vector<std::string> strings;
+ if (not string.empty()) boost::split(
+ // do not split an empty string:
+ // let me tell you about the time when boost::split segfaulted...
+ strings, string, boost::is_any_of(sep)
+ );
+ return strings;
+ }
+
+ /*!
* A wrapper around std::copy that takes ranges instead of iterators.
*
* Copy the elements of the source range into the destination range.
diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp
index f376d2612..fbca03019 100644
--- a/host/include/uhd/utils/props.hpp
+++ b/host/include/uhd/utils/props.hpp
@@ -21,7 +21,6 @@
#include <uhd/config.hpp>
#include <uhd/wax.hpp>
#include <uhd/utils/exception.hpp>
-#include <boost/tuple/tuple.hpp>
#include <stdexcept>
#include <vector>
#include <string>
@@ -36,8 +35,25 @@ namespace uhd{
* Allows properties to be sub-sectioned by name.
*/
struct UHD_API named_prop_t{
- wax::obj key;
- std::string name;
+ const wax::obj key;
+ const std::string name;
+
+ //! Convert the key to the specified type
+ template<typename T> inline T as(void){
+ return key.as<T>();
+ }
+
+ /*!
+ * Utility function to convert generic key into a named prop.
+ * If the key was already a named prop, the prop will be split.
+ * Otherwise, the key will be the key, and the name will be used.
+ * \param key a reference to the prop object
+ * \param name a reference to the name object
+ * \return a named property struct with key and name
+ */
+ static named_prop_t extract(
+ const wax::obj &key, const std::string &name = ""
+ );
/*!
* Create a new named prop from key and name.
@@ -48,17 +64,6 @@ namespace uhd{
};
/*!
- * Utility function to separate a named property into its components.
- * \param key a reference to the prop object
- * \param name a reference to the name object
- * \return a tuple that can be used with boost::tie
- */
- UHD_API boost::tuple<wax::obj, std::string> extract_named_prop(
- const wax::obj &key,
- const std::string &name = ""
- );
-
- /*!
* Throw when getting a not-implemented or write-only property.
* Throw-site information will be included with this error.
*/
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 48cfe742e..81845de21 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -53,6 +53,17 @@ INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/utils/CMakeLists.txt)
########################################################################
# Append to the list of sources for lib uhd
########################################################################
+FILE(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${PKG_DATA_DIR} LOCAL_PKG_DATA_DIR)
+STRING(REPLACE "\\" "\\\\" LOCAL_PKG_DATA_DIR ${LOCAL_PKG_DATA_DIR})
+MESSAGE(STATUS "Local package data directory: ${LOCAL_PKG_DATA_DIR}")
+
+IF(UNIX)
+ #on unix systems, installers will use this directory for the package data
+ FILE(TO_NATIVE_PATH /usr/${PKG_DATA_DIR} INSTALLER_PKG_DATA_DIR)
+ STRING(REPLACE "\\" "\\\\" INSTALLER_PKG_DATA_DIR ${INSTALLER_PKG_DATA_DIR})
+ MESSAGE(STATUS "Installer package data directory: ${INSTALLER_PKG_DATA_DIR}")
+ENDIF(UNIX)
+
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/constants.hpp.in
${CMAKE_CURRENT_BINARY_DIR}/constants.hpp
diff --git a/host/lib/constants.hpp.in b/host/lib/constants.hpp.in
index aa51e558c..4aedb6d4a 100644
--- a/host/lib/constants.hpp.in
+++ b/host/lib/constants.hpp.in
@@ -18,12 +18,9 @@
#ifndef INCLUDED_LIBUHD_CONSTANTS_HPP
#define INCLUDED_LIBUHD_CONSTANTS_HPP
-#include <uhd/config.hpp>
-#include <string>
-
//these should be pre-processor macros to avoid static initialization issues
#define UHD_VERSION_STRING "@CPACK_PACKAGE_VERSION@"
-#define UHD_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
-#define UHD_PKG_DATA_DIR "@PKG_DATA_DIR@"
+#define LOCAL_PKG_DATA_DIR "@LOCAL_PKG_DATA_DIR@"
+#define INSTALLER_PKG_DATA_DIR "@INSTALLER_PKG_DATA_DIR@"
#endif /* INCLUDED_LIBUHD_CONSTANTS_HPP */
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index 5c0fb1f42..f957cd83f 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -27,7 +27,6 @@
#include <uhd/types/otw_type.hpp>
#include <uhd/types/io_type.hpp>
#include <uhd/types/serial.hpp>
-#include <boost/algorithm/string.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
@@ -181,15 +180,10 @@ static std::string trim(const std::string &in){
}
device_addr_t::device_addr_t(const std::string &args){
- //split the args at the semi-colons
- std::vector<std::string> pairs;
- boost::split(pairs, args, boost::is_any_of(arg_delim));
- BOOST_FOREACH(const std::string &pair, pairs){
+ BOOST_FOREACH(const std::string &pair, std::split_string(args, arg_delim)){
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));
+ std::vector<std::string> key_val = std::split_string(pair, pair_delim);
if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args);
(*this)[trim(key_val.front())] = trim(key_val.back());
}
@@ -238,13 +232,12 @@ mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
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++){
+ size_t i = 0;
+ BOOST_FOREACH(const std::string &hex_str, std::split_string(mac_addr_str, ":")){
int hex_num;
- std::istringstream iss(hex_strs[i]);
+ std::istringstream iss(hex_str);
iss >> std::hex >> hex_num;
- bytes[i] = boost::uint8_t(hex_num);
+ bytes[i++] = boost::uint8_t(hex_num);
}
}
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index d951ab412..2b408e479 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -22,10 +22,9 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/usrp/dboard_eeprom.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index 9180828d8..f8236d598 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -95,8 +95,7 @@ basic_rx::~basic_rx(void){
}
void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -161,8 +160,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
}
void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -194,8 +192,7 @@ basic_tx::~basic_tx(void){
}
void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -252,8 +249,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
}
void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp
index 03e6b6255..06cf91d3b 100644
--- a/host/lib/usrp/dboard/db_dbsrx.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx.cpp
@@ -61,7 +61,7 @@ static const uhd::dict<std::string, gain_range_t> dbsrx_gain_ranges = map_list_o
**********************************************************************/
class dbsrx : public rx_dboard_base{
public:
- dbsrx(ctor_args_t args, boost::uint8_t max2118_addr);
+ dbsrx(ctor_args_t args);
~dbsrx(void);
void rx_get(const wax::obj &key, wax::obj &val);
@@ -73,7 +73,9 @@ private:
uhd::dict<std::string, float> _gains;
max2118_write_regs_t _max2118_write_regs;
max2118_read_regs_t _max2118_read_regs;
- boost::uint8_t _max2118_addr; //0x67 or 0x65 depending on which side
+ boost::uint8_t _max2118_addr(void){
+ return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x65 : 0x67;
+ };
void set_lo_freq(double target_freq);
void set_gain(float gain, const std::string &name);
@@ -102,7 +104,7 @@ private:
//send the data
this->get_iface()->write_i2c(
- _max2118_addr, regs_vector
+ _max2118_addr(), regs_vector
);
}
}
@@ -120,7 +122,7 @@ private:
//read from i2c
regs_vector = this->get_iface()->read_i2c(
- _max2118_addr, num_bytes
+ _max2118_addr(), num_bytes
);
for(boost::uint8_t i=0; i < num_bytes; i++){
@@ -156,10 +158,8 @@ private:
/***********************************************************************
* Register the DBSRX dboard
**********************************************************************/
-// FIXME 0x67 is the default i2c address on USRP2
-// need to handle which side for USRP1 with different address
static dboard_base::sptr make_dbsrx(dboard_base::ctor_args_t args){
- return dboard_base::sptr(new dbsrx(args, 0x67));
+ return dboard_base::sptr(new dbsrx(args));
}
//dbid for USRP2 version
@@ -177,27 +177,27 @@ UHD_STATIC_BLOCK(reg_dbsrx_on_usrp1_dboard){
/***********************************************************************
* Structors
**********************************************************************/
-dbsrx::dbsrx(ctor_args_t args, boost::uint8_t max2118_addr) : rx_dboard_base(args){
+dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){
//warn user about incorrect DBID on USRP1, requires R193 populated
- if (this->get_iface()->get_mboard_name() == "usrp1" and this->get_rx_id() == 0x000D)
+ if (this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x000D)
uhd::print_warning(
str(boost::format(
"DBSRX: incorrect dbid\n"
- "%s expects dbid 0x0002 and R193\n"
+ "Expected dbid 0x0002 and R193\n"
"found dbid == %d\n"
"Please see the daughterboard app notes"
- ) % (this->get_iface()->get_mboard_name()) % (this->get_rx_id().to_pp_string()))
+ ) % this->get_rx_id().to_pp_string())
);
//warn user about incorrect DBID on non-USRP1, requires R194 populated
- if (this->get_iface()->get_mboard_name() != "usrp1" and this->get_rx_id() == 0x0002)
+ if (not this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x0002)
uhd::print_warning(
str(boost::format(
"DBSRX: incorrect dbid\n"
- "%s expects dbid 0x000D and R194\n"
+ "Expected dbid 0x000D and R194\n"
"found dbid == %d\n"
"Please see the daughterboard app notes"
- ) % (this->get_iface()->get_mboard_name()) % (this->get_rx_id().to_pp_string()))
+ ) % this->get_rx_id().to_pp_string())
);
//enable only the clocks we need
@@ -207,9 +207,6 @@ dbsrx::dbsrx(ctor_args_t args, boost::uint8_t max2118_addr) : rx_dboard_base(arg
this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs
- //set the i2c address for the max2118
- _max2118_addr = max2118_addr;
-
//send initial register settings
this->send_reg(0x0, 0x5);
@@ -503,8 +500,7 @@ void dbsrx::set_bandwidth(float bandwidth){
* RX Get and Set
**********************************************************************/
void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -517,13 +513,13 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- assert_has(_gains.keys(), name, "dbsrx gain name");
- val = _gains[name];
+ assert_has(_gains.keys(), key.name, "dbsrx gain name");
+ val = _gains[key.name];
return;
case SUBDEV_PROP_GAIN_RANGE:
- assert_has(dbsrx_gain_ranges.keys(), name, "dbsrx gain name");
- val = dbsrx_gain_ranges[name];
+ assert_has(dbsrx_gain_ranges.keys(), key.name, "dbsrx gain name");
+ val = dbsrx_gain_ranges[key.name];
return;
case SUBDEV_PROP_GAIN_NAMES:
@@ -546,19 +542,6 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){
val = dbsrx_antennas;
return;
-/*
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
- return;
-
- case SUBDEV_PROP_SPECTRUM_INVERTED:
- val = false;
- return;
-*/
case SUBDEV_PROP_CONNECTION:
val = SUBDEV_CONN_COMPLEX_IQ;
return;
@@ -586,8 +569,7 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){
}
void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -597,7 +579,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_gain(val.as<float>(), name);
+ this->set_gain(val.as<float>(), key.name);
return;
case SUBDEV_PROP_BANDWIDTH:
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index b6b44199a..c3ab96e59 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -398,8 +398,7 @@ double rfx_xcvr::set_lo_freq(
* RX Get and Set
**********************************************************************/
void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -412,13 +411,13 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- assert_has(_rx_gains.keys(), name, "rfx rx gain name");
- val = _rx_gains[name];
+ assert_has(_rx_gains.keys(), key.name, "rfx rx gain name");
+ val = _rx_gains[key.name];
return;
case SUBDEV_PROP_GAIN_RANGE:
- assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name");
- val = _rx_gain_ranges[name];
+ assert_has(_rx_gain_ranges.keys(), key.name, "rfx rx gain name");
+ val = _rx_gain_ranges[key.name];
return;
case SUBDEV_PROP_GAIN_NAMES:
@@ -458,8 +457,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
}
void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -469,7 +467,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_rx_gain(val.as<float>(), name);
+ this->set_rx_gain(val.as<float>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
@@ -484,8 +482,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
* TX Get and Set
**********************************************************************/
void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -499,7 +496,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
case SUBDEV_PROP_GAIN:
case SUBDEV_PROP_GAIN_RANGE:
- assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name");
+ assert_has(rfx_tx_gain_ranges.keys(), key.name, "rfx tx gain name");
//no controllable tx gains, will not get here
return;
@@ -540,8 +537,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
}
void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -551,7 +547,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_tx_gain(val.as<float>(), name);
+ this->set_tx_gain(val.as<float>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp
index 9dd9b550b..f6f4f4a61 100644
--- a/host/lib/usrp/dboard/db_unknown.cpp
+++ b/host/lib/usrp/dboard/db_unknown.cpp
@@ -78,8 +78,7 @@ unknown_rx::~unknown_rx(void){
}
void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -136,8 +135,7 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
}
void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -169,8 +167,7 @@ unknown_tx::~unknown_tx(void){
}
void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -227,8 +224,7 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
}
void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 3038ce30b..ccd897674 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -467,8 +467,7 @@ double wbx_xcvr::set_lo_freq(
* RX Get and Set
**********************************************************************/
void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -481,13 +480,13 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- assert_has(_rx_gains.keys(), name, "wbx rx gain name");
- val = _rx_gains[name];
+ assert_has(_rx_gains.keys(), key.name, "wbx rx gain name");
+ val = _rx_gains[key.name];
return;
case SUBDEV_PROP_GAIN_RANGE:
- assert_has(wbx_rx_gain_ranges.keys(), name, "wbx rx gain name");
- val = wbx_rx_gain_ranges[name];
+ assert_has(wbx_rx_gain_ranges.keys(), key.name, "wbx rx gain name");
+ val = wbx_rx_gain_ranges[key.name];
return;
case SUBDEV_PROP_GAIN_NAMES:
@@ -527,8 +526,7 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
}
void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -538,7 +536,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_rx_gain(val.as<float>(), name);
+ this->set_rx_gain(val.as<float>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
@@ -553,8 +551,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
* TX Get and Set
**********************************************************************/
void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -567,13 +564,13 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- assert_has(_tx_gains.keys(), name, "wbx tx gain name");
- val = _tx_gains[name];
+ assert_has(_tx_gains.keys(), key.name, "wbx tx gain name");
+ val = _tx_gains[key.name];
return;
case SUBDEV_PROP_GAIN_RANGE:
- assert_has(wbx_tx_gain_ranges.keys(), name, "wbx tx gain name");
- val = wbx_tx_gain_ranges[name];
+ assert_has(wbx_tx_gain_ranges.keys(), key.name, "wbx tx gain name");
+ val = wbx_tx_gain_ranges[key.name];
return;
case SUBDEV_PROP_GAIN_NAMES:
@@ -613,8 +610,7 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
}
void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -624,7 +620,7 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_tx_gain(val.as<float>(), name);
+ this->set_tx_gain(val.as<float>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index 2c94bcd2d..798ff74a3 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -438,8 +438,7 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){
* RX Get and Set
**********************************************************************/
void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -452,13 +451,13 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- assert_has(_rx_gains.keys(), name, "xcvr rx gain name");
- val = _rx_gains[name];
+ assert_has(_rx_gains.keys(), key.name, "xcvr rx gain name");
+ val = _rx_gains[key.name];
return;
case SUBDEV_PROP_GAIN_RANGE:
- assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name");
- val = xcvr_rx_gain_ranges[name];
+ assert_has(xcvr_rx_gain_ranges.keys(), key.name, "xcvr rx gain name");
+ val = xcvr_rx_gain_ranges[key.name];
return;
case SUBDEV_PROP_GAIN_NAMES:
@@ -502,8 +501,7 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
}
void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -513,7 +511,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_rx_gain(val.as<float>(), name);
+ this->set_rx_gain(val.as<float>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
@@ -528,8 +526,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){
* TX Get and Set
**********************************************************************/
void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -542,13 +539,13 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- assert_has(_tx_gains.keys(), name, "xcvr tx gain name");
- val = _tx_gains[name];
+ assert_has(_tx_gains.keys(), key.name, "xcvr tx gain name");
+ val = _tx_gains[key.name];
return;
case SUBDEV_PROP_GAIN_RANGE:
- assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name");
- val = xcvr_tx_gain_ranges[name];
+ assert_has(xcvr_tx_gain_ranges.keys(), key.name, "xcvr tx gain name");
+ val = xcvr_tx_gain_ranges[key.name];
return;
case SUBDEV_PROP_GAIN_NAMES:
@@ -588,8 +585,7 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
}
void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
@@ -599,7 +595,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_tx_gain(val.as<float>(), name);
+ this->set_tx_gain(val.as<float>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp
new file mode 100644
index 000000000..fe1313af1
--- /dev/null
+++ b/host/lib/usrp/dsp_utils.cpp
@@ -0,0 +1,124 @@
+//
+// 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/usrp/dsp_utils.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/utils/assert.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <cmath>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+template <class T> T ceil_log2(T num){
+ return std::ceil(std::log(num)/std::log(T(2)));
+}
+
+boost::uint32_t dsp_type1::calc_rx_mux_word(subdev_conn_t subdev_conn){
+ switch(subdev_conn){
+ case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 2) | (0x0 << 0); //DDC0Q=ADC1, DDC0I=ADC0
+ case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 2) | (0x1 << 0); //DDC0Q=ADC0, DDC0I=ADC1
+ case SUBDEV_CONN_REAL_I: return (0x3 << 2) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0
+ case SUBDEV_CONN_REAL_Q: return (0x1 << 2) | (0x3 << 0); //DDC0Q=ADC1, DDC0I=ZERO
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+
+boost::uint32_t dsp_type1::calc_tx_mux_word(subdev_conn_t subdev_conn){
+ switch(subdev_conn){
+ case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC1=DUC0Q, DAC0=DUC0I
+ case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC1=DUC0I, DAC0=DUC0Q
+ case SUBDEV_CONN_REAL_I: return (0xf << 4) | (0x0 << 0); //DAC1=ZERO, DAC0=DUC0I
+ case SUBDEV_CONN_REAL_Q: return (0x0 << 4) | (0xf << 0); //DAC1=DUC0I, DAC0=ZERO
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+
+boost::uint32_t dsp_type1::calc_cordic_word_and_update(
+ double &freq,
+ double codec_rate
+){
+ UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0);
+ static const double scale_factor = std::pow(2.0, 32);
+
+ //calculate the freq register word (signed)
+ boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / codec_rate) * scale_factor));
+
+ //update the actual frequency
+ freq = (double(freq_word) / scale_factor) * codec_rate;
+
+ return boost::uint32_t(freq_word);
+}
+
+boost::uint32_t dsp_type1::calc_cic_filter_word(unsigned rate){
+ int hb0 = 0, hb1 = 0;
+ if (not (rate & 0x1)){
+ hb0 = 1;
+ rate /= 2;
+ }
+ if (not (rate & 0x1)){
+ hb1 = 1;
+ rate /= 2;
+ }
+ return (hb1 << 9) | (hb0 << 8) | (rate & 0xff);
+}
+
+boost::uint32_t dsp_type1::calc_iq_scale_word(
+ boost::int16_t i, boost::int16_t q
+){
+ return (boost::uint32_t(i) << 16) | (boost::uint32_t(q) << 0);
+}
+
+boost::uint32_t dsp_type1::calc_iq_scale_word(unsigned rate){
+ // Calculate CIC interpolation (i.e., without halfband interpolators)
+ unsigned tmp_rate = calc_cic_filter_word(rate) & 0xff;
+
+ // Calculate closest multiplier constant to reverse gain absent scale multipliers
+ double rate_cubed = std::pow(double(tmp_rate), 3);
+ boost::int16_t scale = boost::math::iround((4096*std::pow(2, ceil_log2(rate_cubed)))/(1.65*rate_cubed));
+ return calc_iq_scale_word(scale, scale);
+}
+
+boost::uint32_t dsp_type1::calc_stream_cmd_word(
+ const stream_cmd_t &stream_cmd, size_t num_samps_continuous
+){
+ UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff);
+
+ //setup the mode to instruction flags
+ typedef boost::tuple<bool, bool, bool> inst_t;
+ static const uhd::dict<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst = boost::assign::map_list_of
+ //reload, chain, samps
+ (stream_cmd_t::STREAM_MODE_START_CONTINUOUS, inst_t(true, true, false))
+ (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS, inst_t(false, false, false))
+ (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true))
+ (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true, true))
+ ;
+
+ //setup the instruction flag values
+ bool inst_reload, inst_chain, inst_samps;
+ boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode];
+
+ //calculate the word from flags and length
+ boost::uint32_t word = 0;
+ word |= boost::uint32_t((stream_cmd.stream_now)? 1 : 0) << 31;
+ word |= boost::uint32_t((inst_chain)? 1 : 0) << 30;
+ word |= boost::uint32_t((inst_reload)? 1 : 0) << 29;
+ word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? num_samps_continuous : 1);
+ return word;
+}
diff --git a/host/lib/usrp/dsp_utils.hpp b/host/lib/usrp/dsp_utils.hpp
deleted file mode 100644
index ebed12c41..000000000
--- a/host/lib/usrp/dsp_utils.hpp
+++ /dev/null
@@ -1,187 +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_LIBUHD_USRP_DSP_UTILS_HPP
-#define INCLUDED_LIBUHD_USRP_DSP_UTILS_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/types/dict.hpp>
-#include <uhd/utils/assert.hpp>
-#include <uhd/types/stream_cmd.hpp>
-#include <uhd/usrp/subdev_props.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/assign/list_of.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <boost/math/special_functions/round.hpp>
-
-namespace uhd{ namespace usrp{
-
-namespace dsp_type1{
-
- template <class T> T ceil_log2(T num){
- return std::ceil(std::log(num)/std::log(T(2)));
- }
-
- /*!
- * Calculate the rx mux word from properties.
- * \param subdev_conn the subdev connection type
- * \param the 32-bit rx mux control word
- */
- static inline boost::uint32_t calc_rx_mux_word(
- subdev_conn_t subdev_conn
- ){
- switch(subdev_conn){
- case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 2) | (0x0 << 0); //DDC0Q=ADC1, DDC0I=ADC0
- case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 2) | (0x1 << 0); //DDC0Q=ADC0, DDC0I=ADC1
- case SUBDEV_CONN_REAL_I: return (0x3 << 2) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0
- case SUBDEV_CONN_REAL_Q: return (0x1 << 2) | (0x3 << 0); //DDC0Q=ADC1, DDC0I=ZERO
- default: UHD_THROW_INVALID_CODE_PATH();
- }
- }
-
- /*!
- * Calculate the tx mux word from properties.
- * \param subdev_conn the subdev connection type
- * \param the 32-bit tx mux control word
- */
- static inline boost::uint32_t calc_tx_mux_word(
- subdev_conn_t subdev_conn
- ){
- switch(subdev_conn){
- case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC1=DUC0Q, DAC0=DUC0I
- case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC1=DUC0I, DAC0=DUC0Q
- case SUBDEV_CONN_REAL_I: return (0xf << 4) | (0x0 << 0); //DAC1=ZERO, DAC0=DUC0I
- case SUBDEV_CONN_REAL_Q: return (0x0 << 4) | (0xf << 0); //DAC1=DUC0I, DAC0=ZERO
- default: UHD_THROW_INVALID_CODE_PATH();
- }
- }
-
- /*!
- * Calculate the cordic word from the frequency and clock rate.
- * The frequency will be set to the actual (possible) frequency.
- *
- * \param freq the requested frequency in Hz
- * \param codec_rate the dsp codec rate in Hz
- * \param the 32-bit cordic control word
- */
- static inline boost::uint32_t calc_cordic_word_and_update(
- double &freq,
- double codec_rate
- ){
- UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0);
- static const double scale_factor = std::pow(2.0, 32);
-
- //calculate the freq register word (signed)
- boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / codec_rate) * scale_factor));
-
- //update the actual frequency
- freq = (double(freq_word) / scale_factor) * codec_rate;
-
- return boost::uint32_t(freq_word);
- }
-
- /*!
- * Calculate the CIC filter word from the rate.
- * Check if requested decim/interp rate is:
- * multiple of 4, enable two halfband filters
- * multiple of 2, enable one halfband filter
- * handle remainder in CIC
- *
- * \param rate the requested rate in Sps
- * \return the 32-bit cic filter control word
- */
- template <typename dsp_rate_type>
- static inline boost::uint32_t calc_cic_filter_word(dsp_rate_type rate){
- int hb0 = 0, hb1 = 0;
- if (not (rate & 0x1)){
- hb0 = 1;
- rate /= 2;
- }
- if (not (rate & 0x1)){
- hb1 = 1;
- rate /= 2;
- }
- return (hb1 << 9) | (hb0 << 8) | (rate & 0xff);
- }
-
- /*!
- * Calculate the IQ scale factor word from I and Q components.
- * \param i the I component of the scalar
- * \param q the Q component of the scalar
- * \return the 32-bit scale factor control word
- */
- static inline boost::uint32_t calc_iq_scale_word(
- boost::int16_t i, boost::int16_t q
- ){
- return (boost::uint32_t(i) << 16) | (boost::uint32_t(q) << 0);
- }
-
- /*!
- * Calculate the IQ scale factor word from the rate.
- * \param rate the requested rate in Sps
- * \return the 32-bit scale factor control word
- */
- template <typename dsp_rate_type>
- static inline boost::uint32_t calc_iq_scale_word(dsp_rate_type rate){
- // Calculate CIC interpolation (i.e., without halfband interpolators)
- dsp_rate_type tmp_rate = calc_cic_filter_word(rate) & 0xff;
-
- // Calculate closest multiplier constant to reverse gain absent scale multipliers
- double rate_cubed = std::pow(double(tmp_rate), 3);
- boost::int16_t scale = boost::math::iround((4096*std::pow(2, ceil_log2(rate_cubed)))/(1.65*rate_cubed));
- return calc_iq_scale_word(scale, scale);
- }
-
- /*!
- * Calculate the stream command word from the stream command struct.
- * \param stream_cmd the requested stream command with mode, flags, timestamp
- * \param num_samps_continuous number of samples to request in continuous mode
- * \return the 32-bit stream command word
- */
- static inline boost::uint32_t calc_stream_cmd_word(
- const stream_cmd_t &stream_cmd, size_t num_samps_continuous
- ){
- UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff);
-
- //setup the mode to instruction flags
- typedef boost::tuple<bool, bool, bool> inst_t;
- static const uhd::dict<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst = boost::assign::map_list_of
- //reload, chain, samps
- (stream_cmd_t::STREAM_MODE_START_CONTINUOUS, inst_t(true, true, false))
- (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS, inst_t(false, false, false))
- (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true))
- (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true, true))
- ;
-
- //setup the instruction flag values
- bool inst_reload, inst_chain, inst_samps;
- boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode];
-
- //calculate the word from flags and length
- boost::uint32_t word = 0;
- word |= boost::uint32_t((stream_cmd.stream_now)? 1 : 0) << 31;
- word |= boost::uint32_t((inst_chain)? 1 : 0) << 30;
- word |= boost::uint32_t((inst_reload)? 1 : 0) << 29;
- word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? num_samps_continuous : 1);
- return word;
- }
-
-} //namespace dsp_type1
-
-}} //namespace
-
-#endif /* INCLUDED_LIBUHD_USRP_DSP_UTILS_HPP */
diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp
index 0aa03a6cc..46094ba32 100644
--- a/host/lib/usrp/misc_utils.cpp
+++ b/host/lib/usrp/misc_utils.cpp
@@ -15,9 +15,13 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include "misc_utils.hpp"
+#include <uhd/usrp/misc_utils.hpp>
+#include <uhd/utils/assert.hpp>
#include <uhd/utils/gain_group.hpp>
+#include <uhd/usrp/dboard_id.hpp>
#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/usrp/mboard_props.hpp>
+#include <uhd/usrp/dboard_props.hpp>
#include <uhd/usrp/codec_props.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
@@ -25,9 +29,6 @@
using namespace uhd;
using namespace uhd::usrp;
-static const size_t subdev_gain_priority = 1; //higher, closer to the antenna
-static const size_t codec_gain_priority = 0;
-
/***********************************************************************
* codec gain group helper functions:
* do this so we dont have to bind a templated function
@@ -76,7 +77,15 @@ static void set_subdev_gain(wax::obj subdev, const std::string &name, float gain
/***********************************************************************
* gain group factory function for usrp
**********************************************************************/
-gain_group::sptr usrp::make_gain_group(wax::obj subdev, wax::obj codec){
+gain_group::sptr usrp::make_gain_group(
+ wax::obj subdev, wax::obj codec,
+ gain_group_policy_t gain_group_policy
+){
+ const size_t subdev_gain_priority = 1;
+ const size_t codec_gain_priority = (gain_group_policy == GAIN_GROUP_POLICY_RX)?
+ (subdev_gain_priority - 1): //RX policy, codec gains fill last (lower priority)
+ (subdev_gain_priority + 1); //TX policy, codec gains fill first (higher priority)
+
gain_group::sptr gg = gain_group::make();
gain_fcns_t fcns;
//add all the subdev gains first (antenna to dsp order)
@@ -112,3 +121,69 @@ gain_group::sptr usrp::make_gain_group(wax::obj subdev, wax::obj codec){
}
return gg;
}
+
+/***********************************************************************
+ * verify subdev specs
+ **********************************************************************/
+static void verify_xx_subdev_spec(
+ mboard_prop_t dboard_names_prop,
+ mboard_prop_t dboard_prop,
+ subdev_spec_t &subdev_spec,
+ wax::obj mboard,
+ std::string xx_type
+){
+ prop_names_t dboard_names = mboard[dboard_names_prop].as<prop_names_t>();
+ UHD_ASSERT_THROW(dboard_names.size() > 0); //well i hope there is a dboard
+
+ //the subdevice specification is empty: handle automatic
+ if (subdev_spec.empty()){
+ BOOST_FOREACH(const std::string &db_name, dboard_names){
+ wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)];
+
+ //if the dboard slot is populated, take the first subdevice
+ if (dboard[DBOARD_PROP_DBOARD_ID].as<dboard_id_t>() != dboard_id_t::none()){
+ std::string sd_name = dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>().front();
+ subdev_spec.push_back(subdev_spec_pair_t(db_name, sd_name));
+ break;
+ }
+ }
+
+ //didnt find any populated dboards: add the first subdevice
+ if (subdev_spec.empty()){
+ std::string db_name = dboard_names.front();
+ wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)];
+ std::string sd_name = dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>().front();
+ subdev_spec.push_back(subdev_spec_pair_t(db_name, sd_name));
+ }
+ }
+
+ //sanity check that the dboard/subdevice names exist for this mboard
+ BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){
+ //empty db name means select dboard automatically
+ if (pair.db_name.empty()){
+ if (dboard_names.size() != 1) throw std::runtime_error(
+ "A daughterboard name must be provided for multi-slot boards: " + subdev_spec.to_string()
+ );
+ pair.db_name == dboard_names.front();
+ }
+ uhd::assert_has(dboard_names, pair.db_name, xx_type + " dboard name");
+ wax::obj dboard = mboard[named_prop_t(dboard_prop, pair.db_name)];
+ uhd::assert_has(dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>(), pair.sd_name, xx_type + " subdev name");
+ }
+}
+
+void usrp::verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){
+ return verify_xx_subdev_spec(
+ MBOARD_PROP_RX_DBOARD_NAMES,
+ MBOARD_PROP_RX_DBOARD,
+ subdev_spec, mboard, "rx"
+ );
+}
+
+void usrp::verify_tx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){
+ return verify_xx_subdev_spec(
+ MBOARD_PROP_TX_DBOARD_NAMES,
+ MBOARD_PROP_TX_DBOARD,
+ subdev_spec, mboard, "tx"
+ );
+}
diff --git a/host/lib/usrp/misc_utils.hpp b/host/lib/usrp/misc_utils.hpp
deleted file mode 100644
index 7fe3c899d..000000000
--- a/host/lib/usrp/misc_utils.hpp
+++ /dev/null
@@ -1,35 +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_LIBUHD_USRP_MISC_UTILS_HPP
-#define INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/wax.hpp>
-#include <uhd/utils/gain_group.hpp>
-
-namespace uhd{ namespace usrp{
-
- /*!
- * Create a gain group that represents the subdevice and its codec.
- */
- gain_group::sptr make_gain_group(wax::obj subdev, wax::obj codec);
-
-}} //namespace
-
-#endif /* INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP */
-
diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp
index 0f00e2f74..7a3e72867 100644
--- a/host/lib/usrp/subdev_spec.cpp
+++ b/host/lib/usrp/subdev_spec.cpp
@@ -16,7 +16,7 @@
//
#include <uhd/usrp/subdev_spec.hpp>
-#include <boost/algorithm/string.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <stdexcept>
@@ -35,12 +35,9 @@ subdev_spec_pair_t::subdev_spec_pair_t(
}
subdev_spec_t::subdev_spec_t(const std::string &markup){
- std::vector<std::string> pairs;
- boost::split(pairs, markup, boost::is_any_of("\t "));
- BOOST_FOREACH(const std::string &pair, pairs){
+ BOOST_FOREACH(const std::string &pair, std::split_string(markup)){
if (pair == "") continue;
- std::vector<std::string> db_sd;
- boost::split(db_sd, pair, boost::is_any_of(":"));
+ std::vector<std::string> db_sd = std::split_string(pair, ":");
switch(db_sd.size()){
case 1: this->push_back(subdev_spec_pair_t("", db_sd.front())); break;
case 2: this->push_back(subdev_spec_pair_t(db_sd.front(), db_sd.back())); break;
@@ -56,13 +53,9 @@ std::string subdev_spec_t::to_pp_string(void) const{
size_t count = 0;
ss << "Subdevice Specification:" << std::endl;
BOOST_FOREACH(const subdev_spec_pair_t &pair, *this){
- std::string db_name = pair.db_name;
- if (db_name == "") db_name = "0";
- std::string sd_name = pair.sd_name;
- if (sd_name == "") sd_name = "0";
ss << boost::format(
" Channel %d: Daughterboard %s, Subdevice %s"
- ) % (count++) % db_name % sd_name << std::endl;
+ ) % (count++) % pair.db_name % pair.sd_name << std::endl;
}
return ss.str();
}
diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp
index 969b5b4b9..f7f9ce2d5 100644
--- a/host/lib/usrp/usrp2/codec_impl.cpp
+++ b/host/lib/usrp/usrp2/codec_impl.cpp
@@ -53,9 +53,7 @@ void usrp2_mboard_impl::codec_init(void){
/***********************************************************************
* RX Codec Properties
**********************************************************************/
-void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+void usrp2_mboard_impl::rx_codec_get(const wax::obj &key, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<codec_prop_t>()){
@@ -136,9 +134,7 @@ void usrp2_mboard_impl::rx_codec_set_gain(float gain, const std::string &name){
/***********************************************************************
* TX Codec Properties
**********************************************************************/
-void usrp2_mboard_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+void usrp2_mboard_impl::tx_codec_get(const wax::obj &key, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<codec_prop_t>()){
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index be45c2c9e..cff13292b 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -37,7 +37,12 @@ public:
usrp2_dboard_iface(usrp2_iface::sptr iface, usrp2_clock_ctrl::sptr clock_ctrl);
~usrp2_dboard_iface(void);
- std::string get_mboard_name(void){return "usrp2";}
+ special_props_t get_special_props(void){
+ special_props_t props;
+ props.soft_clock_divider = false;
+ props.mangle_i2c_addrs = false;
+ return props;
+ }
void write_aux_dac(unit_t, aux_dac_t, float);
float read_aux_adc(unit_t, aux_adc_t);
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 075f22388..a462b93c2 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -17,8 +17,8 @@
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
-#include "../dsp_utils.hpp"
-#include "../misc_utils.hpp"
+#include <uhd/usrp/misc_utils.hpp>
+#include <uhd/usrp/dsp_utils.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dboard_props.hpp>
#include <uhd/utils/assert.hpp>
@@ -59,8 +59,7 @@ void usrp2_mboard_impl::dboard_init(void){
* RX DBoard Properties
**********************************************************************/
void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<dboard_prop_t>()){
@@ -69,7 +68,7 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
return;
case DBOARD_PROP_SUBDEV:
- val = _dboard_manager->get_rx_subdev(name);
+ val = _dboard_manager->get_rx_subdev(key.name);
return;
case DBOARD_PROP_SUBDEV_NAMES:
@@ -90,7 +89,9 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
case DBOARD_PROP_GAIN_GROUP:
val = make_gain_group(
- _dboard_manager->get_rx_subdev(name), _rx_codec_proxy->get_link()
+ _dboard_manager->get_rx_subdev(key.name),
+ _rx_codec_proxy->get_link(),
+ GAIN_GROUP_POLICY_RX
);
return;
@@ -114,8 +115,7 @@ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
* TX DBoard Properties
**********************************************************************/
void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<dboard_prop_t>()){
@@ -124,7 +124,7 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
return;
case DBOARD_PROP_SUBDEV:
- val = _dboard_manager->get_tx_subdev(name);
+ val = _dboard_manager->get_tx_subdev(key.name);
return;
case DBOARD_PROP_SUBDEV_NAMES:
@@ -145,7 +145,9 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
case DBOARD_PROP_GAIN_GROUP:
val = make_gain_group(
- _dboard_manager->get_tx_subdev(name), _tx_codec_proxy->get_link()
+ _dboard_manager->get_tx_subdev(key.name),
+ _tx_codec_proxy->get_link(),
+ GAIN_GROUP_POLICY_TX
);
return;
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 936b1f7a2..97bda51fc 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -17,9 +17,10 @@
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
-#include "../dsp_utils.hpp"
+#include <uhd/usrp/dsp_utils.hpp>
#include <uhd/usrp/dsp_props.hpp>
#include <boost/bind.hpp>
+#include <cmath>
using namespace uhd;
using namespace uhd::usrp;
@@ -30,10 +31,10 @@ static const size_t default_interp = 16;
/***********************************************************************
* DDC Helper Methods
**********************************************************************/
-template <class rate_t> static rate_t
-pick_closest_rate(double exact_rate, const std::vector<rate_t> &rates){
- rate_t closest_match = rates.at(0);
- BOOST_FOREACH(rate_t possible_rate, rates){
+template <typename rate_type>
+static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_type> &rates){
+ unsigned closest_match = rates.front();
+ BOOST_FOREACH(rate_type possible_rate, rates){
if(std::abs(exact_rate - possible_rate) < std::abs(exact_rate - closest_match))
closest_match = possible_rate;
}
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index fc1e6f2a7..4d3b62d6b 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -34,7 +34,7 @@ extern "C" {
//fpga and firmware compatibility numbers
#define USRP2_FPGA_COMPAT_NUM 1
-#define USRP2_FW_COMPAT_NUM 5
+#define USRP2_FW_COMPAT_NUM 6
//used to differentiate control packets over data port
#define USRP2_INVALID_VRT_HEADER 0
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 6c4234641..fc1cc3a9a 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -17,13 +17,15 @@
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
-#include "../dsp_utils.hpp"
+#include <uhd/usrp/misc_utils.hpp>
+#include <uhd/usrp/dsp_utils.hpp>
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/algorithm.hpp>
#include <uhd/types/mac_addr.hpp>
#include <uhd/types/dict.hpp>
#include <boost/bind.hpp>
+#include <boost/assign/list_of.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
@@ -194,12 +196,13 @@ void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
/***********************************************************************
* MBoard Get Properties
**********************************************************************/
+static const std::string dboard_name = "0";
+
void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the other props
- if (key.type() == typeid(std::string)){
+ if (key_.type() == typeid(std::string)){
if (key.as<std::string>() == "mac-addr"){
byte_vector_t bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, 6);
val = mac_addr_t::from_bytes(bytes).to_string();
@@ -230,25 +233,25 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
return;
case MBOARD_PROP_RX_DBOARD:
- UHD_ASSERT_THROW(name == "");
+ UHD_ASSERT_THROW(key.name == dboard_name);
val = _rx_dboard_proxy->get_link();
return;
case MBOARD_PROP_RX_DBOARD_NAMES:
- val = prop_names_t(1, "");
+ val = prop_names_t(1, dboard_name);
return;
case MBOARD_PROP_TX_DBOARD:
- UHD_ASSERT_THROW(name == "");
+ UHD_ASSERT_THROW(key.name == dboard_name);
val = _tx_dboard_proxy->get_link();
return;
case MBOARD_PROP_TX_DBOARD_NAMES:
- val = prop_names_t(1, "");
+ val = prop_names_t(1, dboard_name);
return;
case MBOARD_PROP_RX_DSP:
- UHD_ASSERT_THROW(name == "");
+ UHD_ASSERT_THROW(key.name == "");
val = _rx_dsp_proxy->get_link();
return;
@@ -257,7 +260,7 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
return;
case MBOARD_PROP_TX_DSP:
- UHD_ASSERT_THROW(name == "");
+ UHD_ASSERT_THROW(key.name == "");
val = _tx_dsp_proxy->get_link();
return;
@@ -333,14 +336,9 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_RX_SUBDEV_SPEC:
_rx_subdev_spec = val.as<subdev_spec_t>();
- //handle automatic
- if (_rx_subdev_spec.empty()) _rx_subdev_spec.push_back(
- subdev_spec_pair_t("", _dboard_manager->get_rx_subdev_names().front())
- );
+ verify_rx_subdev_spec(_rx_subdev_spec, this->get_link());
//sanity check
UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1);
- uhd::assert_has((*this)[MBOARD_PROP_RX_DBOARD_NAMES].as<prop_names_t>(), _rx_subdev_spec.front().db_name, "rx dboard names");
- uhd::assert_has(_dboard_manager->get_rx_subdev_names(), _rx_subdev_spec.front().sd_name, "rx subdev names");
//set the mux
_iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word(
_dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
@@ -349,14 +347,9 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_TX_SUBDEV_SPEC:
_tx_subdev_spec = val.as<subdev_spec_t>();
- //handle automatic
- if (_tx_subdev_spec.empty()) _tx_subdev_spec.push_back(
- subdev_spec_pair_t("", _dboard_manager->get_tx_subdev_names().front())
- );
+ verify_tx_subdev_spec(_tx_subdev_spec, this->get_link());
//sanity check
UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1);
- uhd::assert_has((*this)[MBOARD_PROP_TX_DBOARD_NAMES].as<prop_names_t>(), _tx_subdev_spec.front().db_name, "tx dboard names");
- uhd::assert_has(_dboard_manager->get_tx_subdev_names(), _tx_subdev_spec.front().sd_name, "tx subdev names");
//set the mux
_iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word(
_dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 21f411afe..568c87a22 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -21,7 +21,7 @@
#include <uhd/usrp/device_props.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
-#include <boost/algorithm/string.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
@@ -41,12 +41,6 @@ static const size_t DISCOVERY_TIMEOUT_MS = 100;
/***********************************************************************
* Helper Functions
**********************************************************************/
-std::vector<std::string> split_addrs(const std::string &addrs_str){
- std::vector<std::string> addrs;
- boost::split(addrs, addrs_str, boost::is_any_of("\t "));
- return addrs;
-}
-
template <class T> std::string num2str(T num){
return boost::lexical_cast<std::string>(num);
}
@@ -80,7 +74,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
}
//if there are multiple addresses, just return good, dont test
- std::vector<std::string> addrs = split_addrs(hint["addr"]);
+ std::vector<std::string> addrs = std::split_string(hint["addr"]);
if (addrs.size() > 1){
device_addr_t new_addr;
new_addr["type"] = "usrp2";
@@ -155,7 +149,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){
std::vector<udp_simple::sptr> ctrl_transports;
std::vector<udp_zero_copy::sptr> data_transports;
- BOOST_FOREACH(const std::string &addr, split_addrs(device_addr["addr"])){
+ BOOST_FOREACH(const std::string &addr, std::split_string(device_addr["addr"])){
ctrl_transports.push_back(udp_simple::make_connected(
addr, num2str(USRP2_UDP_CTRL_PORT)
));
@@ -207,8 +201,7 @@ usrp2_impl::~usrp2_impl(void){
* Device Properties
**********************************************************************/
void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
- wax::obj key; std::string name;
- boost::tie(key, name) = extract_named_prop(key_);
+ named_prop_t key = named_prop_t::extract(key_);
//handle the get request conditioned on the key
switch(key.as<device_prop_t>()){
@@ -218,7 +211,7 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
return;
case DEVICE_PROP_MBOARD:
- val = _mboard_dict[name]->get_link();
+ val = _mboard_dict[key.name]->get_link();
return;
case DEVICE_PROP_MBOARD_NAMES:
diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp
index 4029bd989..6ad12d3cc 100644
--- a/host/lib/utils/paths.cpp
+++ b/host/lib/utils/paths.cpp
@@ -17,7 +17,7 @@
#include "constants.hpp"
#include <uhd/config.hpp>
-#include <boost/algorithm/string.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
@@ -58,15 +58,9 @@ static std::vector<fs::path> get_env_paths(const std::string &var_name){
po::store(po::parse_environment(desc, boost::bind(&name_mapper, var_name, _1)), vm);
po::notify(vm);
- //split the path at the path separators
- std::vector<std::string> path_strings;
- if (not var_value.empty()) boost::split(//dont split empty strings
- path_strings, var_value, boost::is_any_of(env_path_sep)
- );
-
//convert to filesystem path, filter blank paths
std::vector<fs::path> paths;
- BOOST_FOREACH(std::string &path_string, path_strings){
+ BOOST_FOREACH(const std::string &path_string, std::split_string(var_value, env_path_sep)){
if (path_string.empty()) continue;
paths.push_back(fs::system_complete(path_string));
}
@@ -78,13 +72,17 @@ static std::vector<fs::path> get_env_paths(const std::string &var_name){
**********************************************************************/
std::vector<fs::path> get_image_paths(void){
std::vector<fs::path> paths = get_env_paths("UHD_IMAGE_PATH");
- paths.push_back(fs::path(UHD_INSTALL_PREFIX) / UHD_PKG_DATA_DIR / "images");
+ paths.push_back(fs::path(LOCAL_PKG_DATA_DIR) / "images");
+ if (not std::string(INSTALLER_PKG_DATA_DIR).empty())
+ paths.push_back(fs::path(INSTALLER_PKG_DATA_DIR) / "images");
return paths;
}
std::vector<fs::path> get_module_paths(void){
std::vector<fs::path> paths = get_env_paths("UHD_MODULE_PATH");
- paths.push_back(fs::path(UHD_INSTALL_PREFIX) / UHD_PKG_DATA_DIR / "modules");
+ paths.push_back(fs::path(LOCAL_PKG_DATA_DIR) / "modules");
+ if (not std::string(INSTALLER_PKG_DATA_DIR).empty())
+ paths.push_back(fs::path(INSTALLER_PKG_DATA_DIR) / "modules");
return paths;
}
diff --git a/host/lib/utils/props.cpp b/host/lib/utils/props.cpp
index fac5fe24f..fc9f8e63f 100644
--- a/host/lib/utils/props.cpp
+++ b/host/lib/utils/props.cpp
@@ -29,15 +29,12 @@ named_prop_t::named_prop_t(
/* NOP */
}
-typedef boost::tuple<wax::obj, std::string> named_prop_tuple;
-
-named_prop_tuple uhd::extract_named_prop(
+named_prop_t named_prop_t::extract(
const wax::obj &key,
const std::string &name
){
if (key.type() == typeid(named_prop_t)){
- named_prop_t np = key.as<named_prop_t>();
- return named_prop_tuple(np.key, np.name);
+ return key.as<named_prop_t>();
}
- return named_prop_tuple(key, name);
+ return named_prop_t(key, name);
}
diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp
index ae4d4c7aa..8a7d35a23 100644
--- a/host/lib/utils/warning.cpp
+++ b/host/lib/utils/warning.cpp
@@ -16,7 +16,7 @@
//
#include <uhd/utils/warning.hpp>
-#include <boost/algorithm/string.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <vector>
@@ -24,13 +24,9 @@
using namespace uhd;
void uhd::print_warning(const std::string &msg){
- //extract the message lines
- std::vector<std::string> lines;
- boost::split(lines, msg, boost::is_any_of("\n"));
-
//print the warning message
std::cerr << std::endl << "Warning:" << std::endl;
- BOOST_FOREACH(const std::string &line, lines){
+ BOOST_FOREACH(const std::string &line, std::split_string(msg, "\n")){
std::cerr << " " << line << std::endl;
}
}
diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp
index 097317516..8947034d7 100644
--- a/host/utils/uhd_usrp_probe.cpp
+++ b/host/utils/uhd_usrp_probe.cpp
@@ -18,6 +18,7 @@
#include <uhd/utils/safe_main.hpp>
#include <uhd/device.hpp>
#include <uhd/types/ranges.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <uhd/usrp/device_props.hpp>
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/usrp/dboard_props.hpp>
@@ -26,7 +27,6 @@
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dboard_id.hpp>
#include <boost/program_options.hpp>
-#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <iostream>
@@ -43,7 +43,7 @@ static std::string make_border(const std::string &text){
std::stringstream ss;
ss << boost::format(" _____________________________________________________") << std::endl;
ss << boost::format(" /") << std::endl;
- std::vector<std::string> lines; boost::split(lines, text, boost::is_any_of("\n"));
+ std::vector<std::string> lines = std::split_string(text, "\n");
while (lines.back() == "") lines.pop_back(); //strip trailing newlines
if (lines.size()) lines[0] = " " + lines[0]; //indent the title line
BOOST_FOREACH(const std::string &line, lines){