diff options
Diffstat (limited to 'host')
84 files changed, 2157 insertions, 1654 deletions
| diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 67a824c8f..2245cd755 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -138,6 +138,22 @@ IF(MSVC)      ADD_DEFINITIONS(/MP) #multi-threaded build  ENDIF(MSVC) +IF(MINGW) +    #Avoid depending on MinGW runtime DLLs +    CHECK_CXX_COMPILER_FLAG(-static-libgcc HAVE_STATIC_LIBGCC_FLAG) +    IF(HAVE_STATIC_LIBGCC_FLAG) +        SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc") +        SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc") +        SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -static-libgcc") +    ENDIF() +    CHECK_CXX_COMPILER_FLAG(-static-libstdc++ HAVE_STATIC_LIBSTDCXX_FLAG) +    IF(HAVE_STATIC_LIBSTDCXX_FLAG) +        SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++") +        SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++") +        SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -static-libstdc++") +    ENDIF() +ENDIF() +  IF(CYGWIN)      ADD_DEFINITIONS(-D__USE_W32_SOCKETS) #boost asio says we need this  ENDIF(CYGWIN) diff --git a/host/apps/omap_debug/.gitignore b/host/apps/omap_debug/.gitignore deleted file mode 100644 index 008a23138..000000000 --- a/host/apps/omap_debug/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -.gitignore -clkgen-config -fpga-downloader -usrp-e-button -usrp-e-crc-rw -usrp-e-ctl -usrp-e-debug-pins -usrp-e-fpga-rw -usrp-e-gpio -usrp-e-i2c -usrp-e-lb-test -usrp-e-led -usrp-e-loopback -usrp-e-random-loopback -usrp-e-rw -usrp-e-spi -usrp-e-timed -usrp-e-uart -usrp-e-uart-rx -usrp-e-mm-loopback diff --git a/host/apps/omap_debug/Makefile b/host/apps/omap_debug/Makefile deleted file mode 100644 index f8b9f2bd9..000000000 --- a/host/apps/omap_debug/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CFLAGS=-Wall -I../../lib/usrp/usrp_e/ -march=armv7-a -mtune=cortex-a8 -mfpu=neon -O3 -CXXFLAGS=-Wall -I../../lib/usrp/usrp_e/ -march=armv7-a -mtune=cortex-a8 -mfpu=neon -O3 - -all : usrp-e-spi usrp-e-i2c usrp-e-uart usrp-e-led usrp-e-ctl usrp-e-button usrp-e-uart-rx usrp-e-gpio usrp-e-debug-pins - -usrp-e-spi : usrp-e-spi.c - -usrp-e-i2c : usrp-e-i2c.c - -usrp-e-uart : usrp-e-uart.c - -usrp-e-uart-rx : usrp-e-uart-rx.c - -usrp-e-led : usrp-e-led.c - -usrp-e-ctl : usrp-e-ctl.c - -usrp-e-button : usrp-e-button.c - -usrp-e-gpio : usrp-e-gpio.c - -usrp-e-debug-pins : usrp-e-debug-pins.c -clean : -	rm -f usrp-e-spi -	rm -f usrp-e-i2c -	rm -f usrp-e-uart -	rm -f usrp-e-uart-rx -	rm -f usrp-e-led -	rm -f usrp-e-ctl -	rm -f usrp-e-button -	rm -f usrp-e-gpio -	rm -f usrp-e-debug-pins -	rm -f usrp-e-lb-test diff --git a/host/apps/omap_debug/set_debug_pins.py b/host/apps/omap_debug/set_debug_pins.py deleted file mode 100755 index 0f9ecd7b9..000000000 --- a/host/apps/omap_debug/set_debug_pins.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/python - -import os - -# Memory Map -misc_base = 0 -uart_base = 1 -spi_base = 2 -i2c_base = 3 -gpio_base = 4 * 128 -settings_base = 5 - -# GPIO offset -gpio_pins = 0 -gpio_ddr = 4 -gpio_ctrl_lo = 8 -gpio_ctrl_hi = 12 - -def set_reg(reg, val): -    os.system("./usrp1-e-ctl w %d 1 %d" % (reg,val)) - -def get_reg(reg): -    fin,fout = os.popen4("./usrp1-e-ctl r %d 1" % (reg,)) -    print fout.read() - -# Set DDRs to output -set_reg(gpio_base+gpio_ddr, 0xFFFF) -set_reg(gpio_base+gpio_ddr+2, 0xFFFF) - -# Set CTRL to Debug #0 ( A is for debug 0, F is for debug 1 ) -set_reg(gpio_base+gpio_ctrl_lo, 0xAAAA) -set_reg(gpio_base+gpio_ctrl_lo+2, 0xAAAA) -set_reg(gpio_base+gpio_ctrl_hi, 0xAAAA) -set_reg(gpio_base+gpio_ctrl_hi+2, 0xAAAA) - diff --git a/host/apps/omap_debug/test.c b/host/apps/omap_debug/test.c deleted file mode 100644 index 36f4d700a..000000000 --- a/host/apps/omap_debug/test.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <stdio.h> - -void -main() -{ -  int x; -  char *y; -  long long z; - -  x = 0x01020304; -  z = 0x0102030405060708LL; - -  printf("%x\n",x); -  y = (char *)&x; -  printf("%x\n",y[0]); -  printf("%x\n",y[1]); -  printf("%x\n",y[2]); -  printf("%x\n",y[3]); - -  printf("Printing z ...\n"); -  printf("%llx\n",z); -  printf("Printing z done\n"); - -  y = (char *)&z; -  printf("%x\n",y[0]); -  printf("%x\n",y[1]); -  printf("%x\n",y[2]); -  printf("%x\n",y[3]); -  printf("%x\n",y[4]); -  printf("%x\n",y[5]); -  printf("%x\n",y[6]); -  printf("%x\n",y[7]); -} - diff --git a/host/apps/omap_debug/u1e-read-stream.c b/host/apps/omap_debug/u1e-read-stream.c deleted file mode 100644 index 4e4c21d9e..000000000 --- a/host/apps/omap_debug/u1e-read-stream.c +++ /dev/null @@ -1,21 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> - -int main(int rgc, char *argv[]) -{ -	int fp, cnt, n; -	short buf[1024]; - -	n = 0; - -	fp = open("/dev/usrp1_e0", O_RDONLY); -	printf("fp = %d\n", fp); - -	do { -		cnt = read(fp, buf, 2048); -		n++; -//		printf("Bytes read - %d\n", cnt); -	} while(n < 10*512); -	printf("Data - %hX\n", buf[0]); -} diff --git a/host/apps/omap_debug/usrp-e-button.c b/host/apps/omap_debug/usrp-e-button.c deleted file mode 100644 index f13291491..000000000 --- a/host/apps/omap_debug/usrp-e-button.c +++ /dev/null @@ -1,56 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <fcntl.h> -#include <string.h> -#include <sys/ioctl.h> -#include <unistd.h> - -#include "usrp_e.h" -#include "usrp_e_regs.hpp" - -// Usage: usrp_e_uart <string> - -#define PB1 (1<<8) -#define PB2 (1<<9) -#define PB3 (1<<10) -#define P1 (0) -#define P2 (0xFF) -#define P3 (0xAA) -#define P4 (0x55) - -int main(int argc, char *argv[]) -{ -	int fp, ret; -	struct usrp_e_ctl16 d; -	int pb1=0, pb2=0, pb3=0, p1=0, p2=0, p3=0, p4=0; - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	d.offset = UE_REG_MISC_SW; -	d.count = 1; - -	do { -		ret = ioctl(fp, USRP_E_READ_CTL16, &d); -		if (d.buf[0] & PB1) { -			pb1 = 1; -			printf("Pushbutton 1 hit\n"); -		} - -		if (d.buf[0] & PB2) { -			pb2 = 1; -			printf("Pushbutton 2 hit\n"); -		} - -		if (d.buf[0] & PB3) { -			pb3 = 1; -			printf("Pushbutton 3 hit\n"); -		} - -		sleep(1); - -	} while (!(pb1 && pb2 && pb3)); - -	return 0; -} diff --git a/host/apps/omap_debug/usrp-e-ctl.c b/host/apps/omap_debug/usrp-e-ctl.c deleted file mode 100644 index 69c48ee6f..000000000 --- a/host/apps/omap_debug/usrp-e-ctl.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#include "usrp_e.h" - -// Usage: usrp_e_ctl w|r offset number_of_values val1 val2 .... - -int main(int argc, char *argv[]) -{ -	int fp, i, cnt, ret; -	struct usrp_e_ctl16 ctl_data; - -	if (argc < 4) { -		printf("Usage: usrp_e_ctl w|r offset number_of_values val1 val2 ....\n"); -		exit(-1); -	} - -	cnt = atoi(argv[3]); - -	ctl_data.offset = atoi(argv[2]); -	ctl_data.count  = cnt; - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	if (*argv[1] == 'w') { -		for (i=0; i<cnt; i++) -			ctl_data.buf[i] = atoi(argv[4+i]); - -		ret = ioctl(fp, USRP_E_WRITE_CTL16, &ctl_data); -		printf("Return value from write ioctl = %d\n", ret); -	} - -	if (*argv[1] == 'r') { -		ret = ioctl(fp, USRP_E_READ_CTL16, &ctl_data); -		printf("Return value from write ioctl = %d\n", ret); - -		for (i=0; i<ctl_data.count; i++) { -			if (!(i%8)) -				printf("\nData at %4d :", i); -			printf(" %5d", ctl_data.buf[i]); -		} -		printf("\n"); -	} -} diff --git a/host/apps/omap_debug/usrp-e-debug-pins.c b/host/apps/omap_debug/usrp-e-debug-pins.c deleted file mode 100644 index d18bbf990..000000000 --- a/host/apps/omap_debug/usrp-e-debug-pins.c +++ /dev/null @@ -1,77 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <fcntl.h> -#include <string.h> -#include <sys/ioctl.h> - -#include "usrp_e.h" -#include "usrp_e_regs.hpp" - -// Usage: usrp_e_gpio <string> - -static int fp; - -static int read_reg(__u16 reg) -{ -	int ret; -	struct usrp_e_ctl16 d; - -	d.offset = reg; -	d.count = 1; -	ret = ioctl(fp, USRP_E_READ_CTL16, &d); -	return d.buf[0]; -} - -static void write_reg(__u16 reg, __u16 val) -{ -	int ret; -	struct usrp_e_ctl16 d; - -	d.offset = reg; -	d.count = 1; -	d.buf[0] = val; -	ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -} - -int main(int argc, char *argv[]) -{ -	int test; - -	test = 0; -	if (argc < 2) { -		printf("%s 0|1|off\n", argv[0]); -	} - -        fp = open("/dev/usrp_e0", O_RDWR); -        printf("fp = %d\n", fp); -	if (fp < 0) { -		perror("Open failed"); -		return -1; -	} - -	if (strcmp(argv[1], "0") == 0) { -		printf("Selected 0 based on %s\n", argv[1]); -		write_reg(UE_REG_GPIO_TX_DDR, 0xFFFF); -		write_reg(UE_REG_GPIO_RX_DDR, 0xFFFF); -		write_reg(UE_REG_GPIO_TX_SEL, 0x0); -		write_reg(UE_REG_GPIO_RX_SEL, 0x0); -		write_reg(UE_REG_GPIO_TX_DBG, 0xFFFF); -		write_reg(UE_REG_GPIO_RX_DBG, 0xFFFF); -	} else if (strcmp(argv[1], "1") == 0) { -		printf("Selected 1 based on %s\n", argv[1]); -		write_reg(UE_REG_GPIO_TX_DDR, 0xFFFF); -		write_reg(UE_REG_GPIO_RX_DDR, 0xFFFF); -		write_reg(UE_REG_GPIO_TX_SEL, 0xFFFF); -		write_reg(UE_REG_GPIO_RX_SEL, 0xFFFF); -		write_reg(UE_REG_GPIO_TX_DBG, 0xFFFF); -		write_reg(UE_REG_GPIO_RX_DBG, 0xFFFF); -	} else { -		printf("Selected off based on %s\n", argv[1]); -		write_reg(UE_REG_GPIO_TX_DDR, 0x0); -		write_reg(UE_REG_GPIO_RX_DDR, 0x0); -	} - -	return 0; -} diff --git a/host/apps/omap_debug/usrp-e-i2c.c b/host/apps/omap_debug/usrp-e-i2c.c deleted file mode 100644 index da8709ae1..000000000 --- a/host/apps/omap_debug/usrp-e-i2c.c +++ /dev/null @@ -1,87 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#include "usrp_e.h" - -// Usage: usrp_e_i2c w address data0 data1 data 2 .... -// Usage: usrp_e_i2c r address count - -int main(int argc, char *argv[]) -{ -	int fp, ret, i, tmp; -	struct usrp_e_i2c *i2c_msg; -	int direction, address, count; - -	if (argc < 3) { -		printf("Usage: usrp-e-i2c w address data0 data1 data2 ...\n"); -		printf("Usage: usrp-e-i2c r address count\n"); -		printf("All addresses and data in hex.\n"); -		exit(-1); -	} - -	if (strcmp(argv[1], "r") == 0) { -		direction = 0; -	} else if (strcmp(argv[1], "w") == 0) { -		direction = 1; -	} else { -		return -1; -	} - -	sscanf(argv[2], "%X", &address); -	printf("Address = %X\n", address); - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); -	if (fp < 0) { -		perror("Open failed"); -		return -1; -	} - -//	sleep(1); - -	if (direction) { -		count = argc - 3; -	} else { -		sscanf(argv[3], "%X", &count); -	} -	printf("Count = %X\n", count); - -	i2c_msg = malloc(sizeof(i2c_msg) + count * sizeof(char)); - -	i2c_msg->addr = address; -	i2c_msg->len = count; - -	for (i = 0; i < count; i++) { -		i2c_msg->data[i] = i; -	} - -	if (direction) { -		// Write - -		for (i=0; i<count; i++) { -			sscanf(argv[3+i], "%X", &tmp); -			i2c_msg->data[i] = tmp; -		} - -		ret = ioctl(fp, USRP_E_I2C_WRITE, i2c_msg); -		printf("Return value from i2c_write ioctl: %d\n", ret); -	} else { -		// Read - -		ret = ioctl(fp, USRP_E_I2C_READ, i2c_msg); -		printf("Return value from i2c_read ioctl: %d\n", ret); - -		printf("Ioctl: %d Data read :", ret); -		for (i=0; i<count; i++) { -			printf(" %X", i2c_msg->data[i]); -		} -		printf("\n"); -			 -	} -	return 0; -} diff --git a/host/apps/omap_debug/usrp-e-lb-test.c b/host/apps/omap_debug/usrp-e-lb-test.c deleted file mode 100644 index 68848064e..000000000 --- a/host/apps/omap_debug/usrp-e-lb-test.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include "usrp_e.h" - -// max length #define PKT_DATA_LENGTH 1016 - -int main(int argc, char *argv[]) -{ -	struct usrp_transfer_frame *tx_data, *rx_data; -	int i, fp, packet_data_length, cnt; -	struct usrp_e_ctl16 d; - -	if (argc < 2) { -		printf("%s data_size (in bytes < 2040)\n", argv[0]); -		return -1; -	} - -	packet_data_length = atoi(argv[1]); - -	fp = open("/dev/usrp_e0", O_RDWR); - -	d.offset = 14; -	d.count = 1; -	d.buf[0] = (1 << 13); -	ioctl(fp, USRP_E_WRITE_CTL16, &d); - -	tx_data = malloc(2048); -	rx_data = malloc(2048); - -	tx_data->status = 0; -	tx_data->len = sizeof(struct usrp_transfer_frame) + packet_data_length; - -	while (1) { - -		for (i = 0; i < packet_data_length; i++) { -			tx_data->buf[i] = random() >> 24; - -		} - -		cnt = write(fp, tx_data, 2048); -		cnt = read(fp, rx_data, 2048); - -		if (tx_data->len != rx_data->len) -			printf("Bad frame length sent %d, read %d\n", tx_data->len, rx_data->len); - -		for (i = 0; i < packet_data_length; i++) { -			if (tx_data->buf[i] != rx_data->buf[i]) -				printf("Bad data at %d, sent %d, received %d\n", i, tx_data->buf[i], rx_data->buf[i]); -		} -		printf("---------------------------------------------------\n"); -		sleep(1); -	} -} diff --git a/host/apps/omap_debug/usrp-e-led.c b/host/apps/omap_debug/usrp-e-led.c deleted file mode 100644 index d1b6c8996..000000000 --- a/host/apps/omap_debug/usrp-e-led.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <fcntl.h> -#include <string.h> -#include <sys/ioctl.h> -#include <unistd.h> - -#include "usrp_e.h" -#include "usrp_e_regs.hpp" - -// Usage: usrp_e_uart <string> - - -int main(int argc, char *argv[]) -{ -	int fp, i, ret; -	struct usrp_e_ctl16 d; - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	d.offset = UE_REG_MISC_BASE; -	d.count = 1; - -	while (1) { -		for (i=0; i<8; i++) { -			d.buf[0] = i; -			ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -			sleep(1); -		} -	} - -	return 0; -} diff --git a/host/apps/omap_debug/usrp-e-ram.c b/host/apps/omap_debug/usrp-e-ram.c deleted file mode 100644 index d548f7ccd..000000000 --- a/host/apps/omap_debug/usrp-e-ram.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> - -int main(int rgc, char *argv[]) -{ -	int fp, i, cnt; -	unsigned short buf[1024]; -	unsigned short buf_rb[1024]; - -	fp = open("/dev/usrp1_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	for (i=0; i<1024; i++) -		buf[i] = i*256;  -	write(fp, buf, 2048); -	read(fp, buf_rb, 2048); - -	printf("Read back %hX %hX\n", buf_rb[0], buf_rb[1]); - -	for (i=0; i<1024; i++) { -		if (buf[i] != buf_rb[i]) -			printf("Read - %hX, expected - %hX\n", buf_rb[i], buf[i]); -	} -} diff --git a/host/apps/omap_debug/usrp-e-read.c b/host/apps/omap_debug/usrp-e-read.c deleted file mode 100644 index c28f018d5..000000000 --- a/host/apps/omap_debug/usrp-e-read.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> - -int main(int rgc, char *argv[]) -{ -	int fp, cnt; -	short buf[1024]; - -	fp = open("/dev/usrp1_e0", O_RDONLY); -	printf("fp = %d\n", fp); - -	do { -	cnt = read(fp, buf, 2048); -//	printf("Bytes read - %d\n", cnt); -	} while(1); -	printf("Data - %hX\n", buf[0]); -} diff --git a/host/apps/omap_debug/usrp-e-spi.c b/host/apps/omap_debug/usrp-e-spi.c deleted file mode 100644 index c353c409b..000000000 --- a/host/apps/omap_debug/usrp-e-spi.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#include "usrp_e.h" - -// Usage: usrp_e_spi w|rb slave data - -int main(int argc, char *argv[]) -{ -	int fp, slave, length, ret; -	unsigned int data; -	struct usrp_e_spi spi_dat; - -	if (argc < 5) { -		printf("Usage: usrp_e_spi w|rb slave transfer_length data\n"); -		exit(-1); -	} - -	slave = atoi(argv[2]); -	length = atoi(argv[3]); -	data = atoll(argv[4]); - -	printf("Data = %X\n", data); - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); -	if (fp < 0) { -		perror("Open failed"); -		return -1; -	} - -//	sleep(1); - - -	spi_dat.slave = slave; -	spi_dat.data = data; -	spi_dat.length = length; -	spi_dat.flags = UE_SPI_PUSH_FALL | UE_SPI_LATCH_RISE; - -	if (*argv[1] == 'r') { -		spi_dat.readback = 1; -		ret = ioctl(fp, USRP_E_SPI, &spi_dat); -		printf("Ioctl returns: %d, Data returned = %d\n", ret, spi_dat.data); -	} else { -		spi_dat.readback = 0; -		ioctl(fp, USRP_E_SPI, &spi_dat); -	} - -	return 0; -} diff --git a/host/apps/omap_debug/usrp-e-uart-rx.c b/host/apps/omap_debug/usrp-e-uart-rx.c deleted file mode 100644 index 24b417980..000000000 --- a/host/apps/omap_debug/usrp-e-uart-rx.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <fcntl.h> -#include <string.h> -#include <sys/ioctl.h> - -#include "usrp_e.h" -#include "usrp_e_regs.hpp" - -// Usage: usrp_e_uart <string> - - -int main(int argc, char *argv[]) -{ -	int fp, ret; -	struct usrp_e_ctl16 d; -	__u16 clkdiv; - -	if (argc == 0) { -		printf("Usage: usrp-e-uart-rx <opt clkdiv>\n"); -		printf("clkdiv = 278 is 230.4k \n"); -		printf("clkdiv = 556 is 115.2k \n"); -		exit(-1); -	} - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	if (argc == 2) { -		clkdiv = atoi(argv[1]); -		d.offset = UE_REG_UART_CLKDIV; -		d.count = 1; -		d.buf[0] = clkdiv; -		ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -	} - -	while(1) { -		d.offset = UE_REG_UART_RXLEVEL; -		d.count = 1; -		ret = ioctl(fp, USRP_E_READ_CTL16, &d); - -		if (d.buf[0] > 0) { -			d.offset = UE_REG_UART_RXCHAR; -			d.count = 1; -			ret = ioctl(fp, USRP_E_READ_CTL16, &d); -			printf("%c", d.buf[0]); -			fflush(stdout); -		} -	} - -	return 0; -} diff --git a/host/apps/omap_debug/usrp-e-uart.c b/host/apps/omap_debug/usrp-e-uart.c deleted file mode 100644 index 2956c407f..000000000 --- a/host/apps/omap_debug/usrp-e-uart.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <fcntl.h> -#include <string.h> -#include <sys/ioctl.h> - -#include "usrp_e.h" -#include "usrp_e_regs.hpp" - -// Usage: usrp_e_uart <string> - - -int main(int argc, char *argv[]) -{ -	int fp, i, ret; -	struct usrp_e_ctl16 d; -	char *str = argv[1]; -	__u16 clkdiv; - -	if (argc < 2) { -		printf("Usage: usrp_e_uart <string> <opt clkdiv>\n"); -		printf("clkdiv = 278 is 230.4k \n"); -		printf("clkdiv = 556 is 115.2k \n"); -		exit(-1); -	} - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	if (argc == 3) { -		clkdiv = atoi(argv[2]); -		d.offset = UE_REG_UART_CLKDIV; -		d.count = 1; -		d.buf[0] = clkdiv; -		ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -	} - -	for (i=0; i<strlen(str); i++) { -		d.offset = UE_REG_UART_TXCHAR; -		d.count = 1; -		d.buf[0] = str[i]; -		ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -		printf("Wrote %X, to %X, ret = %d\n", d.buf[0], d.offset, ret); -	} - -	return 0; -} diff --git a/host/apps/omap_debug/usrp-e-write.c b/host/apps/omap_debug/usrp-e-write.c deleted file mode 100644 index 903c0071f..000000000 --- a/host/apps/omap_debug/usrp-e-write.c +++ /dev/null @@ -1,21 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> - -int main(int rgc, char *argv[]) -{ -	int fp, i, cnt; -	short buf[1024]; - -	fp = open("/dev/usrp1_e0", O_WRONLY); -	printf("fp = %d\n", fp); - -	for (i=0; i<1024; i++) { -		buf[i] = i; -	} - -//	do { -		cnt = write(fp, buf, 2048); -		printf("Bytes written - %d\n", cnt); -//	} while (1); -} diff --git a/host/apps/omap_debug/usrp_e.h b/host/apps/omap_debug/usrp_e.h deleted file mode 100644 index 2c4aa2ac1..000000000 --- a/host/apps/omap_debug/usrp_e.h +++ /dev/null @@ -1,60 +0,0 @@ - -/* - *  Copyright (C) 2010 Ettus Research, LLC - * - *  Written by Philip Balister <philip@opensdr.com> - * - *  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 2 of the License, or - *  (at your option) any later version. - */ - -#ifndef __USRP_E_H -#define __USRP_E_H - -#include <linux/types.h> -#include <linux/ioctl.h> - -struct usrp_e_ctl16 { -	__u32 offset; -	__u32 count; -	__u16 buf[20]; -}; - -struct usrp_e_ctl32 { -	__u32 offset; -	__u32 count; -	__u32 buf[10]; -}; - -#define USRP_E_IOC_MAGIC	'u' -#define USRP_E_WRITE_CTL16	_IOW(USRP_E_IOC_MAGIC, 0x20, struct usrp_e_ctl16) -#define USRP_E_READ_CTL16	_IOWR(USRP_E_IOC_MAGIC, 0x21, struct usrp_e_ctl16) -#define USRP_E_WRITE_CTL32	_IOW(USRP_E_IOC_MAGIC, 0x22, struct usrp_e_ctl32) -#define USRP_E_READ_CTL32	_IOWR(USRP_E_IOC_MAGIC, 0x23, struct usrp_e_ctl32) -#define USRP_E_GET_RB_INFO      _IOR(USRP_E_IOC_MAGIC, 0x27, struct usrp_e_ring_buffer_size_t) -#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) - -#define USRP_E_COMPAT_NUMBER 2 - -/* Flag defines */ -#define RB_USER (1<<0) -#define RB_KERNEL (1<<1) -#define RB_OVERRUN (1<<2) -#define RB_DMA_ACTIVE (1<<3) -#define RB_USER_PROCESS (1<<4) - -struct ring_buffer_info { -	int flags; -	int len; -}; - -struct usrp_e_ring_buffer_size_t { -	int num_pages_rx_flags; -	int num_rx_frames; -	int num_pages_tx_flags; -	int num_tx_frames; -}; - -#endif diff --git a/host/cmake/Toolchains/mingw_cross.cmake b/host/cmake/Toolchains/mingw_cross.cmake new file mode 100644 index 000000000..7c5adb002 --- /dev/null +++ b/host/cmake/Toolchains/mingw_cross.cmake @@ -0,0 +1,69 @@ +# Use this command: +# +#   cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw.cmake . +# +# or for out of source: +# +#   cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw.cmake .. +# +# You will need at least CMake 2.6.0. +# +# Adjust the following paths to suit your environment. +# +# This file was based on http://www.cmake.org/Wiki/CmakeMingw + +# the name of the target operating system +set(CMAKE_SYSTEM_NAME Windows) + +# Assume the target architecture. +# XXX for some reason the value set here gets cleared before we reach the +# main CMakeLists.txt; see that file for a workaround. +# set(CMAKE_SYSTEM_PROCESSOR i686) + +# Which compilers to use for C and C++, and location of target +# environment. +if(EXISTS /usr/i586-mingw32msvc) +    # First look in standard location as used by Debian/Ubuntu/etc. +    set(CMAKE_C_COMPILER i586-mingw32msvc-gcc) +    set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) +    set(CMAKE_RC_COMPILER i586-mingw32msvc-windres) +    set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) +elseif(EXISTS /usr/i686-w64-mingw32) +    # First look in standard location as used by Debian/Ubuntu/etc. +    set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) +    set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) +    set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) +    set(CMAKE_AR:FILEPATH /usr/bin/i686-w64-mingw32-ar) +elseif(EXISTS /opt/mingw) +    # You can get a MinGW environment using the script at <http://mxe.cc>. +    # It downloads and builds MinGW and most of the dependencies for you. +    # You can use the toolchain file generated by MXE called `mxe-conf.cmake' +    # or you can use this file by adjusting the above and following paths. +    set(CMAKE_C_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-gcc) +    set(CMAKE_CXX_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-g++) +    set(CMAKE_RC_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-windres) +    set(CMAKE_FIND_ROOT_PATH /opt/mingw/usr/i686-pc-mingw32) +else() +    # Else fill in local path which the user will likely adjust. +    # This is the location assumed by <http://www.libsdl.org/extras/win32/cross/> +    set(CMAKE_C_COMPILER /usr/local/cross-tools/bin/i386-mingw32-gcc) +    set(CMAKE_CXX_COMPILER /usr/local/cross-tools/bin/i386-mingw32-g++) +    set(CMAKE_RC_COMPILER /usr/local/cross-tools/bin/i386-mingw32-windres) +    set(CMAKE_FIND_ROOT_PATH /usr/local/cross-tools) +endif() + +# Adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Tell pkg-config not to look at the target environment's .pc files. +# Setting PKG_CONFIG_LIBDIR sets the default search directory, but we have to +# set PKG_CONFIG_PATH as well to prevent pkg-config falling back to the host's +# path. +set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) +set(ENV{PKG_CONFIG_PATH} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) + +set(ENV{MINGDIR} ${CMAKE_FIND_ROOT_PATH}) diff --git a/host/docs/dboards.dox b/host/docs/dboards.dox index 13f3ccadd..b38fa5ae1 100644 --- a/host/docs/dboards.dox +++ b/host/docs/dboards.dox @@ -331,6 +331,10 @@ Sensors:  -   **rssi**: float for measured RSSI in dBm  -   **temperature**: float for measured temperature in degC +\subsection dboards_e300 E310 MIMO XCVR board + +Please refer to \ref e3x0_dboard_e310. +  \subsection dboards_dbsrxmod DBSRX - Modifying for other boards that USRP1  Due to different clocking capabilities, the DBSRX will require diff --git a/host/docs/uhd.dox b/host/docs/uhd.dox index 5b0738969..5cbe51a90 100644 --- a/host/docs/uhd.dox +++ b/host/docs/uhd.dox @@ -11,6 +11,7 @@ Some additional pages on developing UHD are also available here:  \li \subpage page_coding  \li \subpage page_stream +\li \subpage page_rtp  */  // vim:ft=doxygen: diff --git a/host/docs/usrp_b200.dox b/host/docs/usrp_b200.dox index 6ee2f3445..9d3550b98 100644 --- a/host/docs/usrp_b200.dox +++ b/host/docs/usrp_b200.dox @@ -36,15 +36,40 @@ images:  The master clock rate feeds the RF frontends and the DSP chains. Users  may select non-default clock rates to acheive integer decimations or -interpolations in the DSP chains. The default master clock rate defaults -to 32 MHz, but can be set to any rate between 5 MHz and 61.44 MHz. +interpolations in the DSP chains. The clock rate can be set to any value +between 5 MHz and 61.44 MHz (or 30.72 MHz for dual-channel mode). +Note that rates above 56 MHz are possible, but not recommended.  The user can set the master clock rate through the usrp API call  uhd::usrp::multi_usrp::set_master_clock_rate(), or the clock rate can be set through the -device arguments, which many applications take: : +device arguments, which many applications take:      uhd_usrp_probe --args="master_clock_rate=52e6" +The property to control the master clock rate is a double value, called `tick_rate`. + +\subsection b200_auto_mcr Automatic Clock Rate Setting + +The default clock rate setting is to automatically set a clock rate +depending on the requested sampling rate. The automatic clock rate selection +is disabled when either `master_clock_rate` is given in the device initialization +arguments, or when uhd::usrp::multi_usrp::set_master_clock_rate() is called. + +Note that the master clock rate must be an integer multiple of the sampling +rate. If a master clock rate is chosen for which this condition does not +hold, a warning will be displayed and a different sampling rate is used internally. + +Nevertheless, there are multiple valid values for the master clock rate +for most sampling rates. The auto clock rate selection attempts to use +the largest possible clock rate as to enable as many half-band filters +as possible. Expert users might have cases where a more fine-grained +control over the resampling stages is required, in which case manually +selecting a master clock rate might be more suitable than the automatic +rate. + +The property to dis- or enable the auto tick rate is a boolean value, +`auto_tick_rate`. +  \section b200_fe RF Frontend Notes  The B200 features an integrated RF frontend. diff --git a/host/docs/usrp_e3x0.dox b/host/docs/usrp_e3x0.dox index ebe02627a..6ef8554a6 100644 --- a/host/docs/usrp_e3x0.dox +++ b/host/docs/usrp_e3x0.dox @@ -132,7 +132,7 @@ which should return 'arm-oe-linux-gnueabi'.  -# Setup your environment as described in \ref e3x0_sdk_usage  -# Type the following in the build directory (assuming a build in host/build): -        $ cmake -DCMAKE_TOOLCHAIN_FILE=<youruhdsrc>/host/cmake/Toolchains/oe-sdk_cross.cmake -DENABLE_E300 .. +        $ cmake -DCMAKE_TOOLCHAIN_FILE=<youruhdsrc>/host/cmake/Toolchains/oe-sdk_cross.cmake -DENABLE_E300=On ..          $ make  \subsubsection e3x0_sdk_usage_gnuradio Building GNU Radio @@ -191,7 +191,7 @@ builds)   $ bitbake gnuradio-dev-image  \endcode -When this completes, the files needed to create the sd card are in +When this completes, the files needed to create the SD card are in  `tmp-glibc/deploy/images/ettus-e300`  -# Build the toolchain. @@ -395,7 +395,7 @@ usrp->set_rx_subdev_spec("A:A A:B");  The following sensors are available for the USRP-E Series motherboards;  they can be queried through the API. -- **fe_locked** - rx / tx frontend pll locked +- **fe_locked** - rx / tx frontend PLL locked  - **temp** - processor temperature value  - **gps_time** and **gps_locked** sensors are added when the GPSDO is found diff --git a/host/docs/vrt_chdr.dox b/host/docs/vrt_chdr.dox new file mode 100644 index 000000000..8ab177b21 --- /dev/null +++ b/host/docs/vrt_chdr.dox @@ -0,0 +1,83 @@ +/*! \page page_rtp Radio Transport Protocols + +\tableofcontents + +Radio transport protocols are used to exchange samples (or other items) between host and devices. +If one were to sniff Ethernet traffic between a USRP and a PC, the packets would conform to a +radio transport protocol. + +For USRP devices, two radio transport protocols are relevent: VRT (the VITA Radio Transport protocol) +and CVITA (compressed VITA), also known as CHDR. Generation-3 devices and the B200 use CHDR, the rest +use VRT. + +\section rtp_vrt VRT + +VRT is an open protocol defined by the VITA-49 standard. It was designed for interoperability, +and to allow different device types to work with different software stacks. + +VRT is a very verbose standard, and only a subset is implemented in UHD/USRPs. +The full standard is available from the VITA website: http://www.vita.com . + + +\section rtp_chdr CVITA (CHDR) + +For the third generation of Ettus devices, a new type transport protocol was designed. +It reduces the complexity of the original standard and uses a fixed-length 64-Bit header +for everything except the timestamp. Because this is a "compressed" form of VITA, it +was dubbed "Compressed VITA" (CVITA). The compressed header is called CHDR, which is why +the protocol is often called CHDR itself (pronounced like the cheese "cheddar"). + +By compressing all information into a 64-bit line, the header can efficiently be parsed +in newer FPGAs, where the common streaming protocol is 64-Bit AXI. The first line in a +packet already provides all necessary information to proceed. + +Some CHDR-specific functions can be found in: uhd::transport::vrt::chdr. + +The form of a CVITA packet is the following: + +Address (Bytes) | Length (Bytes) | Payload +----------------|----------------|---------------------------- +0               | 8              | Compressed Header (CHDR) +8               | 8              | Fractional Time (Optional!) +8/16            | -              | Data + +If there is no timestamp present, the data starts at address 8, otherwise, it starts at 16. + +The 64 Bits in the compressed header have the following meaning: + +Bits   | Meaning +-------|-------------------------------------------------- +63:62  | Packet Type +61     | Has fractional time stamp (1: Yes) +60     | End-of-burst or error flag +59:48  | 12-bit sequence number +47:32  | Total packet length in Bytes +31:0   | Stream ID (SID) + + +The packet type is determined mainly by the first two bits, although +the EOB or error flag are also taken into consideration: + +Bit 63 | Bit 62 | Bit 60 | Packet Type +-------|--------|--------|-------------- +0      | 0      | 0      | Data +0      | 0      | 1      | Data (End-of-burst) +0      | 1      | 0      | Flow Control +1      | 0      | 0      | Command Packet +1      | 1      | 0      | Command Response +1      | 1      | 1      | Command Response (Error) + +\section vrt_tools Tools + +For CHDR, we provide a Wireshark dissector under tools/chdr_dissector. It can be used +for Ethernet links as well as USB (e.g., for the B210). + +\section vrt_code Code + +Relevent code sections for the radio transport layer are: +* uhd::transport::vrt - Namespace for radio transport protocol related functions and definitions +* uhd::transport::vrt::chdr - Sub-namespace specifically for CVITA/CHDR +* uhd::sid_t - Datatype to represent SIDs + +*/ +// vim:ft=doxygen: diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index 1e6f2f013..598e42302 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -29,7 +29,6 @@ SET(example_sources      test_messages.cpp      test_pps_input.cpp      test_timed_commands.cpp -    transport_hammer.cpp      tx_bursts.cpp      tx_samples_from_file.cpp      tx_timed_samples.cpp diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp index 03d8f3477..7ff8b9939 100644 --- a/host/examples/benchmark_rate.cpp +++ b/host/examples/benchmark_rate.cpp @@ -43,7 +43,12 @@ unsigned long long num_seq_errors = 0;  /***********************************************************************   * Benchmark RX Rate   **********************************************************************/ -void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_cpu, uhd::rx_streamer::sptr rx_stream){ +void benchmark_rx_rate( +        uhd::usrp::multi_usrp::sptr usrp, +        const std::string &rx_cpu, +        uhd::rx_streamer::sptr rx_stream, +        bool random_nsamps +) {      uhd::set_thread_priority_safe();      //print pre-test summary @@ -68,15 +73,19 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_c      rx_stream->issue_stream_cmd(cmd);      while (not boost::this_thread::interruption_requested()){ +        if (random_nsamps) { +            cmd.num_samps = rand() % max_samps_per_packet; +            rx_stream->issue_stream_cmd(cmd); +        }          try { -          num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md)*rx_stream->get_num_channels(); +            num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md)*rx_stream->get_num_channels();          }          catch (...) { -          /* apparently, the boost thread interruption can sometimes result in -             throwing exceptions not of type boost::exception, this catch allows -             this thread to still attempt to issue the STREAM_MODE_STOP_CONTINUOUS -          */ -          break; +            /* apparently, the boost thread interruption can sometimes result in +               throwing exceptions not of type boost::exception, this catch allows +               this thread to still attempt to issue the STREAM_MODE_STOP_CONTINUOUS +            */ +            break;          }          //handle the error codes @@ -109,7 +118,12 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_c  /***********************************************************************   * Benchmark TX Rate   **********************************************************************/ -void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &tx_cpu, uhd::tx_streamer::sptr tx_stream){ +void benchmark_tx_rate( +        uhd::usrp::multi_usrp::sptr usrp, +        const std::string &tx_cpu, +        uhd::tx_streamer::sptr tx_stream, +        bool random_nsamps=false +) {      uhd::set_thread_priority_safe();      //print pre-test summary @@ -127,9 +141,25 @@ void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp, const std::string &tx_c          buffs.push_back(&buff.front()); //same buffer for each channel      md.has_time_spec = (buffs.size() != 1); -    while (not boost::this_thread::interruption_requested()){ -        num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md)*tx_stream->get_num_channels();; -        md.has_time_spec = false; +    if (random_nsamps) { +        std::srand( time(NULL) ); +        while(not boost::this_thread::interruption_requested()){ +            size_t total_num_samps = rand() % max_samps_per_packet; +            size_t num_acc_samps = 0; +            const float timeout = 1; + +            usrp->set_time_now(uhd::time_spec_t(0.0)); +            while(num_acc_samps < total_num_samps){ +                //send a single packet +                num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md, timeout)*tx_stream->get_num_channels(); +                num_acc_samps += std::min(total_num_samps-num_acc_samps, tx_stream->get_max_num_samps()); +            } +        } +    } else { +        while (not boost::this_thread::interruption_requested()){ +            num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md)*tx_stream->get_num_channels(); +            md.has_time_spec = false; +        }      }      //send a mini EOB packet @@ -182,6 +212,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      std::string rx_cpu, tx_cpu;      std::string mode;      std::string channel_list; +    bool random_nsamps = false;      //setup the program options      po::options_description desc("Allowed options"); @@ -196,6 +227,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("rx_cpu", po::value<std::string>(&rx_cpu)->default_value("fc32"), "specify the host/cpu sample mode for RX")          ("tx_cpu", po::value<std::string>(&tx_cpu)->default_value("fc32"), "specify the host/cpu sample mode for TX")          ("mode", po::value<std::string>(&mode)->default_value("none"), "multi-channel sync mode option: none, mimo") +        ("random", "Run with random values of samples in send() and recv() to stress-test the I/O.")          ("channels", po::value<std::string>(&channel_list)->default_value("0"), "which channel(s) to use (specify \"0\", \"1\", \"0,1\", etc)")      ;      po::variables_map vm; @@ -213,6 +245,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          return ~0;      } +    // Random number of samples? +    if (vm.count("random")) { +        std::cout << "Using random number of samples in send() and recv() calls." << std::endl; +        random_nsamps = true; +    } +      //create a usrp device      std::cout << std::endl;      uhd::device_addrs_t device_addrs = uhd::device::find(args, uhd::device::USRP); @@ -251,7 +289,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          uhd::stream_args_t stream_args(rx_cpu, rx_otw);          stream_args.channels = channel_nums;          uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); -        thread_group.create_thread(boost::bind(&benchmark_rx_rate, usrp, rx_cpu, rx_stream)); +        thread_group.create_thread(boost::bind(&benchmark_rx_rate, usrp, rx_cpu, rx_stream, random_nsamps));      }      //spawn the transmit test thread @@ -261,7 +299,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          uhd::stream_args_t stream_args(tx_cpu, tx_otw);          stream_args.channels = channel_nums;          uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); -        thread_group.create_thread(boost::bind(&benchmark_tx_rate, usrp, tx_cpu, tx_stream)); +        thread_group.create_thread(boost::bind(&benchmark_tx_rate, usrp, tx_cpu, tx_stream, random_nsamps));          thread_group.create_thread(boost::bind(&benchmark_tx_rate_async_helper, tx_stream));      } @@ -287,6 +325,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      //finished      std::cout << std::endl << "Done!" << std::endl << std::endl; -         return EXIT_SUCCESS;  } diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 4fe438798..4e6d8139f 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -56,7 +56,7 @@ template<typename samp_type> void recv_to_file(      std::vector<samp_type> buff(samps_per_buff);      std::ofstream outfile;      if (not null) -		outfile.open(file.c_str(), std::ofstream::binary); +        outfile.open(file.c_str(), std::ofstream::binary);      bool overflow_message = true;      //setup streaming @@ -78,8 +78,8 @@ template<typename samp_type> void recv_to_file(      typedef std::map<size_t,size_t> SizeMap;      SizeMap mapSizes; -    while(not stop_signal_called and (num_requested_samples != num_total_samps or num_requested_samples == 0)){ -		boost::system_time now = boost::get_system_time(); +    while(not stop_signal_called and (num_requested_samples != num_total_samps or num_requested_samples == 0)) { +        boost::system_time now = boost::get_system_time();          size_t num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md, 3.0, enable_size_map); @@ -88,7 +88,7 @@ template<typename samp_type> void recv_to_file(              break;          }          if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){ -            if (overflow_message){ +            if (overflow_message) {                  overflow_message = false;                  std::cerr << boost::format(                      "Got an overflow indication. Please consider the following:\n" @@ -110,99 +110,99 @@ template<typename samp_type> void recv_to_file(                  throw std::runtime_error(error);          } -        if (enable_size_map){ -			SizeMap::iterator it = mapSizes.find(num_rx_samps); -			if (it == mapSizes.end()) -				mapSizes[num_rx_samps] = 0; -			mapSizes[num_rx_samps] += 1; -		} +        if (enable_size_map) { +            SizeMap::iterator it = mapSizes.find(num_rx_samps); +            if (it == mapSizes.end()) +                mapSizes[num_rx_samps] = 0; +            mapSizes[num_rx_samps] += 1; +        }          num_total_samps += num_rx_samps; -		if (outfile.is_open()) -			outfile.write((const char*)&buff.front(), num_rx_samps*sizeof(samp_type)); - -		if (bw_summary){ -			last_update_samps += num_rx_samps; -			boost::posix_time::time_duration update_diff = now - last_update; -			if (update_diff.ticks() > boost::posix_time::time_duration::ticks_per_second()) { -				double t = (double)update_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second(); -				double r = (double)last_update_samps / t; -				std::cout << boost::format("\t%f Msps") % (r/1e6) << std::endl; -				last_update_samps = 0; -				last_update = now; -			} -		} +        if (outfile.is_open()) +            outfile.write((const char*)&buff.front(), num_rx_samps*sizeof(samp_type)); + +        if (bw_summary) { +            last_update_samps += num_rx_samps; +            boost::posix_time::time_duration update_diff = now - last_update; +            if (update_diff.ticks() > boost::posix_time::time_duration::ticks_per_second()) { +                double t = (double)update_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second(); +                double r = (double)last_update_samps / t; +                std::cout << boost::format("\t%f Msps") % (r/1e6) << std::endl; +                last_update_samps = 0; +                last_update = now; +            } +        }          ticks_diff = now - start; -		if (ticks_requested > 0){ -			if ((unsigned long long)ticks_diff.ticks() > ticks_requested) -				break; -		} +        if (ticks_requested > 0){ +            if ((unsigned long long)ticks_diff.ticks() > ticks_requested) +                break; +        }      }      stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;      rx_stream->issue_stream_cmd(stream_cmd);      if (outfile.is_open()) -		outfile.close(); - -    if (stats){ -		std::cout << std::endl; - -		double t = (double)ticks_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second(); -		std::cout << boost::format("Received %d samples in %f seconds") % num_total_samps % t << std::endl; -		double r = (double)num_total_samps / t; -		std::cout << boost::format("%f Msps") % (r/1e6) << std::endl; - -		if (enable_size_map) { -			std::cout << std::endl; -			std::cout << "Packet size map (bytes: count)" << std::endl; -			for (SizeMap::iterator it = mapSizes.begin(); it != mapSizes.end(); it++) -				std::cout << it->first << ":\t" << it->second << std::endl; -		} -	} +        outfile.close(); + +    if (stats) { +        std::cout << std::endl; + +        double t = (double)ticks_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second(); +        std::cout << boost::format("Received %d samples in %f seconds") % num_total_samps % t << std::endl; +        double r = (double)num_total_samps / t; +        std::cout << boost::format("%f Msps") % (r/1e6) << std::endl; + +        if (enable_size_map) { +            std::cout << std::endl; +            std::cout << "Packet size map (bytes: count)" << std::endl; +            for (SizeMap::iterator it = mapSizes.begin(); it != mapSizes.end(); it++) +                std::cout << it->first << ":\t" << it->second << std::endl; +        } +    }  }  typedef boost::function<uhd::sensor_value_t (const std::string&)> get_sensor_fn_t;  bool check_locked_sensor(std::vector<std::string> sensor_names, const char* sensor_name, get_sensor_fn_t get_sensor_fn, double setup_time){ -	if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) == sensor_names.end()) -		return false; - -	boost::system_time start = boost::get_system_time(); -	boost::system_time first_lock_time; - -	std::cout << boost::format("Waiting for \"%s\": ") % sensor_name; -	std::cout.flush(); - -	while (true){ -		if ((not first_lock_time.is_not_a_date_time()) and -			(boost::get_system_time() > (first_lock_time + boost::posix_time::seconds(setup_time)))) -		{ -			std::cout << " locked." << std::endl; -			break; -		} -		if (get_sensor_fn(sensor_name).to_bool()){ -			if (first_lock_time.is_not_a_date_time()) -				first_lock_time = boost::get_system_time(); -			std::cout << "+"; -			std::cout.flush(); -		} -		else{ -			first_lock_time = boost::system_time();	//reset to 'not a date time' - -			if (boost::get_system_time() > (start + boost::posix_time::seconds(setup_time))){ -				std::cout << std::endl; -				throw std::runtime_error(str(boost::format("timed out waiting for consecutive locks on sensor \"%s\"") % sensor_name)); -			} -			std::cout << "_"; -			std::cout.flush(); -		} -		boost::this_thread::sleep(boost::posix_time::milliseconds(100)); -	} -	std::cout << std::endl; -	return true; +    if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) == sensor_names.end()) +        return false; + +    boost::system_time start = boost::get_system_time(); +    boost::system_time first_lock_time; + +    std::cout << boost::format("Waiting for \"%s\": ") % sensor_name; +    std::cout.flush(); + +    while (true) { +        if ((not first_lock_time.is_not_a_date_time()) and +                (boost::get_system_time() > (first_lock_time + boost::posix_time::seconds(setup_time)))) +        { +            std::cout << " locked." << std::endl; +            break; +        } +        if (get_sensor_fn(sensor_name).to_bool()){ +            if (first_lock_time.is_not_a_date_time()) +                first_lock_time = boost::get_system_time(); +            std::cout << "+"; +            std::cout.flush(); +        } +        else { +            first_lock_time = boost::system_time();	//reset to 'not a date time' + +            if (boost::get_system_time() > (start + boost::posix_time::seconds(setup_time))){ +                std::cout << std::endl; +                throw std::runtime_error(str(boost::format("timed out waiting for consecutive locks on sensor \"%s\"") % sensor_name)); +            } +            std::cout << "_"; +            std::cout.flush(); +        } +        boost::this_thread::sleep(boost::posix_time::milliseconds(100)); +    } +    std::cout << std::endl; +    return true;  }  int UHD_SAFE_MAIN(int argc, char *argv[]){ @@ -246,8 +246,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      po::notify(vm);      //print the help message -    if (vm.count("help")){ +    if (vm.count("help")) {          std::cout << boost::format("UHD RX samples to file %s") % desc << std::endl; +        std::cout +            << std::endl +            << "This application streams data from a single channel of a USRP device to a file.\n" +            << std::endl;          return ~0;      } @@ -258,7 +262,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      bool continue_on_bad_packet = vm.count("continue") > 0;      if (enable_size_map) -		std::cout << "Packet size tracking enabled - will only recv one packet at a time!" << std::endl; +        std::cout << "Packet size tracking enabled - will only recv one packet at a time!" << std::endl;      //create a usrp device      std::cout << std::endl; @@ -283,23 +287,23 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      std::cout << boost::format("Actual RX Rate: %f Msps...") % (usrp->get_rx_rate()/1e6) << std::endl << std::endl;      //set the center frequency -    if (vm.count("freq")){	//with default of 0.0 this will always be true -		std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl; +    if (vm.count("freq")) { //with default of 0.0 this will always be true +        std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl;          uhd::tune_request_t tune_request(freq);          if(vm.count("int-n")) tune_request.args = uhd::device_addr_t("mode_n=integer"); -		usrp->set_rx_freq(tune_request); -		std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq()/1e6) << std::endl << std::endl; -	} +        usrp->set_rx_freq(tune_request); +        std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq()/1e6) << std::endl << std::endl; +    }      //set the rf gain -    if (vm.count("gain")){ +    if (vm.count("gain")) {          std::cout << boost::format("Setting RX Gain: %f dB...") % gain << std::endl;          usrp->set_rx_gain(gain);          std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl;      } -    //set the analog frontend filter bandwidth -    if (vm.count("bw")){ +    //set the IF filter bandwidth +    if (vm.count("bw")) {          std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % bw << std::endl;          usrp->set_rx_bandwidth(bw);          std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % usrp->get_rx_bandwidth() << std::endl << std::endl; @@ -312,12 +316,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      //check Ref and LO Lock detect      if (not vm.count("skip-lo")){ -		check_locked_sensor(usrp->get_rx_sensor_names(0), "lo_locked", boost::bind(&uhd::usrp::multi_usrp::get_rx_sensor, usrp, _1, 0), setup_time); -		if (ref == "mimo") -			check_locked_sensor(usrp->get_mboard_sensor_names(0), "mimo_locked", boost::bind(&uhd::usrp::multi_usrp::get_mboard_sensor, usrp, _1, 0), setup_time); -		if (ref == "external") -			check_locked_sensor(usrp->get_mboard_sensor_names(0), "ref_locked", boost::bind(&uhd::usrp::multi_usrp::get_mboard_sensor, usrp, _1, 0), setup_time); -	} +        check_locked_sensor(usrp->get_rx_sensor_names(0), "lo_locked", boost::bind(&uhd::usrp::multi_usrp::get_rx_sensor, usrp, _1, 0), setup_time); +        if (ref == "mimo") +            check_locked_sensor(usrp->get_mboard_sensor_names(0), "mimo_locked", boost::bind(&uhd::usrp::multi_usrp::get_mboard_sensor, usrp, _1, 0), setup_time); +        if (ref == "external") +            check_locked_sensor(usrp->get_mboard_sensor_names(0), "ref_locked", boost::bind(&uhd::usrp::multi_usrp::get_mboard_sensor, usrp, _1, 0), setup_time); +    }      if (total_num_samps == 0){          std::signal(SIGINT, &sig_int_handler); @@ -325,7 +329,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      }  #define recv_to_file_args(format) \ -	(usrp, format, wirefmt, file, spb, total_num_samps, total_time, bw_summary, stats, null, enable_size_map, continue_on_bad_packet) +    (usrp, format, wirefmt, file, spb, total_num_samps, total_time, bw_summary, stats, null, enable_size_map, continue_on_bad_packet)      //recv to file      if (type == "double") recv_to_file<std::complex<double> >recv_to_file_args("fc64");      else if (type == "float") recv_to_file<std::complex<float> >recv_to_file_args("fc32"); diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 30535907f..20abd92fe 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -48,7 +48,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples")          ("dilv", "specify to disable inner-loop verbose")          ("channels", po::value<std::string>(&channel_list)->default_value("0"), "which channel(s) to use (specify \"0\", \"1\", \"0,1\", etc)") -          ;      po::variables_map vm;      po::store(po::parse_command_line(argc, argv, desc), vm); diff --git a/host/examples/test_pps_input.cpp b/host/examples/test_pps_input.cpp index 889c98a45..3e6c4ba9d 100644 --- a/host/examples/test_pps_input.cpp +++ b/host/examples/test_pps_input.cpp @@ -47,6 +47,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      //print the help message      if (vm.count("help")){          std::cout << boost::format("UHD Test PPS Input %s") % desc << std::endl; +        std::cout +                << std::endl +                << "Tests if the PPS input signal is working. Will throw an error if not." +                << std::endl +                << std::endl;          return ~0;      } diff --git a/host/examples/transport_hammer.cpp b/host/examples/transport_hammer.cpp deleted file mode 100644 index 32e344e3e..000000000 --- a/host/examples/transport_hammer.cpp +++ /dev/null @@ -1,280 +0,0 @@ -// -// Copyright 2012 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#include <uhd/utils/thread_priority.hpp> -#include <uhd/convert.hpp> -#include <uhd/utils/safe_main.hpp> -#include <uhd/usrp/multi_usrp.hpp> -#include <boost/program_options.hpp> -#include <boost/format.hpp> -#include <boost/thread/thread.hpp> -#include <boost/math/special_functions/round.hpp> -#include <iostream> -#include <complex> - -namespace po = boost::program_options; - -/*********************************************************************** - * Test result variables - **********************************************************************/ -unsigned long long num_overflows = 0; -unsigned long long num_underflows = 0; -unsigned long long num_rx_samps = 0; -unsigned long long num_tx_samps = 0; -unsigned long long num_dropped_samps = 0; -unsigned long long num_seq_errors = 0; - -/*********************************************************************** - * RX Hammer - **********************************************************************/ -void rx_hammer(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_cpu, uhd::rx_streamer::sptr rx_stream){ -    uhd::set_thread_priority_safe(); - -    //print pre-test summary -    std::cout << boost::format( -        "Testing receive rate %f Msps" -    ) % (usrp->get_rx_rate()/1e6) << std::endl; - -    //setup variables and allocate buffer -    uhd::rx_metadata_t md; -    const size_t max_samps_per_packet = rx_stream->get_max_num_samps(); -    std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(rx_cpu)); -    std::vector<void *> buffs; -    for (size_t ch = 0; ch < rx_stream->get_num_channels(); ch++) -        buffs.push_back(&buff.front()); //same buffer for each channel -    bool had_an_overflow = false; -    uhd::time_spec_t last_time; -    const double rate = usrp->get_rx_rate(); -    double timeout = 1; - -    uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); -    cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05); -    cmd.stream_now = (buffs.size() == 1); -    srand( time(NULL) ); - -    while (not boost::this_thread::interruption_requested()){ -        cmd.num_samps = rand() % 100000; -        rx_stream->issue_stream_cmd(cmd); -        num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md, timeout, true); - -        //handle the error codes -        switch(md.error_code){ -        case uhd::rx_metadata_t::ERROR_CODE_NONE: -            if (had_an_overflow){ -                had_an_overflow = false; -                num_dropped_samps += boost::math::iround((md.time_spec - last_time).get_real_secs()*rate); -            } -            break; - -        case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: -            had_an_overflow = true; -            last_time = md.time_spec; -            if (!md.out_of_sequence) -                num_overflows++; -            break; - -        default: -            std::cerr << "Receiver error: " << md.strerror() << std::endl; -            std::cerr << "Unexpected error on recv, continuing..." << std::endl; -            break; -        } -    } -} - -/*********************************************************************** - * TX Hammer - **********************************************************************/ -void tx_hammer(uhd::usrp::multi_usrp::sptr usrp, const std::string &tx_cpu, uhd::tx_streamer::sptr tx_stream){ -    uhd::set_thread_priority_safe(); - -    uhd::tx_metadata_t md; -    const size_t max_samps_per_packet = tx_stream->get_max_num_samps(); -    std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(tx_cpu)); -    std::vector<void *> buffs; -    for (size_t ch = 0; ch < tx_stream->get_num_channels(); ch++) -        buffs.push_back(&buff.front()); //same buffer for each channel - -    //print pre-test summary -    std::cout << boost::format( -        "Testing transmit rate %f Msps" -    ) % (usrp->get_tx_rate()/1e6) << std::endl; - -    //setup variables and allocate buffer -    std::srand( time(NULL) ); -    while(not boost::this_thread::interruption_requested()){ -        size_t total_num_samps = rand() % 100000; -        size_t num_acc_samps = 0; -        float timeout = 1; - -        usrp->set_time_now(uhd::time_spec_t(0.0)); -        while(num_acc_samps < total_num_samps){ - -            //send a single packet -            num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md, timeout); - -            num_acc_samps += std::min(total_num_samps-num_acc_samps, tx_stream->get_max_num_samps()); -        } -        //send a mini EOB packet -        md.end_of_burst = true; -        tx_stream->send("", 0, md); -    } -} - -void tx_hammer_async_helper(uhd::tx_streamer::sptr tx_stream){ -    //setup variables and allocate buffer -    uhd::async_metadata_t async_md; - -    while (not boost::this_thread::interruption_requested()){ - -        if (not tx_stream->recv_async_msg(async_md)) continue; - -        //handle the error codes -        switch(async_md.event_code){ -        case uhd::async_metadata_t::EVENT_CODE_BURST_ACK: -            return; - -        case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW: -        case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET: -            num_underflows++; -            break; - -        case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR: -        case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST: -            num_seq_errors++; -            break; - -        default: -            std::cerr << "Event code: " << async_md.event_code << std::endl; -            std::cerr << "Unexpected event on async recv, continuing..." << std::endl; -            break; -        } -    } -} - -/*********************************************************************** - * Main code + dispatcher - **********************************************************************/ -int UHD_SAFE_MAIN(int argc, char *argv[]){ -    uhd::set_thread_priority_safe(); - -    //variables to be set by po -    std::string args; -    double duration; -    double rx_rate, tx_rate; -    std::string rx_otw, tx_otw; -    std::string rx_cpu, tx_cpu; -    std::string mode; - -    //setup the program options -    po::options_description desc("Allowed options"); -    desc.add_options() -        ("help", "help message") -        ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args") -        ("duration", po::value<double>(&duration)->default_value(10.0), "if random, specify duration for the test in seconds") -        ("rx_rate", po::value<double>(&rx_rate), "specify to perform a RX rate test (sps)") -        ("tx_rate", po::value<double>(&tx_rate), "specify to perform a TX rate test (sps)") -        ("rx_otw", po::value<std::string>(&rx_otw)->default_value("sc16"), "specify the over-the-wire sample mode for RX") -        ("tx_otw", po::value<std::string>(&tx_otw)->default_value("sc16"), "specify the over-the-wire sample mode for TX") -        ("rx_cpu", po::value<std::string>(&rx_cpu)->default_value("fc32"), "specify the host/cpu sample mode for RX") -        ("tx_cpu", po::value<std::string>(&tx_cpu)->default_value("fc32"), "specify the host/cpu sample mode for TX") -        ("mode", po::value<std::string>(&mode)->default_value("none"), "multi-channel sync mode option: none, mimo") -    ; -    po::variables_map vm; -    po::store(po::parse_command_line(argc, argv, desc), vm); -    po::notify(vm); - -    //print the help message -    if (vm.count("help") or (vm.count("rx_rate") + vm.count("tx_rate")) == 0){ -        //std::cout << boost::format("UHD Transport Hammer - %s") % desc << std::endl; -        std::cout << -        "UHD Transport Hammer: a transport layer stress test that continuously\n" -        "calls for random amounts of TX and RX samples\n\n"; -        std::cout << desc << std::endl << -        "    Specify --rx_rate for a receive-only test.\n" -        "    Specify --tx_rate for a transmit-only test.\n" -        "    Specify both options for a full-duplex test.\n" -        << std::endl; -        return ~0; -    } - -    //create a usrp device -    std::cout << std::endl; -    uhd::device_addrs_t device_addrs = uhd::device::find(args, uhd::device::USRP); -    if (not device_addrs.empty() and device_addrs.at(0).get("type", "") == "usrp1"){ -        std::cerr << "*** Warning! ***" << std::endl; -        std::cerr << "Results will be inaccurate on USRP1 due to insufficient features.\n" << std::endl; -    } -    std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; -    uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); -    std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; - -    if (mode == "mimo"){ -        usrp->set_clock_source("mimo", 0); -        usrp->set_time_source("mimo", 0); -        boost::this_thread::sleep(boost::posix_time::seconds(1)); -    } - -    boost::thread_group thread_group; - -    //spawn the receive test thread -    if (vm.count("rx_rate")){ -        usrp->set_rx_rate(rx_rate); -        //create a receive streamer -        uhd::stream_args_t stream_args(rx_cpu, rx_otw); -        for (size_t ch = 0; ch < usrp->get_num_mboards(); ch++) //linear channel mapping -            stream_args.channels.push_back(ch); -        uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); -        thread_group.create_thread(boost::bind(&rx_hammer, usrp, rx_cpu, rx_stream)); -    } - -    //spawn the transmit test thread -    if (vm.count("tx_rate")){ -        usrp->set_tx_rate(tx_rate); -        //create a transmit streamer -        uhd::stream_args_t stream_args(tx_cpu, tx_otw); -        for (size_t ch = 0; ch < usrp->get_num_mboards(); ch++) //linear channel mapping -            stream_args.channels.push_back(ch); -        uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); -        thread_group.create_thread(boost::bind(&tx_hammer, usrp, tx_cpu, tx_stream)); -        thread_group.create_thread(boost::bind(&tx_hammer_async_helper, tx_stream)); -    } - -    //sleep for the required duration -    const long secs = long(duration); -    const long usecs = long((duration - secs)*1e6); -    boost::this_thread::sleep(boost::posix_time::seconds(secs) + boost::posix_time::microseconds(usecs)); - -    //interrupt and join the threads -    thread_group.interrupt_all(); -    thread_group.join_all(); - -    //print summary -    std::cout << std::endl << boost::format( -        "Transport Hammer summary:\n" -        "  Num received samples:    %u\n" -        "  Num dropped samples:     %u\n" -        "  Num overflows detected:  %u\n" -        "  Num transmitted samples: %u\n" -        "  Num sequence errors:     %u\n" -        "  Num underflows detected: %u\n" -    ) % num_rx_samps % num_dropped_samps % num_overflows % num_tx_samps % num_seq_errors % num_underflows << std::endl; - -    //finished -    std::cout << std::endl << "Done!" << std::endl << std::endl; - -    return EXIT_SUCCESS; -} diff --git a/host/examples/tx_bursts.cpp b/host/examples/tx_bursts.cpp index fec89a0e4..bb71d4581 100644 --- a/host/examples/tx_bursts.cpp +++ b/host/examples/tx_bursts.cpp @@ -148,7 +148,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){              size_t num_tx_samps = tx_stream->send(                  buffs, samps_to_send, md, timeout              ); -                              //do not use time spec for subsequent packets              md.has_time_spec = false;              md.start_of_burst = false; diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 7e633262c..9254c3b24 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -15,6 +15,7 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +#include "wavetable.hpp"  #include <uhd/utils/thread_priority.hpp>  #include <uhd/utils/safe_main.hpp>  #include <uhd/utils/static.hpp> @@ -28,9 +29,7 @@  #include <boost/lexical_cast.hpp>  #include <boost/algorithm/string.hpp>  #include <iostream> -#include <complex>  #include <csignal> -#include <cmath>  namespace po = boost::program_options; @@ -41,52 +40,6 @@ static bool stop_signal_called = false;  void sig_int_handler(int){stop_signal_called = true;}  /*********************************************************************** - * Waveform generators - **********************************************************************/ -static const size_t wave_table_len = 8192; - -class wave_table_class{ -public: -    wave_table_class(const std::string &wave_type, const float ampl): -        _wave_table(wave_table_len) -    { -        //compute real wave table with 1.0 amplitude -        std::vector<double> real_wave_table(wave_table_len); -        if (wave_type == "CONST"){ -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = 1.0; -        } -        else if (wave_type == "SQUARE"){ -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = (i < wave_table_len/2)? 0.0 : 1.0; -        } -        else if (wave_type == "RAMP"){ -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = 2.0*i/(wave_table_len-1) - 1.0; -        } -        else if (wave_type == "SINE"){ -            static const double tau = 2*std::acos(-1.0); -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = std::sin((tau*i)/wave_table_len); -        } -        else throw std::runtime_error("unknown waveform type: " + wave_type); - -        //compute i and q pairs with 90% offset and scale to amplitude -        for (size_t i = 0; i < wave_table_len; i++){ -            const size_t q = (i+(3*wave_table_len)/4)%wave_table_len; -            _wave_table[i] = std::complex<float>(ampl*real_wave_table[i], ampl*real_wave_table[q]); -        } -    } - -    inline std::complex<float> operator()(const size_t index) const{ -        return _wave_table[index % wave_table_len]; -    } - -private: -    std::vector<std::complex<float> > _wave_table; -}; - -/***********************************************************************   * Main function   **********************************************************************/  int UHD_SAFE_MAIN(int argc, char *argv[]){ diff --git a/host/examples/txrx_loopback_to_file.cpp b/host/examples/txrx_loopback_to_file.cpp index f8c8b9785..7ef77801b 100644 --- a/host/examples/txrx_loopback_to_file.cpp +++ b/host/examples/txrx_loopback_to_file.cpp @@ -15,6 +15,7 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +#include "wavetable.hpp"  #include <uhd/types/tune_request.hpp>  #include <uhd/utils/thread_priority.hpp>  #include <uhd/utils/safe_main.hpp> @@ -31,7 +32,6 @@  #include <iostream>  #include <fstream>  #include <csignal> -#include <cmath>  namespace po = boost::program_options; @@ -61,51 +61,6 @@ std::string generate_out_filename(const std::string &base_fn, size_t n_names, si      return base_fn_fp.string();  } -/*********************************************************************** - * Waveform generators - **********************************************************************/ -static const size_t wave_table_len = 8192; - -class wave_table_class{ -public: -    wave_table_class(const std::string &wave_type, const float ampl): -        _wave_table(wave_table_len) -    { -        //compute real wave table with 1.0 amplitude -        std::vector<double> real_wave_table(wave_table_len); -        if (wave_type == "CONST"){ -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = 1.0; -        } -        else if (wave_type == "SQUARE"){ -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = (i < wave_table_len/2)? 0.0 : 1.0; -        } -        else if (wave_type == "RAMP"){ -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = 2.0*i/(wave_table_len-1) - 1.0; -        } -        else if (wave_type == "SINE"){ -            static const double tau = 2*std::acos(-1.0); -            for (size_t i = 0; i < wave_table_len; i++) -                real_wave_table[i] = std::sin((tau*i)/wave_table_len); -        } -        else throw std::runtime_error("unknown waveform type: " + wave_type); - -        //compute i and q pairs with 90% offset and scale to amplitude -        for (size_t i = 0; i < wave_table_len; i++){ -            const size_t q = (i+(3*wave_table_len)/4)%wave_table_len; -            _wave_table[i] = std::complex<float>(ampl*real_wave_table[i], ampl*real_wave_table[q]); -        } -    } - -    inline std::complex<float> operator()(const size_t index) const{ -        return _wave_table[index % wave_table_len]; -    } - -private: -    std::vector<std::complex<float> > _wave_table; -};  /***********************************************************************   * transmit_worker function diff --git a/host/examples/wavetable.hpp b/host/examples/wavetable.hpp new file mode 100644 index 000000000..d7ffc8406 --- /dev/null +++ b/host/examples/wavetable.hpp @@ -0,0 +1,66 @@ +// +// Copyright 2010-2012,2014 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 <string> +#include <cmath> +#include <complex> +#include <vector> +#include <stdexcept> + +static const size_t wave_table_len = 8192; + +class wave_table_class{ +public: +    wave_table_class(const std::string &wave_type, const float ampl): +        _wave_table(wave_table_len) +    { +        //compute real wave table with 1.0 amplitude +        std::vector<double> real_wave_table(wave_table_len); +        if (wave_type == "CONST"){ +            for (size_t i = 0; i < wave_table_len; i++) +                real_wave_table[i] = 1.0; +        } +        else if (wave_type == "SQUARE"){ +            for (size_t i = 0; i < wave_table_len; i++) +                real_wave_table[i] = (i < wave_table_len/2)? 0.0 : 1.0; +        } +        else if (wave_type == "RAMP"){ +            for (size_t i = 0; i < wave_table_len; i++) +                real_wave_table[i] = 2.0*i/(wave_table_len-1) - 1.0; +        } +        else if (wave_type == "SINE"){ +            static const double tau = 2*std::acos(-1.0); +            for (size_t i = 0; i < wave_table_len; i++) +                real_wave_table[i] = std::sin((tau*i)/wave_table_len); +        } +        else throw std::runtime_error("unknown waveform type: " + wave_type); + +        //compute i and q pairs with 90% offset and scale to amplitude +        for (size_t i = 0; i < wave_table_len; i++){ +            const size_t q = (i+(3*wave_table_len)/4)%wave_table_len; +            _wave_table[i] = std::complex<float>(ampl*real_wave_table[i], ampl*real_wave_table[q]); +        } +    } + +    inline std::complex<float> operator()(const size_t index) const{ +        return _wave_table[index % wave_table_len]; +    } + +private: +    std::vector<std::complex<float> > _wave_table; +}; + diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 619bd0787..173845fea 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2011,2014 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 @@ -56,6 +56,13 @@ typedef ptrdiff_t ssize_t;      #define UHD_DEPRECATED     __declspec(deprecated)      #define UHD_ALIGNED(x)     __declspec(align(x))      #define UHD_UNUSED(x)      x +#elif defined(__MINGW32__) +    #define UHD_EXPORT         __declspec(dllexport) +    #define UHD_IMPORT         __declspec(dllimport) +    #define UHD_INLINE         inline +    #define UHD_DEPRECATED     __declspec(deprecated) +    #define UHD_ALIGNED(x)     __declspec(align(x)) +    #define UHD_UNUSED(x)      x  #elif defined(__GNUG__) && __GNUG__ >= 4      #define UHD_EXPORT         __attribute__((visibility("default")))      #define UHD_IMPORT         __attribute__((visibility("default"))) diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 2118674c6..623c179e9 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -1,5 +1,5 @@  # -# Copyright 2010-2013 Ettus Research LLC +# Copyright 2010-2014 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 @@ -15,11 +15,11 @@  # along with this program.  If not, see <http://www.gnu.org/licenses/>.  # -  UHD_INSTALL(FILES      bounded_buffer.hpp      bounded_buffer.ipp      buffer_pool.hpp +    chdr.hpp      if_addrs.hpp      udp_constants.hpp      udp_simple.hpp diff --git a/host/include/uhd/transport/chdr.hpp b/host/include/uhd/transport/chdr.hpp new file mode 100644 index 000000000..5e8cd58a9 --- /dev/null +++ b/host/include/uhd/transport/chdr.hpp @@ -0,0 +1,113 @@ +// +// Copyright 2014 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_TRANSPORT_CHDR_HPP +#define INCLUDED_UHD_TRANSPORT_CHDR_HPP + +#include <uhd/transport/vrt_if_packet.hpp> + +namespace uhd{ namespace transport{ namespace vrt{ + +/*! \brief CVITA/CHDR related function + * + * See \ref rtp_chdr for details on the CVITA/CHDR protocol. + * + * All packers take the host format into account. Choose the _le functions + * if the transport uses little endian format (e.g. PCIe) and the _be + * functions if the transport uses big endian format (e.g. Ethernet). + * + * Note 1: All packers assume there to be enough space at the address + * provided by \p packet_buff. See also \ref vrt_pack_contract. + * + * Note 2: All these packers assume the following options without checking them: + * - `if_packet_info.link_type == LINK_TYPE_CHDR` + * - `if_packet_info.has_cid == false` + * - `if_packet_info.has_sid == true` + * - `if_packet_info.has_tsi == false` + * - `if_packet_info.has_tlr == false` + * This relaxes some of \ref vrt_pack_contract, but adds the additional + * constraint that the input data must be CHDR. + * + * In the unpacker, these values will be set accordingly. + */ +namespace chdr{ + +    //! The maximum number of 64-bit words in a CVITA header +    static const size_t max_if_hdr_words64 = 2; // CHDR + tsf (fractional timestamp) + +    /*! +     * Pack a CHDR header from metadata (big endian format). +     * +     * See \ref vrt_pack_contract, but `link_type` is assumed to be +     * `LINK_TYPE_CHDR`. +     * +     * \param packet_buff memory to write the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_pack_be( +        boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +    /*! +     * Unpack a CHDR header to metadata (big endian format). +     * +     * See \ref vrt_unpack_contract, but `link_type` is assumed to be +     * `LINK_TYPE_CHDR`. +     * +     * \param packet_buff memory to read the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_unpack_be( +        const boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +    /*! +     * Pack a CHDR header from metadata (little endian format). +     * +     * See \ref vrt_pack_contract, but `link_type` is assumed to be +     * `LINK_TYPE_CHDR`. +     * +     * \param packet_buff memory to write the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_pack_le( +        boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +    /*! +     * Unpack a CHDR header to metadata (little endian format). +     * +     * See \ref vrt_unpack_contract, but `link_type` is assumed to be +     * `LINK_TYPE_CHDR`. +     * +     * \param packet_buff memory to read the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_unpack_le( +        const boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +} //namespace chdr + +}}} //namespace uhd::transport::vrt + +#endif /* INCLUDED_UHD_TRANSPORT_CHDR_HPP */ + diff --git a/host/include/uhd/transport/nirio/nirio_driver_iface.h b/host/include/uhd/transport/nirio/nirio_driver_iface.h index 83afd816a..3e0e56a7f 100644 --- a/host/include/uhd/transport/nirio/nirio_driver_iface.h +++ b/host/include/uhd/transport/nirio/nirio_driver_iface.h @@ -24,9 +24,9 @@  #include <uhd/transport/nirio/status.h>  #include <uhd/config.hpp>  #if defined(UHD_PLATFORM_WIN32) -    #include <Windows.h> +    #include <windows.h>      #pragma warning(disable:4201)  // nonstandard extension used : nameless struct/union -        #include <WinIoCtl.h> +        #include <winioctl.h>      #pragma warning(default:4201)  #elif !defined(UHD_PLATFORM_LINUX)      #include <IOKit/IOKitLib.h> diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index fdea9e2be..bf122f549 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -41,6 +41,7 @@ namespace uhd { namespace transport {  class UHD_API usb_device_handle : boost::noncopyable {  public:      typedef boost::shared_ptr<usb_device_handle> sptr; +    typedef std::pair<boost::uint16_t, boost::uint16_t> vid_pid_pair_t;      /*!       * Return the device's serial number @@ -83,6 +84,8 @@ public:       * \return a vector of USB device handles that match vid and pid       */      static std::vector<usb_device_handle::sptr> get_device_list(boost::uint16_t vid, boost::uint16_t pid); +    static std::vector<usb_device_handle::sptr> get_device_list(const std::vector<usb_device_handle::vid_pid_pair_t>& vid_pid_pair_list); +  }; //namespace usb diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp index d16892281..8bc65cdf1 100644 --- a/host/include/uhd/transport/vrt_if_packet.hpp +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2013 Ettus Research LLC +// Copyright 2010-2014 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 @@ -52,9 +52,18 @@ namespace vrt{          //packet type          enum packet_type_t          { +            // VRT language:              PACKET_TYPE_DATA      = 0x0,              PACKET_TYPE_IF_EXT    = 0x1,              PACKET_TYPE_CONTEXT   = 0x2, //extension context: has_sid = true + +            // CVITA language: +            //PACKET_TYPE_DATA      = 0x0, // Data +            PACKET_TYPE_FC        = 0x1, // Flow control +            PACKET_TYPE_ACK       = 0x1, // Flow control (ack) +            PACKET_TYPE_CMD       = 0x2, // Command +            PACKET_TYPE_RESP      = 0x3, // Command response +            PACKET_TYPE_ERROR     = 0x3, // Command response: Error (the EOB bit is raised in this case)          } packet_type;          //size fields @@ -65,18 +74,46 @@ namespace vrt{          //header fields          size_t packet_count; +        //! Asserted for start- or end-of-burst          bool sob, eob; +        //! This is asserted for command responses that are errors (CHDR only) +        bool error;          //optional fields +        //! Stream ID (SID). See uhd::sid_t          bool has_sid; boost::uint32_t sid; +        //! Class ID.          bool has_cid; boost::uint64_t cid; +        //! Integer timestamp          bool has_tsi; boost::uint32_t tsi; +        //! Fractional timestamp          bool has_tsf; boost::uint64_t tsf; +        //! Trailer          bool has_tlr; boost::uint32_t tlr;      };      /*!       * Pack a vrt header from metadata (big endian format). +     * +     * \section vrt_pack_contract Packing contract +     * +     * \subsection Requirements: +     * - packet_buff points to a valid address space with enough space to write +     *   the entire buffer, regardless of its length. At the very least, it must +     *   be able to hold an entire header. +     * - `if_packet_info` has the following members set to correct values: +     *   - `has_*` members all set accordingly +     *   - For every true `has_*` member, the corresponding variable holds a valid +     *     value (e.g. if `has_sid` is true, `sid` contains a valid SID) +     *   - `num_payload_bytes` and `num_payload_words32` are both set to the correct values +     * +     * \subsection Result: +     * - `packet_buff` now points to a valid header that can be sent over the transport +     *   without further modification +     * - The following members on `if_packet_info` are set: +     *   - `num_header_words32` +     *   - `num_packet_words32` +     *       * \param packet_buff memory to write the packed vrt header       * \param if_packet_info the if packet info (read/write)       */ @@ -87,6 +124,34 @@ namespace vrt{      /*!       * Unpack a vrt header to metadata (big endian format). +     * +     * \section vrt_unpack_contract Unpacking contract +     * +     * \subsection Requirements +     * - `packet_buff` points to a readable address space with a +     *   CHDR packet, starting at the header. `packet_buff[0]` *must* always +     *   point to a valid first word of the header. This implies that num_packet_words32 +     *   must be at least 1. +     * - `if_packet_info` has the following members set to correct values: +     *   - `num_packet_words32`. This means all values `packet_buff[0]` +     *     through `packet_buff[if_packet_info.num_packet_words32-1]` are +     *     readable words from this packet. +     *   - `link_type` +     * +     * \subsection Result +     * - `if_packet_info` now has the following values set to correct values: +     *   - `packet_type` +     *   - `num_payload_bytes` +     *   - `num_payload_words32` +     *   - `num_header_words32` +     *   - `has_*` +     *   - `sob`, `eob`, `error`, `cid`, `sid` (if applicable) +     *   - `tsf`, `tsi` (if applicable) +     * +     * \subsection Exceptions +     * - If the header is invalid, but the requirements are still met, +     *   will throw a uhd::value_error. +     *       * \param packet_buff memory to read the packed vrt header       * \param if_packet_info the if packet info (read/write)       */ @@ -97,6 +162,9 @@ namespace vrt{      /*!       * Pack a vrt header from metadata (little endian format). +     * +     * See \ref vrt_pack_contract. +     *       * \param packet_buff memory to write the packed vrt header       * \param if_packet_info the if packet info (read/write)       */ @@ -107,6 +175,9 @@ namespace vrt{      /*!       * Unpack a vrt header to metadata (little endian format). +     * +     * See \ref vrt_unpack_contract. +     *       * \param packet_buff memory to read the packed vrt header       * \param if_packet_info the if packet info (read/write)       */ @@ -124,6 +195,7 @@ namespace vrt{          num_packet_words32(0),          packet_count(0),          sob(false), eob(false), +        error(false),          has_sid(false), sid(0),          has_cid(false), cid(0),          has_tsi(false), tsi(0), diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 334f1b41b..444ff71ae 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -21,6 +21,7 @@ UHD_INSTALL(FILES      device_addr.hpp      dict.ipp      dict.hpp +    direction.hpp      io_type.hpp      mac_addr.hpp      metadata.hpp @@ -29,6 +30,7 @@ UHD_INSTALL(FILES      ref_vector.hpp      sensors.hpp      serial.hpp +    sid.hpp      stream_cmd.hpp      time_spec.hpp      tune_request.hpp diff --git a/host/include/uhd/types/direction.hpp b/host/include/uhd/types/direction.hpp new file mode 100644 index 000000000..62fbde3f0 --- /dev/null +++ b/host/include/uhd/types/direction.hpp @@ -0,0 +1,34 @@ +// +// Copyright 2014 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_DIRECTION_HPP +#define INCLUDED_UHD_TYPES_DIRECTION_HPP + +namespace uhd { + +    enum direction_t { +        //! Receive +        RX_DIRECTION, +        //! Transmit +        TX_DIRECTION, +        //! Duplex +        DX_DIRECTION +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DIRECTION_HPP */ diff --git a/host/include/uhd/types/sid.hpp b/host/include/uhd/types/sid.hpp new file mode 100644 index 000000000..95034c7a5 --- /dev/null +++ b/host/include/uhd/types/sid.hpp @@ -0,0 +1,238 @@ +// +// Copyright 2014 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_SID_HPP +#define INCLUDED_UHD_TYPES_SID_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <boost/shared_ptr.hpp> +#include <iostream> + +namespace uhd { +    /*! +     * \brief Represents a stream ID (SID). +     * +     * A stream ID (SID) is an identifier for data. +     * It is a 32-Bit value which consistst of 16 Bits +     * for the source address and 16 Bits for the destination +     * address. +     * Every address is split into two parts: The _address_, which +     * identifies the device used, and the _endpoint_, which identifies +     * a specific object inside the given device (e.g., a block). +     * *Note:* In the case where there are several crossbars on a single +     * device, each crossbar gets its own address. +     * Both address and endpoint are 8 bits in length. If a 16-bit address +     * is required, we use the combination of the 8-bit address and the 8-bit +     * endpoint. +     * +     * \section sid_str_repr String Representation +     * +     * The string representation of a SID is of the form +     * +     *     2.3>0.6 +     * +     * The '>' symbol shows the direction, so in this case, +     * data is flowing from address 2.3 to 0.6. +     * +     * As a convention, ':' is used instead of '.' when giving the +     * SID in hexadecimal numbers, and two characters are used for each +     * address part. As an example, the following two SIDs are identical: +     * +     *     2.3>0.16 (decimal) +     *     02:03>00:10 (hexadecimal) +     * +     * The format is: +     *     SRC_ADDRESS.SRC_ENDPOINT>DST_ADDRESS.DST_ENDPOINT +     * +     * +     * \section sid_block_ports Block Ports +     * +     * In the special case where a block on a crossbar is addressed, the +     * endpoint is further split up into two parts of four bits each: The +     * first four bits specify the port number on the crossbar, whereas the +     * lower four bits represent the *block port*. As an example, consider +     * the following SID, given in hexadecimal: +     * +     *    00:10>02:A1 +     * +     * In this example, assume data is flowing from the host computer to an +     * X300. The crossbar address is 02. The endpoint is A1, which means we +     * are accessing a block on crossbar port A (the tenth port), and are addressing +     * block port 1. +     * +     */ +    class UHD_API sid_t +    { +    public: +        //! Create an unset SID +        sid_t(); +        //! Create a sid_t object from a 32-Bit SID value +        sid_t(boost::uint32_t sid); +        //! Create a sid_t object from its four components +        sid_t(boost::uint8_t src_addr, boost::uint8_t src_ep, boost::uint8_t dst_addr, boost::uint8_t dst_ep); +        //! Convert a string representation of a SID into its numerical representation +        sid_t(const std::string &); + +        //! Return a decimal string representation of the SID. +        std::string to_pp_string() const; +        //! Return a hexadecimal string representation of the SID. +        std::string to_pp_string_hex() const; + +        //! Returns true if this actually holds a valid SID +        bool is_set() const { return _set; }; + +        // Getters +        // +        //! Alias for get_sid() +        UHD_INLINE boost::uint32_t get() const { return get_sid(); }; +        //! Returns a 32-Bit representation of the SID if set, or zero otherwise. +        UHD_INLINE boost::uint32_t get_sid() const { return _set ? _sid : 0; }; +        //! Return the 16-bit source address of this SID +        UHD_INLINE boost::uint32_t get_src() const { +            return (_sid >> 16) & 0xFFFF; +        } +        //! Return the 16-bit destination address of this SID +        UHD_INLINE boost::uint32_t get_dst() const { +            return _sid & 0xFFFF; +        } +        //! Return 8-bit address of the source +        UHD_INLINE boost::uint32_t get_src_addr() const { +            return (get_src() >> 8) & 0xFF; +        } +        //! Return endpoint of the source +        UHD_INLINE boost::uint32_t get_src_endpoint() const { +            return get_src() & 0xFF; +        } +        //! Return crossbar port of the source +        UHD_INLINE boost::uint32_t get_src_xbarport() const { +            return (get_src_endpoint() >> 4) & 0xF; +        } +        //! Return block port of the source +        UHD_INLINE boost::uint32_t get_src_blockport() const { +            return (get_src_endpoint()) & 0xF; +        } +        //! Return 8-bit address of the destination +        UHD_INLINE boost::uint32_t get_dst_addr() const { +            return (get_dst() >> 8) & 0xFF; +        } +        //! Return endpoint of the destination +        UHD_INLINE boost::uint32_t get_dst_endpoint() const { +            return get_dst() & 0xFF; +        } +        //! Return crossbar port of the source +        UHD_INLINE boost::uint32_t get_dst_xbarport() const { +            return (get_dst_endpoint() >> 4) & 0xF; +        } +        //! Return block port of the source +        UHD_INLINE boost::uint32_t get_dst_blockport() const { +            return (get_dst_endpoint()) & 0xF; +        } + +        // Setters + +        //! Alias for set_sid() +        void set(boost::uint32_t new_sid) { set_sid(new_sid); }; +        //! Convert a string representation of a SID into a numerical one +        // Throws uhd::value_error if the string is not a valid SID +        // representation. +        void set_from_str(const std::string &); +        void set_sid(boost::uint32_t new_sid); +        //! Set the source address of this SID +        //  (the first 16 Bits) +        void set_src(boost::uint32_t new_addr); +        //! Set the destination address of this SID +        //  (the last 16 Bits) +        void set_dst(boost::uint32_t new_addr); +        void set_src_addr(boost::uint32_t new_addr); +        void set_src_endpoint(boost::uint32_t new_addr); +        void set_dst_addr(boost::uint32_t new_addr); +        void set_dst_endpoint(boost::uint32_t new_addr); +        void set_dst_xbarport(boost::uint32_t new_xbarport); +        void set_dst_blockport(boost::uint32_t new_blockport); + +        // Manipulators + +        //! Swaps dst and src address and returns the new SID. +        sid_t reversed(); + +        //! Swaps dst and src in-place. +        void reverse(); + +        // Overloaded operators + +        sid_t operator = (boost::uint32_t new_sid) { +            set_sid(new_sid); +            return *this; +        } + +        sid_t operator = (sid_t &sid) { +            set_sid(sid.get_sid()); +            return *this; +        } + +        sid_t operator = (const std::string &sid_str) { +            set_from_str(sid_str); +            return *this; +        } + +        bool operator == (const sid_t &sid) const { +            return (not _set and not sid.is_set()) or (_sid == sid.get_sid()); +        } + +        bool operator == (boost::uint32_t sid) const { +            return _set and _sid == sid; +        } + +        bool operator == (const std::string &sid_str) const { +            sid_t rhs(sid_str); +            return *this == rhs; +        } + +        // overloaded type casts are tricky, but for now we'll need them +        // for backward compatibility. consider them deprecated. + +        //! If the SID is not set, always returns zero. +        //  Use is_set() to check if the return value is valid. +        operator boost::uint32_t() const { +            return get(); +        } + +        operator bool() const { +            return _set; +        } + +    private: +        boost::uint32_t _sid; +        bool _set; +    }; + +    //! Stream output operator. Honors std::ios::hex. +    UHD_INLINE std::ostream& operator<< (std::ostream& out, const sid_t &sid) { +        std::ios_base::fmtflags ff = out.flags(); +        if (ff & std::ios::hex) { +            out << sid.to_pp_string_hex(); +        } else { +            out << sid.to_pp_string(); +        } +        return out; +    } + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_SID_HPP */ +// vim: sw=4 et: diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 6fd22ff23..2362ebcd7 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -155,6 +155,11 @@ public:       * If the specified rate is not available, this method will throw.       * On other devices, this method notifies the software of the rate,       * but requires the the user has made the necessary hardware change. +     * +     * If the device has an 'auto clock rate' setting (e.g. B200, see also +     * \ref b200_auto_mcr), this will get disabled and the clock rate will be +     * fixed to \p rate. +     *       * \param rate the new master clock rate in Hz       * \param mboard the motherboard index 0 to M-1       */ diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index c308c9cde..05f6892d2 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -25,7 +25,6 @@ UHD_INSTALL(FILES      cast.hpp      csv.hpp      gain_group.hpp -    images.hpp      log.hpp      math.hpp      msg.hpp diff --git a/host/include/uhd/utils/images.hpp b/host/include/uhd/utils/images.hpp deleted file mode 100644 index a0934fb08..000000000 --- a/host/include/uhd/utils/images.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2010,2012 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_UHD_UTILS_IMAGES_HPP -#define INCLUDED_UHD_UTILS_IMAGES_HPP - -#include <uhd/config.hpp> -#include <string> - -namespace uhd{ - -    /*! -     * Search for an image in the system image paths: -     * Search compiled-in paths and environment variable paths -     * for a specific image file with the provided file name. -     * \param image_name the name of the file -     * \return the full system path to the file -     * \throw exception if the image was not found -     */ -    UHD_API std::string find_image_path(const std::string &image_name); - -    /*! -     * Search for the location of the UHD Images Downloader script. -     * \return the full system path to uhd_images_downloader.py -     */ - -    UHD_API std::string find_images_downloader(void); - -    /*! -     * Return the error string for recommending using the UHD Images Downloader. -     * String depends on OS. -     * \return the message suggesting the use of uhd_images_downloader.py -     */ - -    UHD_API std::string print_images_error(void); - -} //namespace uhd - -#endif /* INCLUDED_UHD_UTILS_IMAGES_HPP */ diff --git a/host/include/uhd/utils/math.hpp b/host/include/uhd/utils/math.hpp index 21825c3dc..275a94f72 100644 --- a/host/include/uhd/utils/math.hpp +++ b/host/include/uhd/utils/math.hpp @@ -18,11 +18,11 @@  #ifndef INCLUDED_UHD_UTILS_MATH_HPP  #define INCLUDED_UHD_UTILS_MATH_HPP +#include <cmath>  #include <uhd/config.hpp>  #include <boost/cstdint.hpp>  #include <boost/numeric/conversion/bounds.hpp> -  namespace uhd {  /*! @@ -237,6 +237,16 @@ namespace fp_compare {                  == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));      } +    //! Portable log2() +    template <typename float_t> UHD_INLINE +    float_t log2(float_t x) +    { +        // C++11 defines std::log2(), when that's universally supported +        // we can switch over. +        return std::log(x) / std::log(float_t(2)); +    } + +  } // namespace math  } // namespace uhd diff --git a/host/include/uhd/utils/paths.hpp b/host/include/uhd/utils/paths.hpp index e0f455e92..c1f32ba61 100644 --- a/host/include/uhd/utils/paths.hpp +++ b/host/include/uhd/utils/paths.hpp @@ -32,6 +32,31 @@ namespace uhd{      //! Get a string representing the system's pkg directory      UHD_API std::string get_pkg_path(void); +    /*! +     * Search for an image in the system image paths: +     * Search compiled-in paths and environment variable paths +     * for a specific image file with the provided file name. +     * \param image_name the name of the file +     * \return the full system path to the file +     * \throw exception if the image was not found +     */ +    UHD_API std::string find_image_path(const std::string &image_name); + +    /*! +     * Search for the location of a particular UHD utility. +     * The utility must be installed in the `uhd/utils` directory. +     * \param the name of the utility to search for +     * \return the full system path to @param +     */ +    UHD_API std::string find_utility(std::string name); + +    /*! +     * Return an error string recommending the user run the utility. +     * The error string will include the full path to the utility to run. +     * \return the message suggesting the use of the named utility. +     */ +    UHD_API std::string print_utility_error(std::string name); +  } //namespace uhd  #endif /* INCLUDED_UHD_UTILS_PATHS_HPP */ diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 5920f3d78..9ec8a5c0b 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -129,6 +129,7 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/if_addrs.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/udp_simple.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/nirio_zero_copy.cpp +    ${CMAKE_CURRENT_SOURCE_DIR}/chdr.cpp  )  # Verbose Debug output for send/recv diff --git a/host/lib/transport/chdr.cpp b/host/lib/transport/chdr.cpp new file mode 100644 index 000000000..47ac961b9 --- /dev/null +++ b/host/lib/transport/chdr.cpp @@ -0,0 +1,182 @@ +// +// Copyright 2014 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/transport/chdr.hpp> +#include <uhd/utils/byteswap.hpp> +#include <uhd/exception.hpp> + +//define the endian macros to convert integers +#ifdef BOOST_BIG_ENDIAN +    #define BE_MACRO(x) (x) +    #define LE_MACRO(x) uhd::byteswap(x) +#else +    #define BE_MACRO(x) uhd::byteswap(x) +    #define LE_MACRO(x) (x) +#endif + +using namespace uhd::transport::vrt; + +static const boost::uint32_t HDR_FLAG_TSF = (1 << 29); +static const boost::uint32_t HDR_FLAG_EOB = (1 << 28); +static const boost::uint32_t HDR_FLAG_ERROR = (1 << 28); + +/***************************************************************************/ +/* Packing                                                                 */ +/***************************************************************************/ +/*! Translate the contents of \p if_packet_info into a 32-Bit word and return it. + */ +UHD_INLINE boost::uint32_t _hdr_pack_chdr( +        if_packet_info_t &if_packet_info +) { +    // Set fields in if_packet_info +    if_packet_info.num_header_words32 = 2 + (if_packet_info.has_tsf ? 2 : 0); +    if_packet_info.num_packet_words32 = +            if_packet_info.num_header_words32 + +            if_packet_info.num_payload_words32; + +    boost::uint16_t pkt_length = +        if_packet_info.num_payload_bytes + (4 * if_packet_info.num_header_words32); +    boost::uint32_t chdr = 0 +        // 2 Bits: Packet type +        | (if_packet_info.packet_type << 30) +        // 1 Bit: Has time +        | (if_packet_info.has_tsf ? HDR_FLAG_TSF : 0) +        // 1 Bit: EOB or Error +        | ((if_packet_info.eob or if_packet_info.error) ? HDR_FLAG_EOB : 0) +        // 12 Bits: Sequence number +        | ((if_packet_info.packet_count & 0xFFF) << 16) +        // 16 Bits: Total packet length +        | pkt_length; +    return chdr; +} + +void chdr::if_hdr_pack_be( +        boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +) { +    // Write header and update if_packet_info +    packet_buff[0] = BE_MACRO(_hdr_pack_chdr(if_packet_info)); + +    // Write SID +    packet_buff[1] = BE_MACRO(if_packet_info.sid); + +    // Write time +    if (if_packet_info.has_tsf) { +        packet_buff[2] = BE_MACRO(boost::uint32_t(if_packet_info.tsf >> 32)); +        packet_buff[3] = BE_MACRO(boost::uint32_t(if_packet_info.tsf >> 0)); +    } +} + +void chdr::if_hdr_pack_le( +        boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +) { +    // Write header and update if_packet_info +    packet_buff[0] = LE_MACRO(_hdr_pack_chdr(if_packet_info)); + +    // Write SID +    packet_buff[1] = LE_MACRO(if_packet_info.sid); + +    // Write time +    if (if_packet_info.has_tsf) { +        packet_buff[2] = LE_MACRO(boost::uint32_t(if_packet_info.tsf >> 32)); +        packet_buff[3] = LE_MACRO(boost::uint32_t(if_packet_info.tsf >> 0)); +    } +} + + +/***************************************************************************/ +/* Unpacking                                                               */ +/***************************************************************************/ +UHD_INLINE void _hdr_unpack_chdr( +        const boost::uint32_t chdr, +        if_packet_info_t &if_packet_info +) { +    // Set constant members +    if_packet_info.link_type = if_packet_info_t::LINK_TYPE_CHDR; +    if_packet_info.has_cid = false; +    if_packet_info.has_sid = true; +    if_packet_info.has_tsi = false; +    if_packet_info.has_tlr = false; +    if_packet_info.sob = false; + +    // Set configurable members +    if_packet_info.has_tsf = bool(chdr & HDR_FLAG_TSF); +    if_packet_info.packet_type = if_packet_info_t::packet_type_t((chdr >> 30) & 0x3); +    if_packet_info.eob = (if_packet_info.packet_type == if_packet_info_t::PACKET_TYPE_DATA) +                         && bool(chdr & HDR_FLAG_EOB); +    if_packet_info.error = (if_packet_info.packet_type == if_packet_info_t::PACKET_TYPE_RESP) +                         && bool(chdr & HDR_FLAG_ERROR); +    if_packet_info.packet_count = (chdr >> 16) & 0xFFF; + +    // Set packet length variables +    if (if_packet_info.has_tsf) { +        if_packet_info.num_header_words32 = 4; +    } else { +        if_packet_info.num_header_words32 = 2; +    } +    size_t pkt_size_bytes = (chdr & 0xFFFF); +    size_t pkt_size_word32 = (pkt_size_bytes / 4) + ((pkt_size_bytes % 4) ? 1 : 0); +    // Check lengths match: +    if (pkt_size_word32 < if_packet_info.num_header_words32) { +        throw uhd::value_error("Bad CHDR or invalid packet length"); +    } +    if (if_packet_info.num_packet_words32 < pkt_size_word32) { +        throw uhd::value_error("Bad CHDR or packet fragment"); +    } +    if_packet_info.num_payload_bytes = pkt_size_bytes - (4 * if_packet_info.num_header_words32); +    if_packet_info.num_payload_words32 = pkt_size_word32 - if_packet_info.num_header_words32; +} + +void chdr::if_hdr_unpack_be( +        const boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +) { +    // Read header and update if_packet_info +    boost::uint32_t chdr = BE_MACRO(packet_buff[0]); +    _hdr_unpack_chdr(chdr, if_packet_info); + +    // Read SID +    if_packet_info.sid = BE_MACRO(packet_buff[1]); + +    // Read time (has_tsf was updated earlier) +    if (if_packet_info.has_tsf) { +        if_packet_info.tsf = 0 +            | boost::uint64_t(BE_MACRO(packet_buff[2])) << 32 +            | BE_MACRO(packet_buff[3]); +    } +} + +void chdr::if_hdr_unpack_le( +        const boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +) { +    // Read header and update if_packet_info +    boost::uint32_t chdr = LE_MACRO(packet_buff[0]); +    _hdr_unpack_chdr(chdr, if_packet_info); + +    // Read SID +    if_packet_info.sid = LE_MACRO(packet_buff[1]); + +    // Read time (has_tsf was updated earlier) +    if (if_packet_info.has_tsf) { +        if_packet_info.tsf = 0 +            | boost::uint64_t(LE_MACRO(packet_buff[2])) << 32 +            | LE_MACRO(packet_buff[3]); +    } +} + diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index ee4e20adb..18acb1fdc 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -343,15 +343,21 @@ libusb::special_handle::sptr libusb::special_handle::make(device::sptr dev){  std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list(      boost::uint16_t vid, boost::uint16_t pid  ){ -    std::vector<usb_device_handle::sptr> handles; +    return usb_device_handle::get_device_list(std::vector<usb_device_handle::vid_pid_pair_t>(1,usb_device_handle::vid_pid_pair_t(vid,pid))); +} +std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list(const std::vector<usb_device_handle::vid_pid_pair_t>& vid_pid_pair_list) +{ +    std::vector<usb_device_handle::sptr> handles;      libusb::device_list::sptr dev_list = libusb::device_list::make(); -    for (size_t i = 0; i < dev_list->size(); i++){ -        usb_device_handle::sptr handle = libusb::special_handle::make(dev_list->at(i)); -        if (handle->get_vendor_id() == vid and handle->get_product_id() == pid){ -            handles.push_back(handle); -        } +    for(size_t iter = 0; iter < vid_pid_pair_list.size(); ++iter) +    { +       for (size_t i = 0; i < dev_list->size(); i++){ +           usb_device_handle::sptr handle = libusb::special_handle::make(dev_list->at(i)); +           if (handle->get_vendor_id() == vid_pid_pair_list[iter].first and handle->get_product_id() == vid_pid_pair_list[iter].second){ +               handles.push_back(handle); +           } +       }      } -      return handles;  } diff --git a/host/lib/transport/nirio/nifpga_lvbitx.cpp b/host/lib/transport/nirio/nifpga_lvbitx.cpp index b87d87a8d..189037163 100644 --- a/host/lib/transport/nirio/nifpga_lvbitx.cpp +++ b/host/lib/transport/nirio/nifpga_lvbitx.cpp @@ -115,7 +115,7 @@ std::string nifpga_lvbitx::_get_fpga_images_dir(const std::string search_paths)      // directories searched for a LVBITX image.      //      char* uhd_images_dir; -#ifdef UHD_PLATFORM_WIN32 +#if defined(UHD_PLATFORM_WIN32) && !defined(__MINGW32__) // Some versions of MinGW don't expose _dupenv_s      size_t len;      errno_t err = _dupenv_s(&uhd_images_dir, &len, "UHD_IMAGES_DIR");      if(not err and uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir)); diff --git a/host/lib/transport/nirio/rpc/rpc_client.cpp b/host/lib/transport/nirio/rpc/rpc_client.cpp index cf8e9c1a9..48f47cfae 100644 --- a/host/lib/transport/nirio/rpc/rpc_client.cpp +++ b/host/lib/transport/nirio/rpc/rpc_client.cpp @@ -52,7 +52,7 @@ rpc_client::rpc_client (          //- address_configured: Only return addresses if a non-loopback address is configured for the system.          //- numeric_host: No name resolution should be attempted for host          //- numeric_service: No name resolution should be attempted for service -        tcp::resolver::query::flags query_flags; +        tcp::resolver::query::flags query_flags = tcp::resolver::query::passive;          tcp::resolver::query query(tcp::v4(), server, port, query_flags);          tcp::resolver::iterator iterator = resolver.resolve(query); diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt index f19043c1e..853da3fe2 100644 --- a/host/lib/types/CMakeLists.txt +++ b/host/lib/types/CMakeLists.txt @@ -86,6 +86,7 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/sensors.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/serial.cpp +    ${CMAKE_CURRENT_SOURCE_DIR}/sid.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/time_spec.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/tune.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp diff --git a/host/lib/types/sid.cpp b/host/lib/types/sid.cpp new file mode 100644 index 000000000..2fc3781cf --- /dev/null +++ b/host/lib/types/sid.cpp @@ -0,0 +1,153 @@ +// +// Copyright 2014 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 <boost/format.hpp> +#include <boost/regex.hpp> +#include <boost/lexical_cast.hpp> +#include <uhd/exception.hpp> +#include <uhd/types/sid.hpp> +#include <uhd/utils/cast.hpp> + +using namespace uhd; + +sid_t::sid_t() +    : _sid(0x0000), _set(false) +{ +} + +sid_t::sid_t(boost::uint32_t sid) +    : _sid(sid), _set(true) +{ +} + +sid_t::sid_t(boost::uint8_t src_addr, boost::uint8_t src_ep, boost::uint8_t dst_addr, boost::uint8_t dst_ep) +    :  _sid(0x0000), _set(true) +{ +    set_src_addr(src_addr); +    set_src_endpoint(src_ep); +    set_dst_addr(dst_addr); +    set_dst_endpoint(dst_ep); +} + +sid_t::sid_t(const std::string &sid_str) +    : _sid(0x0000), _set(false) +{ +    set_from_str(sid_str); +} + +std::string sid_t::to_pp_string() const +{ +    if (not _set) { +        return "x.x>x.x"; +    } +    return str(boost::format("%d.%d>%d.%d") +        % get_src_addr() +        % get_src_endpoint() +        % get_dst_addr() +        % get_dst_endpoint() +    ); +} + +std::string sid_t::to_pp_string_hex() const +{ +    if (not _set) { +        return "xx:xx>xx:xx"; +    } +    return str(boost::format("%02x:%02x>%02x:%02x") +        % get_src_addr() +        % get_src_endpoint() +        % get_dst_addr() +        % get_dst_endpoint() +    ); +} + + +void sid_t::set_sid(boost::uint32_t new_sid) +{ +    _set = true; +    _sid = new_sid; +} + +void sid_t::set_from_str(const std::string &sid_str) +{ +    const std::string dec_regex = "(\\d{1,3})\\.(\\d{1,3})[.:/><](\\d{1,3})\\.(\\d{1,3})"; +    const std::string hex_regex = "([[:xdigit:]]{2}):([[:xdigit:]]{2})[.:/><]([[:xdigit:]]{2}):([[:xdigit:]]{2})"; + +    boost::cmatch matches; +    if (boost::regex_match(sid_str.c_str(), matches, boost::regex(dec_regex))) { +        set_src_addr(boost::lexical_cast<size_t>(matches[1])); +        set_src_endpoint(boost::lexical_cast<size_t>(matches[2])); +        set_dst_addr(boost::lexical_cast<size_t>(matches[3])); +        set_dst_endpoint(boost::lexical_cast<size_t>(matches[4])); +        return; +    } + +    if (boost::regex_match(sid_str.c_str(), matches, boost::regex(hex_regex))) { +        set_src_addr(uhd::cast::hexstr_cast<size_t>(matches[1])); +        set_src_endpoint(uhd::cast::hexstr_cast<size_t>(matches[2])); +        set_dst_addr(uhd::cast::hexstr_cast<size_t>(matches[3])); +        set_dst_endpoint(uhd::cast::hexstr_cast<size_t>(matches[4])); +        return; +    } + +    throw uhd::value_error(str(boost::format("Invalid SID representation: %s") % sid_str)); +} + +void sid_t::set_src(boost::uint32_t new_addr) { +    set_sid((_sid & 0x0000FFFF) | ((new_addr & 0xFFFF) << 16)); +} + +void sid_t::set_dst(boost::uint32_t new_addr) { +    set_sid((_sid & 0xFFFF0000) | (new_addr & 0xFFFF)); +} + +void sid_t::set_src_addr(boost::uint32_t new_addr) { +    set_sid((_sid & 0x00FFFFFF) | ((new_addr & 0xFF) << 24)); +} + +void sid_t::set_src_endpoint(boost::uint32_t new_addr) { +    set_sid((_sid & 0xFF00FFFF) | ((new_addr & 0xFF) << 16)); +} + +void sid_t::set_dst_addr(boost::uint32_t new_addr) { +    set_sid((_sid & 0xFFFF00FF) | ((new_addr & 0xFF) << 8)); +} + +void sid_t::set_dst_endpoint(boost::uint32_t new_addr) { +    set_sid((_sid & 0xFFFFFF00) | ((new_addr & 0xFF) << 0)); +} + +void sid_t::set_dst_xbarport(boost::uint32_t new_xbarport) +{ +    set_sid((_sid & 0xFFFFFF0F) | ((new_xbarport & 0xF) << 4)); +} + +void sid_t::set_dst_blockport(boost::uint32_t new_blockport) +{ +    set_sid((_sid & 0xFFFFFFF0) | ((new_blockport & 0xF) << 0)); +} + +sid_t sid_t::reversed() +{ +    return sid_t((get_dst() << 16) | get_src()); +} + +void sid_t::reverse() +{ +    set_sid((get_dst() << 16) | get_src()); +} + diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 24a87a3c8..c4279913c 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -23,7 +23,7 @@  #include <uhd/utils/cast.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <boost/format.hpp>  #include <boost/assign/list_of.hpp> @@ -82,7 +82,7 @@ static device_addrs_t b100_find(const device_addr_t &hint)              b100_fw_image = find_image_path(hint.get("fw", B100_FW_FILE_NAME));          }          catch(...){ -            UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_images_error(); +            UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_utility_error("uhd_images_downloader.py");              return b100_addrs;          }          UHD_LOG << "the firmware image: " << b100_fw_image << std::endl; @@ -532,10 +532,10 @@ void b100_impl::check_fw_compat(void){      );      if (fw_compat_num != B100_FW_COMPAT_NUM){          throw uhd::runtime_error(str(boost::format( -            "Expected firmware compatibility number 0x%x, but got 0x%x:\n" +            "Expected firmware compatibility number %d, but got %d:\n"              "The firmware build is not compatible with the host code build.\n"              "%s" -        ) % B100_FW_COMPAT_NUM % fw_compat_num % print_images_error())); +        ) % int(B100_FW_COMPAT_NUM) % fw_compat_num % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fw_version").set(str(boost::format("%u.0") % fw_compat_num));  } @@ -552,7 +552,7 @@ void b100_impl::check_fpga_compat(void){              "Expected FPGA compatibility number %d, but got %d:\n"              "The FPGA build is not compatible with the host code build."              "%s" -        ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_images_error())); +        ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor));  } diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 59ea2202e..dbca543be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -46,7 +46,7 @@  static const double          B100_LINK_RATE_BPS = 256e6/5; //pratical link rate (< 480 Mbps)  static const std::string     B100_FW_FILE_NAME = "usrp_b100_fw.ihx";  static const std::string     B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin"; -static const boost::uint16_t B100_FW_COMPAT_NUM = 0x04; +static const boost::uint16_t B100_FW_COMPAT_NUM = 4;  static const boost::uint16_t B100_FPGA_COMPAT_NUM = 11;  static const boost::uint32_t B100_RX_SID_BASE = 30;  static const boost::uint32_t B100_TX_ASYNC_SID = 10; diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 83adfdd64..1821865d3 100644 --- a/host/lib/usrp/b200/b200_iface.hpp +++ b/host/lib/usrp/b200/b200_iface.hpp @@ -26,7 +26,10 @@  #include "ad9361_ctrl.hpp"  const static boost::uint16_t B200_VENDOR_ID  = 0x2500; +const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923;  const static boost::uint16_t B200_PRODUCT_ID = 0x0020; +const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; +const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814;  const static boost::uint16_t FX3_VID = 0x04b4;  const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3;  const static boost::uint16_t FX3_REENUM_PID = 0x00f0; diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index aa309e7eb..1523f1858 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -22,7 +22,7 @@  #include <uhd/utils/cast.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <uhd/usrp/dboard_eeprom.hpp>  #include <boost/format.hpp> @@ -87,14 +87,16 @@ static device_addrs_t b200_find(const device_addr_t &hint)      //since an address and resource is intended for a different, non-USB, device.      if (hint.has_key("addr") || hint.has_key("resource")) return b200_addrs; -    boost::uint16_t vid, pid; +    size_t found = 0; +    std::vector<usb_device_handle::vid_pid_pair_t> vid_pid_pair_list;//vid pid pair search list for devices.      if(hint.has_key("vid") && hint.has_key("pid") && hint.has_key("type") && hint["type"] == "b200") { -        vid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("vid")); -        pid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("pid")); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("vid")), +                                                                    uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("pid"))));      } else { -        vid = B200_VENDOR_ID; -        pid = B200_PRODUCT_ID; +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID)); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID)); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID));      }      // Important note: @@ -104,8 +106,9 @@ static device_addrs_t b200_find(const device_addr_t &hint)      // This requirement is a courtesy of libusb1.0 on windows.      //find the usrps and load firmware -    size_t found = 0; -    BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { +    std::vector<usb_device_handle::sptr> uhd_usb_device_vector = usb_device_handle::get_device_list(vid_pid_pair_list); + +    BOOST_FOREACH(usb_device_handle::sptr handle, uhd_usb_device_vector) {          //extract the firmware path for the b200          std::string b200_fw_image;          try{ @@ -115,7 +118,7 @@ static device_addrs_t b200_find(const device_addr_t &hint)              UHD_MSG(warning) << boost::format(                  "Could not locate B200 firmware.\n"                  "Please install the images package. %s\n" -            ) % print_images_error(); +            ) % print_utility_error("uhd_images_downloader.py");              return b200_addrs;          }          UHD_LOG << "the firmware image: " << b200_fw_image << std::endl; @@ -138,7 +141,7 @@ static device_addrs_t b200_find(const device_addr_t &hint)      //search for the device until found or timeout      while (boost::get_system_time() < timeout_time and b200_addrs.empty() and found != 0)      { -        BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) +        BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid_pid_pair_list))          {              usb_control::sptr control;              try{control = usb_control::make(handle, 0);} @@ -155,12 +158,16 @@ static device_addrs_t b200_find(const device_addr_t &hint)              {                  switch (boost::lexical_cast<boost::uint16_t>(mb_eeprom["product"]))                  { +                //0x0001 and 0x7737 are Ettus B200 product Ids.                  case 0x0001:                  case 0x7737: +                case B200_PRODUCT_NI_ID:                      new_addr["product"] = "B200";                      break; -                case 0x7738: +                //0x0002 and 0x7738 are Ettus B210 product Ids.                  case 0x0002: +                case 0x7738: +                case B210_PRODUCT_NI_ID:                      new_addr["product"] = "B210";                      break;                  default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; @@ -204,13 +211,50 @@ b200_impl::b200_impl(const device_addr_t &device_addr)      //try to match the given device address with something on the USB bus      boost::uint16_t vid = B200_VENDOR_ID;      boost::uint16_t pid = B200_PRODUCT_ID; +    bool specified_vid = false; +    bool specified_pid = false; +      if (device_addr.has_key("vid")) +    {          vid = uhd::cast::hexstr_cast<boost::uint16_t>(device_addr.get("vid")); +        specified_vid = true; +    } +      if (device_addr.has_key("pid")) +    {          pid = uhd::cast::hexstr_cast<boost::uint16_t>(device_addr.get("pid")); +        specified_pid = true; +    } -    std::vector<usb_device_handle::sptr> device_list = -        usb_device_handle::get_device_list(vid, pid); +    std::vector<usb_device_handle::vid_pid_pair_t> vid_pid_pair_list;//search list for devices. + +    // Search only for specified VID and PID if both specified +    if (specified_vid && specified_pid) +    { +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,pid)); +    } +    // Search for all supported PIDs limited to specified VID if only VID specified +    else if (specified_vid) +    { +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B200_PRODUCT_ID)); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B200_PRODUCT_NI_ID)); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B210_PRODUCT_NI_ID)); +    } +    // Search for all supported VIDs limited to specified PID if only PID specified +    else if (specified_pid) +    { +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID,pid)); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,pid)); +    } +    // Search for all supported devices if neither VID nor PID specified +    else +    { +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID,B200_PRODUCT_ID)); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,B200_PRODUCT_NI_ID)); +        vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,B210_PRODUCT_NI_ID)); +    } + +    std::vector<usb_device_handle::sptr> device_list = usb_device_handle::get_device_list(vid_pid_pair_list);      //locate the matching handle in the device list      usb_device_handle::sptr handle; @@ -244,13 +288,17 @@ b200_impl::b200_impl(const device_addr_t &device_addr)      {          switch (boost::lexical_cast<boost::uint16_t>(mb_eeprom["product"]))          { +        //0x0001 and 0x7737 are Ettus B200 product Ids.          case 0x0001:          case 0x7737: +        case B200_PRODUCT_NI_ID:              product_name = "B200";              default_file_name = B200_FPGA_FILE_NAME;              break; -        case 0x7738: +        //0x0002 and 0x7738 are Ettus B210 product Ids.          case 0x0002: +        case 0x7738: +        case B210_PRODUCT_NI_ID:              product_name = "B210";              default_file_name = B210_FPGA_FILE_NAME;              break; @@ -416,6 +464,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr)          .publish(boost::bind(&b200_impl::get_tick_rate, this))          .subscribe(boost::bind(&b200_impl::update_tick_rate, this, _1));      _tree->create<time_spec_t>(mb_path / "time" / "cmd"); +    _tree->create<bool>(mb_path / "auto_tick_rate").set(false);      ////////////////////////////////////////////////////////////////////      // and do the misc mboard sensors @@ -516,6 +565,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr)          _tree->access<double>(mb_path / "rx_dsps" / str(boost::format("%u") % i)/ "rate/value").set(B200_DEFAULT_RATE);          _tree->access<double>(mb_path / "tx_dsps" / str(boost::format("%u") % i) / "rate/value").set(B200_DEFAULT_RATE);      } +    // We can automatically choose a master clock rate, but not if the user specifies one +    _tree->access<bool>(mb_path / "auto_tick_rate").set(not device_addr.has_key("master_clock_rate")); +    if (not device_addr.has_key("master_clock_rate")) { +        UHD_MSG(status) << "Setting master clock rate selection to 'automatic'." << std::endl; +    }      //GPS installed: use external ref, time, and init time spec      if (_gps and _gps->gps_detected()) @@ -579,7 +633,7 @@ void b200_impl::setup_radio(const size_t dspno)      _tree->create<meta_range_t>(rx_dsp_path / "rate" / "range")          .publish(boost::bind(&rx_dsp_core_3000::get_host_rates, perif.ddc));      _tree->create<double>(rx_dsp_path / "rate" / "value") -        .coerce(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1)) +        .coerce(boost::bind(&b200_impl::coerce_rx_samp_rate, this, perif.ddc, dspno, _1))          .subscribe(boost::bind(&b200_impl::update_rx_samp_rate, this, dspno, _1))          .set(0.0); // Can only set this after tick rate is initialized.      _tree->create<double>(rx_dsp_path / "freq" / "value") @@ -603,7 +657,7 @@ void b200_impl::setup_radio(const size_t dspno)      _tree->create<meta_range_t>(tx_dsp_path / "rate" / "range")          .publish(boost::bind(&tx_dsp_core_3000::get_host_rates, perif.duc));      _tree->create<double>(tx_dsp_path / "rate" / "value") -        .coerce(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1)) +        .coerce(boost::bind(&b200_impl::coerce_tx_samp_rate, this, perif.duc, dspno, _1))          .subscribe(boost::bind(&b200_impl::update_tx_samp_rate, this, dspno, _1))          .set(0.0); // Can only set this after tick rate is initialized.      _tree->create<double>(tx_dsp_path / "freq" / "value") @@ -721,7 +775,7 @@ void b200_impl::codec_loopback_self_test(wb_iface::sptr iface)  /***********************************************************************   * Sample and tick rate comprehension below   **********************************************************************/ -void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction /*= NULL*/) +void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string &direction /*= ""*/)  {      const size_t max_chans = 2;      if (chan_count > max_chans) @@ -729,7 +783,7 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co          throw uhd::value_error(boost::str(              boost::format("cannot not setup %d %s channels (maximum is %d)")                  % chan_count -                % (direction ? direction : "data") +                % (direction.empty() ? "data" : direction)                  % max_chans          ));      } @@ -743,20 +797,26 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co                      % (tick_rate/1e6)                      % (max_tick_rate/1e6)                      % chan_count -                    % (direction ? direction : "data") +                    % (direction.empty() ? "data" : direction)              ));          }      }  } -double b200_impl::set_tick_rate(const double rate) +double b200_impl::set_tick_rate(const double new_tick_rate)  { -    UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz\n") % (rate/1e6)); - -    check_tick_rate_with_current_streamers(rate);   // Defined in b200_io_impl.cpp +    UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz... ") % (new_tick_rate/1e6)) << std::flush; +    check_tick_rate_with_current_streamers(new_tick_rate);   // Defined in b200_io_impl.cpp + +    // Make sure the clock rate is actually changed before doing +    // the full Monty of setting regs and loopback tests etc. +    if (std::abs(new_tick_rate - _tick_rate) < 1.0) { +        UHD_MSG(status) << "OK" << std::endl; +        return _tick_rate; +    } -    _tick_rate = _codec_ctrl->set_clock_rate(rate); -    UHD_MSG(status) << (boost::format("Actually got clock rate %.6f MHz\n") % (_tick_rate/1e6)); +    _tick_rate = _codec_ctrl->set_clock_rate(new_tick_rate); +    UHD_MSG(status) << std::endl << (boost::format("Actually got clock rate %.6f MHz.") % (_tick_rate/1e6)) << std::endl;      //reset after clock rate change      this->reset_codec_dcm(); @@ -781,11 +841,11 @@ void b200_impl::check_fw_compat(void)      if (compat_major != B200_FW_COMPAT_NUM_MAJOR){          throw uhd::runtime_error(str(boost::format( -            "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" +            "Expected firmware compatibility number %d.%d, but got %d.%d:\n"              "The firmware build is not compatible with the host code build.\n"              "%s" -        ) % int(B200_FW_COMPAT_NUM_MAJOR) % compat_major % compat_minor -          % print_images_error())); +        )   % int(B200_FW_COMPAT_NUM_MAJOR) % int(B200_FW_COMPAT_NUM_MINOR) +            % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fw_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); @@ -802,11 +862,10 @@ void b200_impl::check_fpga_compat(void)      if (compat_major != B200_FPGA_COMPAT_NUM){          throw uhd::runtime_error(str(boost::format( -            "Expected FPGA compatibility number 0x%x, but got 0x%x.%x:\n" +            "Expected FPGA compatibility number %d, but got %d:\n"              "The FPGA build is not compatible with the host code build.\n"              "%s" -        ) % int(B200_FPGA_COMPAT_NUM) % compat_major % compat_minor -          % print_images_error())); +        ) % int(B200_FPGA_COMPAT_NUM) % compat_major % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fpga_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 8f03d81ad..71592f60b 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -45,9 +45,9 @@  #include <uhd/transport/bounded_buffer.hpp>  #include <boost/weak_ptr.hpp>  #include "recv_packet_demuxer_3000.hpp" -static const boost::uint8_t  B200_FW_COMPAT_NUM_MAJOR = 0x07; -static const boost::uint8_t  B200_FW_COMPAT_NUM_MINOR = 0x00; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x04; +static const boost::uint8_t  B200_FW_COMPAT_NUM_MAJOR = 7; +static const boost::uint8_t  B200_FW_COMPAT_NUM_MINOR = 0; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 4;  static const double          B200_BUS_CLOCK_RATE = 100e6;  static const double          B200_DEFAULT_TICK_RATE = 32e6;  static const double          B200_DEFAULT_FREQ = 100e6; // Hz @@ -98,7 +98,13 @@ public:      uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args);      uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args);      bool recv_async_msg(uhd::async_metadata_t &, double); -    void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction = NULL); + +    //! Check that the combination of stream args and tick rate are valid. +    // +    // Basically figures out the arguments for enforce_tick_rate_limits() +    // and calls said method. If arguments are invalid, throws a +    // uhd::value_error. +    void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = "");  private:      //controllers @@ -190,11 +196,56 @@ private:      double _tick_rate;      double get_tick_rate(void){return _tick_rate;}      double set_tick_rate(const double rate); + +    /*! \brief Choose a tick rate (master clock rate) that works well for the given sampling rate. +     * +     * This function will try and choose a master clock rate automatically. +     * See the function definition for details on the algorithm. +     * +     * The chosen tick rate is the largest multiple of two that is smaler +     * than the max tick rate. +     * The base rate is either given explicitly, or is the lcm() of the tx +     * and rx sampling rates. In that case, it reads the rates directly +     * from the property tree. It also tries to guess the number of channels +     * (for the max possible tick rate) by checking the available streamers. +     * This value, too, can explicitly be given. +     * +     * \param rate If this is given, it will be used as a minimum rate, or +     *             argument to lcm(). +     * \param tree_dsp_path The sampling rate from this property tree path +     *                      will be ignored. +     * \param num_chans If given, specifies the number of channels. +     */ +    void set_auto_tick_rate( +            const double rate=0, +            const uhd::fs_path &tree_dsp_path="", +            size_t num_chans=0 +    ); +      void update_tick_rate(const double); -    void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction = NULL); + +    /*! Check if \p tick_rate works with \p chan_count channels. +     * +     * Throws a uhd::value_error if not. +     */ +    void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string  &direction = "");      void check_tick_rate_with_current_streamers(double rate); +    /*! Return the max number of channels on active rx_streamer or tx_streamer objects associated with this device. +     * +     * \param direction Set to "TX" to only check tx_streamers, "RX" to only check +     *                  rx_streamers. Any other value will check if \e any active +     *                  streamers are available. +     * \return Return the number of tx streamers (direction=="TX"), the number of rx +     *         streamers (direction=="RX") or the total number of streamers. +     */ +    size_t max_chan_count(const std::string &direction=""); + +    //! Coercer, attached to the "rate/value" property on the rx dsps. +    double coerce_rx_samp_rate(rx_dsp_core_3000::sptr, size_t, const double);      void update_rx_samp_rate(const size_t, const double); +    //! Coercer, attached to the "rate/value" property on the tx dsps. +    double coerce_tx_samp_rate(tx_dsp_core_3000::sptr, size_t, const double);      void update_tx_samp_rate(const size_t, const double);  }; diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index 262c95f0d..60b925517 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2012-2013 Ettus Research LLC +// Copyright 2012-2014 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -21,8 +21,10 @@  #include "../../transport/super_recv_packet_handler.hpp"  #include "../../transport/super_send_packet_handler.hpp"  #include "async_packet_handler.hpp" +#include <uhd/utils/math.hpp>  #include <boost/bind.hpp>  #include <boost/make_shared.hpp> +#include <boost/math/common_factor.hpp>  #include <set>  using namespace uhd; @@ -34,30 +36,32 @@ using namespace uhd::transport;   **********************************************************************/  void b200_impl::check_tick_rate_with_current_streamers(double rate)  { -    size_t max_tx_chan_count = 0, max_rx_chan_count = 0; +    // Defined in b200_impl.cpp +    enforce_tick_rate_limits(max_chan_count("RX"), rate, "RX"); +    enforce_tick_rate_limits(max_chan_count("TX"), rate, "TX"); +} + +// direction can either be "TX", "RX", or empty (default) +size_t b200_impl::max_chan_count(const std::string &direction /* = "" */) +{ +    size_t max_count = 0;      BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)      { -        { +        if ((direction == "RX" or direction.empty()) and not perif.rx_streamer.expired()) {              boost::shared_ptr<sph::recv_packet_streamer> rx_streamer =                  boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock()); -            if (rx_streamer) -                max_rx_chan_count = std::max(max_rx_chan_count, rx_streamer->get_num_channels()); +            max_count = std::max(max_count, rx_streamer->get_num_channels());          } - -        { +        if ((direction == "TX" or direction.empty()) and not perif.tx_streamer.expired()) {              boost::shared_ptr<sph::send_packet_streamer> tx_streamer =                  boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock()); -            if (tx_streamer) -                max_tx_chan_count = std::max(max_tx_chan_count, tx_streamer->get_num_channels()); +            max_count = std::max(max_count, tx_streamer->get_num_channels());          }      } - -    // Defined in b200_impl.cpp -    enforce_tick_rate_limits(max_rx_chan_count, rate, "RX"); -    enforce_tick_rate_limits(max_tx_chan_count, rate, "TX"); +    return max_count;  } -void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction /*= NULL*/) +void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction /*= ""*/)  {      std::set<size_t> chans_set;      for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) @@ -69,26 +73,120 @@ void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_      enforce_tick_rate_limits(chans_set.size(), tick_rate, direction);   // Defined in b200_impl.cpp  } -void b200_impl::update_tick_rate(const double rate) +void b200_impl::set_auto_tick_rate( +        const double rate, +        const fs_path &tree_dsp_path, +        size_t num_chans +) { +    if (num_chans == 0) { // Divine them +        num_chans = std::max(size_t(1), max_chan_count()); +    } + +    // See also the doxygen documentation for these steps in b200_impl.hpp +    // Step 1: Obtain LCM and max rate from all relevant dsps +    boost::uint32_t lcm_rate = (rate == 0) ? 1 : static_cast<boost::uint32_t>(floor(rate + 0.5)); +    for (int i = 0; i < 2; i++) { // Loop through rx and tx +        std::string dir = (i == 0) ? "tx" : "rx"; +        // We have no way of knowing which DSPs are used, so we check them all. +        BOOST_FOREACH(const std::string &dsp_no, _tree->list(str(boost::format("/mboards/0/%s_dsps") % dir))) { +            fs_path dsp_path = str(boost::format("/mboards/0/%s_dsps/%s") % dir % dsp_no); +            if (dsp_path == tree_dsp_path) { +                continue; +            } +            double this_dsp_rate = _tree->access<double>(dsp_path / "rate/value").get(); +            // If this_dsp_rate == B200_DEFAULT_RATE, we assume the user did not actually set +            // the sampling rate. If the user *did* set the rate to +            // B200_DEFAULT_RATE on all DSPs, then this will still work (see below). +            // If the user set one DSP to B200_DEFAULT_RATE and the other to +            // a different rate, this also works if the rates are integer multiples +            // of one another. Only for certain configurations of B200_DEFAULT_RATE +            // and another rate that is not an integer multiple, this will be problematic. +            // Since this case is less common than the case where a rate is left unset, +            // we don't handle that but rather explain that corner case in the documentation. +            if (this_dsp_rate == B200_DEFAULT_RATE) { +                continue; +            } +            lcm_rate = boost::math::lcm<boost::uint32_t>( +                    lcm_rate, +                    static_cast<boost::uint32_t>(floor(this_dsp_rate + 0.5)) +            ); +        } +    } +    if (lcm_rate == 1) { +        lcm_rate = static_cast<boost::uint32_t>(B200_DEFAULT_RATE); +    } + +    // Step 2: Determine whether if we can use lcm_rate (preferred), +    // or have to give up because too large: +    const double max_tick_rate = +        ((num_chans <= 1) ? ad9361_device_t::AD9361_RECOMMENDED_MAX_CLOCK_RATE : ad9361_device_t::AD9361_MAX_CLOCK_RATE/2); +    double base_rate = static_cast<double>(lcm_rate); +    if (base_rate > max_tick_rate) { +        UHD_MSG(warning) +            << "Cannot automatically determine an appropriate tick rate for these sampling rates." << std::endl +            << "Consider using different sampling rates, or manually specify a suitable master clock rate." << std::endl; +        return; // Let the others handle this +    } + +    // Step 3: Choose the new rate +    // Rules for choosing the tick rate: +    // Choose a rate that is a power of 2 larger than the sampling rate, +    // but at least 4. Cannot exceed the max tick rate, of course, but must +    // be larger than the minimum tick rate. +    // An equation that does all that is: +    // +    // f_auto = r * 2^floor(log2(f_max/r)) +    // +    // where r is the base rate and f_max is the maximum tick rate. The case +    // where floor() yields 1 must be caught. +    const double min_tick_rate = _codec_ctrl->get_clock_rate_range().start(); +    // We use shifts here instead of 2^x because exp2() is not available in all compilers, +    // also this guarantees no rounding issues. The type cast to int32_t serves as floor(): +    boost::int32_t multiplier = (1 << boost::int32_t(uhd::math::log2(max_tick_rate / base_rate))); +    if (multiplier == 2 and base_rate >= min_tick_rate) { +        // Don't bother (see above) +        multiplier = 1; +    } +    double new_rate = base_rate * multiplier; +    UHD_ASSERT_THROW(new_rate >= min_tick_rate); +    UHD_ASSERT_THROW(new_rate <= max_tick_rate); + +    if (_tree->access<double>("/mboards/0/tick_rate").get() != new_rate) { +        _tree->access<double>("/mboards/0/tick_rate").set(new_rate); +    } +} + +void b200_impl::update_tick_rate(const double new_tick_rate)  { -    check_tick_rate_with_current_streamers(rate); +    check_tick_rate_with_current_streamers(new_tick_rate);      BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)      {          boost::shared_ptr<sph::recv_packet_streamer> my_streamer =              boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock()); -        if (my_streamer) my_streamer->set_tick_rate(rate); -        perif.framer->set_tick_rate(_tick_rate); +        if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); +        perif.framer->set_tick_rate(new_tick_rate);      }      BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)      {          boost::shared_ptr<sph::send_packet_streamer> my_streamer =              boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock()); -        if (my_streamer) my_streamer->set_tick_rate(rate); -        perif.deframer->set_tick_rate(_tick_rate); +        if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); +        perif.deframer->set_tick_rate(new_tick_rate);      }  } + +double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate) +{ +    // Have to set tick rate first, or the ddc will change the requested rate based on default tick rate +    if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { +        const std::string dsp_path = (boost::format("/mboards/0/rx_dsps/%s") % dspno).str(); +        set_auto_tick_rate(rx_rate, dsp_path); +    } +    return ddc->set_host_rate(rx_rate); +} +  void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate)  {      boost::shared_ptr<sph::recv_packet_streamer> my_streamer = @@ -99,6 +197,16 @@ void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate)      my_streamer->set_scale_factor(adj);  } +double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno, const double tx_rate) +{ +    // Have to set tick rate first, or the duc will change the requested rate based on default tick rate +    if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { +        const std::string dsp_path = (boost::format("/mboards/0/tx_dsps/%s") % dspno).str(); +        set_auto_tick_rate(tx_rate, dsp_path); +    } +    return duc->set_host_rate(tx_rate); +} +  void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate)  {      boost::shared_ptr<sph::send_packet_streamer> my_streamer = @@ -264,6 +372,9 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_)      if (args.otw_format.empty()) args.otw_format = "sc16";      args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; +    if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { +        set_auto_tick_rate(0, "", args.channels.size()); +    }      check_streamer_args(args, this->get_tick_rate(), "RX");      boost::shared_ptr<sph::recv_packet_streamer> my_streamer; @@ -371,7 +482,10 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_)      if (args.otw_format.empty()) args.otw_format = "sc16";      args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; -    check_streamer_args(args, this->get_tick_rate(), "TX"); +    if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { +        set_auto_tick_rate(0, "", args.channels.size()); +    } +    check_streamer_args(args, this->get_tick_rate(), "RX");      boost::shared_ptr<sph::send_packet_streamer> my_streamer;      for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 8b4f2316c..ac419e0e0 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -21,7 +21,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <boost/bind.hpp>  #include <boost/format.hpp>  #include <boost/filesystem.hpp> @@ -132,7 +132,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){          e100_fpga_image = find_image_path(device_addr.get("fpga", default_fpga_file_name));      }      catch(...){ -        UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_images_error(); +        UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_utility_error("uhd_images_downloader.py");          throw;      }      e100_load_fpga(e100_fpga_image); diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index 59788fbea..43a9b7b26 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -28,7 +28,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/utils/log.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/usrp/dboard_eeprom.hpp>  #include <uhd/transport/if_addrs.hpp>  #include <uhd/transport/udp_zero_copy.hpp> @@ -397,7 +397,7 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)              "%s"          ) % fpga::COMPAT_MAJOR            % _get_version(FPGA_MAJOR) % _get_version(FPGA_MINOR) -          % print_images_error())); +          % print_utility_error("uhd_images_downloader.py")));      }      //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 6d36d8681..189dba838 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -33,7 +33,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <boost/asio.hpp>  #include <boost/thread.hpp> diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 175633c4c..e97787785 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -431,6 +431,9 @@ public:       ******************************************************************/      void set_master_clock_rate(double rate, size_t mboard){          if (mboard != ALL_MBOARDS){ +            if (_tree->exists(mb_root(mboard) / "auto_tick_rate")) { +                _tree->access<bool>(mb_root(mboard) / "auto_tick_rate").set(false); +            }              _tree->access<double>(mb_root(mboard) / "tick_rate").set(rate);              return;          } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 709092e42..dbd5408e8 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -23,7 +23,7 @@  #include <uhd/utils/cast.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <boost/format.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/filesystem.hpp> @@ -85,7 +85,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)              usrp1_fw_image = find_image_path(hint.get("fw", "usrp1_fw.ihx"));          }          catch(...){ -            UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_images_error(); +            UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_utility_error("uhd_images_downloader.py");          }          UHD_LOG << "USRP1 firmware image: " << usrp1_fw_image << std::endl; diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index b2085807f..65cf90a17 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -23,7 +23,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/utils/paths.hpp>  #include <uhd/utils/tasks.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <uhd/types/dict.hpp>  #include <boost/thread.hpp> @@ -375,7 +375,7 @@ public:              fpga_image_path = uhd::find_image_path(fpga_image);          }          catch(const std::exception &){ -            return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_images_error()); +            return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_utility_error("uhd_images_downloader.py"));          }          //escape char for multi-line cmd + newline + indent? @@ -389,13 +389,13 @@ public:          if (this->get_rev() == USRP2_REV3 or this->get_rev() == USRP2_REV4){              const std::string card_burner = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp2_card_burner.py").string();              const std::string card_burner_cmd = str(boost::format("\"%s%s\" %s--fpga=\"%s\" %s--fw=\"%s\"") % sudo % card_burner % ml % fpga_image_path % ml % fw_image_path); -            return str(boost::format("%s\n%s") % print_images_error() % card_burner_cmd); +            return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % card_burner_cmd);          }          else{              const std::string addr = _ctrl_transport->get_recv_addr();              const std::string net_burner_path = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp_n2xx_simple_net_burner").string();              const std::string net_burner_cmd = str(boost::format("\"%s\" %s--addr=\"%s\"") % net_burner_path % ml % addr); -            return str(boost::format("%s\n%s") % print_images_error() % net_burner_cmd); +            return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % net_burner_cmd);          }      } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index eab5cfef2..bf676b661 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -24,7 +24,7 @@  #include "apply_corrections.hpp"  #include <uhd/utils/static.hpp>  #include <uhd/utils/msg.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <uhd/usrp/subdev_spec.hpp>  #include <uhd/transport/if_addrs.hpp> @@ -41,7 +41,7 @@  #define NIUSRPRIO_DEFAULT_RPC_PORT "5444" -#define X300_REV(x) (x - "A" + 1) +#define X300_REV(x) ((x) - "A" + 1)  using namespace uhd;  using namespace uhd::usrp; @@ -171,7 +171,7 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu              default:                  continue;          } -         +          niriok_proxy::sptr kernel_proxy = niriok_proxy::make_and_open(dev_info.interface_path);          //Attempt to read the name from the EEPROM and perform filtering. @@ -1432,8 +1432,8 @@ bool x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout)          boost::this_thread::sleep(boost::posix_time::milliseconds(1));      } while (boost::get_system_time() < timeout_time); -    //failed to lock on reference -    return false; +    //Check one last time +    return get_ref_locked(ctrl).to_bool();  }  sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl) @@ -1668,11 +1668,11 @@ void x300_impl::check_fw_compat(const fs_path &mb_path, wb_iface::sptr iface)      if (compat_major != X300_FW_COMPAT_MAJOR)      {          throw uhd::runtime_error(str(boost::format( -            "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" +            "Expected firmware compatibility number %d.%d, but got %d.%d:\n"              "The firmware build is not compatible with the host code build.\n"              "%s" -        ) % int(X300_FW_COMPAT_MAJOR) % compat_major % compat_minor -          % print_images_error())); +        )   % int(X300_FW_COMPAT_MAJOR) % int(X300_FW_COMPAT_MINOR) +            % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>(mb_path / "fw_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); @@ -1692,11 +1692,11 @@ void x300_impl::check_fpga_compat(const fs_path &mb_path, wb_iface::sptr iface)              "Download the appropriate FPGA images for this version of UHD.\n"              "%s\n\n"              "Then burn a new image to the on-board flash storage of your\n" -            "USRP X3xx device using the burner utility. \n\n" +            "USRP X3xx device using the burner utility. %s\n\n"              "For more information, refer to the UHD manual:\n\n"              " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash"          )   % int(X300_FPGA_COMPAT_MAJOR) % compat_major -            % print_images_error())); +            % print_utility_error("uhd_images_downloader.py") % print_utility_error("usrp_x3xx_fpga_burner")));      }      _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); @@ -1720,14 +1720,20 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie(const std::string& res                  case X300_USRP_PCIE_SSID:                      mb_type = USRP_X300_MB; break;                  case X310_USRP_PCIE_SSID: -                case X310_2940R_PCIE_SSID: -                case X310_2942R_PCIE_SSID: -                case X310_2943R_PCIE_SSID: -                case X310_2944R_PCIE_SSID: -                case X310_2950R_PCIE_SSID: -                case X310_2952R_PCIE_SSID: -                case X310_2953R_PCIE_SSID: -                case X310_2954R_PCIE_SSID: +                case X310_2940R_40MHz_PCIE_SSID: +                case X310_2940R_120MHz_PCIE_SSID: +                case X310_2942R_40MHz_PCIE_SSID: +                case X310_2942R_120MHz_PCIE_SSID: +                case X310_2943R_40MHz_PCIE_SSID: +                case X310_2943R_120MHz_PCIE_SSID: +                case X310_2944R_40MHz_PCIE_SSID: +                case X310_2950R_40MHz_PCIE_SSID: +                case X310_2950R_120MHz_PCIE_SSID: +                case X310_2952R_40MHz_PCIE_SSID: +                case X310_2952R_120MHz_PCIE_SSID: +                case X310_2953R_40MHz_PCIE_SSID: +                case X310_2953R_120MHz_PCIE_SSID: +                case X310_2954R_40MHz_PCIE_SSID:                      mb_type = USRP_X310_MB; break;                  default:                      mb_type = UNKNOWN;      break; @@ -1755,14 +1761,20 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_eeprom(const uhd::usrp::mbo              case X300_USRP_PCIE_SSID:                  mb_type = USRP_X300_MB; break;              case X310_USRP_PCIE_SSID: -            case X310_2940R_PCIE_SSID: -            case X310_2942R_PCIE_SSID: -            case X310_2943R_PCIE_SSID: -            case X310_2944R_PCIE_SSID: -            case X310_2950R_PCIE_SSID: -            case X310_2952R_PCIE_SSID: -            case X310_2953R_PCIE_SSID: -            case X310_2954R_PCIE_SSID: +            case X310_2940R_40MHz_PCIE_SSID: +            case X310_2940R_120MHz_PCIE_SSID: +            case X310_2942R_40MHz_PCIE_SSID: +            case X310_2942R_120MHz_PCIE_SSID: +            case X310_2943R_40MHz_PCIE_SSID: +            case X310_2943R_120MHz_PCIE_SSID: +            case X310_2944R_40MHz_PCIE_SSID: +            case X310_2950R_40MHz_PCIE_SSID: +            case X310_2950R_120MHz_PCIE_SSID: +            case X310_2952R_40MHz_PCIE_SSID: +            case X310_2952R_120MHz_PCIE_SSID: +            case X310_2953R_40MHz_PCIE_SSID: +            case X310_2953R_120MHz_PCIE_SSID: +            case X310_2954R_40MHz_PCIE_SSID:                  mb_type = USRP_X310_MB; break;              default:                  UHD_MSG(warning) << "X300 unknown product code in EEPROM: " << product_num << std::endl; diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index 334ae8168..e3515af0c 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -23,6 +23,7 @@  #include <uhd/transport/nirio_zero_copy.hpp>  #include "async_packet_handler.hpp"  #include <uhd/transport/bounded_buffer.hpp> +#include <uhd/transport/chdr.hpp>  #include <boost/bind.hpp>  #include <uhd/utils/tasks.hpp>  #include <uhd/utils/log.hpp> @@ -124,41 +125,6 @@ void x300_impl::update_subdev_spec(const std::string &tx_rx, const size_t mb_i,  /*********************************************************************** - * VITA stuff - **********************************************************************/ -static void x300_if_hdr_unpack_be( -    const boost::uint32_t *packet_buff, -    vrt::if_packet_info_t &if_packet_info -){ -    if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; -    return vrt::if_hdr_unpack_be(packet_buff, if_packet_info); -} - -static void x300_if_hdr_pack_be( -    boost::uint32_t *packet_buff, -    vrt::if_packet_info_t &if_packet_info -){ -    if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; -    return vrt::if_hdr_pack_be(packet_buff, if_packet_info); -} - -static void x300_if_hdr_unpack_le( -    const boost::uint32_t *packet_buff, -    vrt::if_packet_info_t &if_packet_info -){ -    if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; -    return vrt::if_hdr_unpack_le(packet_buff, if_packet_info); -} - -static void x300_if_hdr_pack_le( -    boost::uint32_t *packet_buff, -    vrt::if_packet_info_t &if_packet_info -){ -    if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; -    return vrt::if_hdr_pack_le(packet_buff, if_packet_info); -} - -/***********************************************************************   * RX flow control handler   **********************************************************************/  static size_t get_rx_flow_control_window(size_t frame_size, size_t sw_buff_size, const device_addr_t& rx_args) @@ -209,9 +175,9 @@ static void handle_rx_flowctrl(const boost::uint32_t sid, zero_copy_if::sptr xpo      //load header      if (big_endian) -        x300_if_hdr_pack_be(pkt, packet_info); +        vrt::chdr::if_hdr_pack_be(pkt, packet_info);      else -        x300_if_hdr_pack_le(pkt, packet_info); +        vrt::chdr::if_hdr_pack_le(pkt, packet_info);      //load payload      pkt[packet_info.num_header_words32+0] = uhd::htonx<boost::uint32_t>(0); @@ -276,12 +242,12 @@ static void handle_tx_async_msgs(boost::shared_ptr<x300_tx_fc_guts_t> guts, zero      {          if (big_endian)          { -            x300_if_hdr_unpack_be(packet_buff, if_packet_info); +            vrt::chdr::if_hdr_unpack_be(packet_buff, if_packet_info);              endian_conv = uhd::ntohx;          }          else          { -            x300_if_hdr_unpack_le(packet_buff, if_packet_info); +            vrt::chdr::if_hdr_unpack_le(packet_buff, if_packet_info);              endian_conv = uhd::wtohx;          }      } @@ -430,10 +396,10 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)          //init some streamer stuff          std::string conv_endianness;          if (mb.if_pkt_is_big_endian) { -            my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_be); +            my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_be);              conv_endianness = "be";          } else { -            my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_le); +            my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_le);              conv_endianness = "le";          } @@ -594,10 +560,10 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_)          std::string conv_endianness;          if (mb.if_pkt_is_big_endian) { -            my_streamer->set_vrt_packer(&x300_if_hdr_pack_be); +            my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_be);              conv_endianness = "be";          } else { -            my_streamer->set_vrt_packer(&x300_if_hdr_pack_le); +            my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_le);              conv_endianness = "le";          } diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index f920b5ae2..4c5729efe 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -25,40 +25,40 @@  #define localparam static const int -localparam SR_DACSYNC   = 5; -localparam SR_LOOPBACK  = 6; -localparam SR_TEST      = 7; -localparam SR_SPI       = 8; -localparam SR_GPIO      = 16; -localparam SR_MISC_OUTS = 24; -localparam SR_READBACK  = 32; -localparam SR_TX_CTRL   = 64; -localparam SR_RX_CTRL   = 96; -localparam SR_TIME      = 128; -localparam SR_RX_DSP    = 144; -localparam SR_TX_DSP    = 184; -localparam SR_LEDS      = 195; -localparam SR_FP_GPIO   = 200; -localparam SR_RX_FRONT  = 208; -localparam SR_TX_FRONT  = 216; - -localparam RB32_GPIO            = 0; -localparam RB32_SPI             = 4; -localparam RB64_TIME_NOW        = 8; -localparam RB64_TIME_PPS        = 16; -localparam RB32_TEST            = 24; -localparam RB32_RX              = 28; -localparam RB32_FP_GPIO         = 32; - -localparam BL_ADDRESS     = 0; -localparam BL_DATA        = 1; +localparam SR_DACSYNC    = 5; +localparam SR_LOOPBACK   = 6; +localparam SR_TEST       = 7; +localparam SR_SPI        = 8; +localparam SR_GPIO       = 16; +localparam SR_MISC_OUTS  = 24; +localparam SR_READBACK   = 32; +localparam SR_TX_CTRL    = 64; +localparam SR_RX_CTRL    = 96; +localparam SR_TIME       = 128; +localparam SR_RX_DSP     = 144; +localparam SR_TX_DSP     = 184; +localparam SR_LEDS       = 195; +localparam SR_FP_GPIO    = 200; +localparam SR_RX_FRONT   = 208; +localparam SR_TX_FRONT   = 216; + +localparam RB32_GPIO     = 0; +localparam RB32_SPI      = 4; +localparam RB64_TIME_NOW = 8; +localparam RB64_TIME_PPS = 16; +localparam RB32_TEST     = 24; +localparam RB32_RX       = 28; +localparam RB32_FP_GPIO  = 32; + +localparam BL_ADDRESS    = 0; +localparam BL_DATA       = 1;  //wishbone settings map - relevant to host code -#define SET0_BASE 0xa000 -#define SETXB_BASE 0xb000 -#define BOOT_LDR_BASE 0xFA00 -#define I2C0_BASE 0xfe00 -#define I2C1_BASE 0xff00 +#define SET0_BASE     0xa000 +#define SETXB_BASE    0xb000 +#define BOOT_LDR_BASE 0xfa00 +#define I2C0_BASE     0xfe00 +#define I2C1_BASE     0xff00  #define SR_ADDR(base, offset) ((base) + (offset)*4)  localparam ZPU_SR_LEDS       = 00; @@ -70,56 +70,62 @@ localparam ZPU_SR_ETHINT0    = 40;  localparam ZPU_SR_ETHINT1    = 56;  //clock controls -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL  0x00 -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL  0x02 -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO     0x03 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL  0x00 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL  0x02 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO     0x03 - -localparam ZPU_RB_SPI = 2; +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00 +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02 +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO    0x03 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO    0x03 + +localparam ZPU_RB_SPI        = 2;  localparam ZPU_RB_CLK_STATUS = 3;  localparam ZPU_RB_COMPAT_NUM = 6;  localparam ZPU_RB_ETH_TYPE0  = 4;  localparam ZPU_RB_ETH_TYPE1  = 5;  //clock status -#define ZPU_RB_CLK_STATUS_LMK_STATUS    (0x3 << 0) -#define ZPU_RB_CLK_STATUS_LMK_LOCK      (0x1 << 2) -#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER  (0x1 << 3) -#define ZPU_RB_CLK_STATUS_PPS_DETECT    (0x1 << 4) +#define ZPU_RB_CLK_STATUS_LMK_STATUS   (0x3 << 0) +#define ZPU_RB_CLK_STATUS_LMK_LOCK     (0x1 << 2) +#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER (0x1 << 3) +#define ZPU_RB_CLK_STATUS_PPS_DETECT   (0x1 << 4)  //spi slaves on radio -#define DB_DAC_SEN (1 << 7) -#define DB_ADC_SEN (1 << 6) +#define DB_DAC_SEN      (1 << 7) +#define DB_ADC_SEN      (1 << 6)  #define DB_RX_LSADC_SEN (1 << 5)  #define DB_RX_LSDAC_SEN (1 << 4)  #define DB_TX_LSADC_SEN (1 << 3)  #define DB_TX_LSDAC_SEN (1 << 2) -#define DB_RX_SEN (1 << 1) -#define DB_TX_SEN (1 << 0) +#define DB_RX_SEN       (1 << 1) +#define DB_TX_SEN       (1 << 0)  //-------------------------------------------------------------------  // PCIe Registers  //------------------------------------------------------------------- -static const uint32_t X300_PCIE_VID         = 0x1093; -static const uint32_t X300_PCIE_PID         = 0xC4C4; -static const uint32_t X300_USRP_PCIE_SSID   = 0x7736; -static const uint32_t X310_USRP_PCIE_SSID   = 0x76CA; -static const uint32_t X310_2940R_PCIE_SSID  = 0x772B; -static const uint32_t X310_2942R_PCIE_SSID  = 0x772C; -static const uint32_t X310_2943R_PCIE_SSID  = 0x772D; -static const uint32_t X310_2944R_PCIE_SSID  = 0x772E; -static const uint32_t X310_2950R_PCIE_SSID  = 0x772F; -static const uint32_t X310_2952R_PCIE_SSID  = 0x7730; -static const uint32_t X310_2953R_PCIE_SSID  = 0x7731; -static const uint32_t X310_2954R_PCIE_SSID  = 0x7732; +static const uint32_t X300_PCIE_VID               = 0x1093; +static const uint32_t X300_PCIE_PID               = 0xC4C4; +static const uint32_t X300_USRP_PCIE_SSID         = 0x7736; +static const uint32_t X310_USRP_PCIE_SSID         = 0x76CA; +static const uint32_t X310_2940R_40MHz_PCIE_SSID  = 0x772B; +static const uint32_t X310_2940R_120MHz_PCIE_SSID = 0x77FB; +static const uint32_t X310_2942R_40MHz_PCIE_SSID  = 0x772C; +static const uint32_t X310_2942R_120MHz_PCIE_SSID = 0x77FC; +static const uint32_t X310_2943R_40MHz_PCIE_SSID  = 0x772D; +static const uint32_t X310_2943R_120MHz_PCIE_SSID = 0x77FD; +static const uint32_t X310_2944R_40MHz_PCIE_SSID  = 0x772E; +static const uint32_t X310_2950R_40MHz_PCIE_SSID  = 0x772F; +static const uint32_t X310_2950R_120MHz_PCIE_SSID = 0x77FE; +static const uint32_t X310_2952R_40MHz_PCIE_SSID  = 0x7730; +static const uint32_t X310_2952R_120MHz_PCIE_SSID = 0x77FF; +static const uint32_t X310_2953R_40MHz_PCIE_SSID  = 0x7731; +static const uint32_t X310_2953R_120MHz_PCIE_SSID = 0x7800; +static const uint32_t X310_2954R_40MHz_PCIE_SSID  = 0x7732;  static const uint32_t FPGA_X3xx_SIG_VALUE   = 0x58333030;  static const uint32_t PCIE_FPGA_ADDR_BASE   = 0xC0000; -#define PCIE_FPGA_REG(X)                    (PCIE_FPGA_ADDR_BASE + X) +#define PCIE_FPGA_REG(X)                    (PCIE_FPGA_ADDR_BASE + (X))  static const uint32_t FPGA_PCIE_SIG_REG     = PCIE_FPGA_REG(0x0000);  static const uint32_t FPGA_CNTR_LO_REG      = PCIE_FPGA_REG(0x0004); @@ -140,8 +146,8 @@ static const uint32_t DMA_FRAME_SIZE_REG    = 0x4;  static const uint32_t DMA_SAMPLE_COUNT_REG  = 0x8;  static const uint32_t DMA_PKT_COUNT_REG     = 0xC; -#define PCIE_TX_DMA_REG(REG, CHAN)          (PCIE_TX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG) -#define PCIE_RX_DMA_REG(REG, CHAN)          (PCIE_RX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG) +#define PCIE_TX_DMA_REG(REG, CHAN)          (PCIE_TX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) +#define PCIE_RX_DMA_REG(REG, CHAN)          (PCIE_RX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG))  static const uint32_t DMA_CTRL_DISABLED     = 0x00000000;  static const uint32_t DMA_CTRL_ENABLED      = 0x00000002; @@ -154,15 +160,15 @@ static const uint32_t DMA_STATUS_ERROR      = 0x00000001;  static const uint32_t DMA_STATUS_BUSY       = 0x00000002;  static const uint32_t PCIE_ROUTER_REG_BASE  = PCIE_FPGA_REG(0x0500); -#define PCIE_ROUTER_REG(X)                  (PCIE_ROUTER_REG_BASE + X) +#define PCIE_ROUTER_REG(X)                  (PCIE_ROUTER_REG_BASE + (X))  static const uint32_t PCIE_ZPU_DATA_BASE    = 0x30000;  static const uint32_t PCIE_ZPU_READ_BASE    = 0x20000;  //Trig and Status share the same base  static const uint32_t PCIE_ZPU_STATUS_BASE  = 0x20000; -#define PCIE_ZPU_DATA_REG(X)                (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + X) -#define PCIE_ZPU_READ_REG(X)                (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + X) -#define PCIE_ZPU_STATUS_REG(X)              (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + X) +#define PCIE_ZPU_DATA_REG(X)                (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + (X)) +#define PCIE_ZPU_READ_REG(X)                (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + (X)) +#define PCIE_ZPU_STATUS_REG(X)              (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + (X))  static const uint32_t PCIE_ZPU_READ_START       = 0x0;  static const uint32_t PCIE_ZPU_READ_CLOBBER     = 0x80000000; diff --git a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp index 8c207dd9f..d55fab10e 100644 --- a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp +++ b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp @@ -33,7 +33,7 @@  #include <uhd/usrp/gps_ctrl.hpp>  #include <uhd/usrp_clock/octoclock_eeprom.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/msg.hpp>  #include <uhd/utils/paths.hpp>  #include <uhd/utils/static.hpp> @@ -420,7 +420,7 @@ std::string octoclock_impl::_get_images_help_message(const std::string &addr){      catch(const std::exception &e){          return str(boost::format("Could not find %s in your images path.\n%s")                     % image_name -                   % uhd::print_images_error()); +                   % uhd::print_utility_error("uhd_images_downloader.py"));      }      //Get escape character @@ -433,5 +433,5 @@ std::string octoclock_impl::_get_images_help_message(const std::string &addr){      //Get burner command      const std::string burner_path = (fs::path(uhd::get_pkg_path()) / "bin" / "octoclock_firmware_burner").string();      const std::string burner_cmd = str(boost::format("%s %s--addr=\"%s\"") % burner_path % ml % addr); -    return str(boost::format("%s\n%s") % uhd::print_images_error() % burner_cmd); +    return str(boost::format("%s\n%s") % uhd::print_utility_error("uhd_images_downloader.py") % burner_cmd);  } diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index 106e2b650..369920ac1 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -132,7 +132,6 @@ SET_SOURCE_FILES_PROPERTIES(  LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/csv.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/images.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/msg.cpp diff --git a/host/lib/utils/images.cpp b/host/lib/utils/images.cpp deleted file mode 100644 index 1ba2f81e6..000000000 --- a/host/lib/utils/images.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2010-2012 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#include <uhd/utils/images.hpp> -#include <uhd/exception.hpp> -#include <uhd/utils/paths.hpp> -#include <boost/foreach.hpp> -#include <boost/filesystem.hpp> -#include <vector> -#include <iostream> - -namespace fs = boost::filesystem; - -std::vector<fs::path> get_image_paths(void); //defined in paths.cpp - -/*********************************************************************** - * Find an image in the image paths - **********************************************************************/ -std::string uhd::find_image_path(const std::string &image_name){ -    if (fs::exists(image_name)){ -        return fs::system_complete(image_name).string(); -    } -    BOOST_FOREACH(const fs::path &path, get_image_paths()){ -        fs::path image_path = path / image_name; -        if (fs::exists(image_path)) return image_path.string(); -    } -    throw uhd::io_error("Could not find path for image: " + image_name + "\n\n" + uhd::print_images_error()); -} - -std::string uhd::find_images_downloader(void){ -    return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "uhd_images_downloader.py").string(); -} - -std::string uhd::print_images_error(void){ -    #ifdef UHD_PLATFORM_WIN32 -    return "As an Administrator, please run:\n\n\"" + find_images_downloader() + "\""; -    #else -    return "Please run:\n\nsudo \"" + find_images_downloader() + "\""; -    #endif -} diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 3e2bea1c6..282ebb566 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -17,15 +17,19 @@  #include <uhd/config.hpp>  #include <uhd/utils/paths.hpp> -#include <boost/tokenizer.hpp> + +#include <boost/bind.hpp> +#include <uhd/exception.hpp>  #include <boost/filesystem.hpp>  #include <boost/foreach.hpp> -#include <boost/bind.hpp> +#include <boost/tokenizer.hpp> + +#include <cstdio>  //P_tmpdir  #include <cstdlib> +#include <iostream>  #include <string>  #include <vector> -#include <cstdlib> //getenv -#include <cstdio>  //P_tmpdir +  #ifdef BOOST_MSVC  #define USE_GET_TEMP_PATH  #include <windows.h> //GetTempPath @@ -136,3 +140,28 @@ std::string uhd::get_app_path(void){      return uhd::get_tmp_path();  } + +std::string uhd::find_image_path(const std::string &image_name){ +    if (fs::exists(image_name)){ +        return fs::system_complete(image_name).string(); +    } +    BOOST_FOREACH(const fs::path &path, get_image_paths()){ +        fs::path image_path = path / image_name; +        if (fs::exists(image_path)) return image_path.string(); +    } +    throw uhd::io_error("Could not find path for image: " + image_name +            + "\n\n" + uhd::print_utility_error("uhd_images_downloader.py")); +} + +std::string uhd::find_utility(std::string name) { +    return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / name) +        .string(); +} + +std::string uhd::print_utility_error(std::string name){ +    #ifdef UHD_PLATFORM_WIN32 +    return "As an Administrator, please run:\n\n\"" + find_utility(name) + "\""; +    #else +    return "Please run:\n\n \"" + find_utility(name) + "\""; +    #endif +} diff --git a/host/lib/utils/platform.cpp b/host/lib/utils/platform.cpp index e2f92039e..a9cef663b 100644 --- a/host/lib/utils/platform.cpp +++ b/host/lib/utils/platform.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2012 Ettus Research LLC +// Copyright 2010-2012,2014 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 @@ -19,7 +19,7 @@  #include <uhd/config.hpp>  #include <boost/functional/hash.hpp>  #ifdef UHD_PLATFORM_WIN32 -#include <Windows.h> +#include <windows.h>  #else  #include <unistd.h>  #endif diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 62544b69b..596ab1017 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -27,16 +27,19 @@ SET(test_sources      addr_test.cpp      buffer_test.cpp      byteswap_test.cpp -    convert_test.cpp      cast_test.cpp +    chdr_test.cpp +    convert_test.cpp      dict_test.cpp      error_test.cpp      fp_compare_delta_test.cpp      fp_compare_epsilon_test.cpp      gain_group_test.cpp +    math_test.cpp      msg_test.cpp      property_test.cpp      ranges_test.cpp +    sid_t_test.cpp      sph_recv_test.cpp      sph_send_test.cpp      subdev_spec_test.cpp @@ -45,7 +48,11 @@ SET(test_sources  )  #turn each test cpp file into an executable with an int main() function -ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) +IF(MINGW) +    ADD_DEFINITIONS(-DBOOST_TEST_MAIN) +ELSE() +    ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) +ENDIF()  SET(UHD_TEST_TARGET_DEPS uhd)  SET(UHD_TEST_LIBRARY_DIRS ${Boost_LIBRARY_DIRS}) @@ -54,7 +61,7 @@ SET(UHD_TEST_LIBRARY_DIRS ${Boost_LIBRARY_DIRS})  FOREACH(test_source ${test_sources})      GET_FILENAME_COMPONENT(test_name ${test_source} NAME_WE)      ADD_EXECUTABLE(${test_name} ${test_source}) -    TARGET_LINK_LIBRARIES(${test_name} uhd) +    TARGET_LINK_LIBRARIES(${test_name} uhd ${Boost_LIBRARIES})      UHD_ADD_TEST(${test_name} ${test_name})      UHD_INSTALL(TARGETS ${test_name} RUNTIME DESTINATION ${PKG_LIB_DIR}/tests COMPONENT tests)  ENDFOREACH(test_source) diff --git a/host/tests/chdr_test.cpp b/host/tests/chdr_test.cpp new file mode 100644 index 000000000..8893e12e5 --- /dev/null +++ b/host/tests/chdr_test.cpp @@ -0,0 +1,141 @@ +// +// Copyright 2014 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/transport/chdr.hpp> +#include <uhd/utils/byteswap.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/format.hpp> +#include <cstdlib> +#include <iostream> + +using namespace uhd::transport::vrt; + +static void pack_and_unpack( +    if_packet_info_t &if_packet_info_in +){ +    // Temp buffer for packed packet +    boost::uint32_t packet_buff[2048] = {0}; + +    // Check input (must not be lazy) +    BOOST_REQUIRE( +        (if_packet_info_in.num_payload_words32 == 0 and if_packet_info_in.num_payload_bytes == 0) +        or +        (if_packet_info_in.num_payload_words32 != 0 and if_packet_info_in.num_payload_bytes != 0) +    ); +    if (if_packet_info_in.num_payload_words32) { +        BOOST_REQUIRE(if_packet_info_in.num_payload_bytes <= 4 * if_packet_info_in.num_payload_words32); +        BOOST_REQUIRE(if_packet_info_in.num_payload_bytes > 4*(if_packet_info_in.num_payload_words32-1)); +    } + +    //pack metadata into a vrt header +    chdr::if_hdr_pack_be( +        packet_buff, if_packet_info_in +    ); +    std::cout << std::endl; +    boost::uint32_t header_bits = (uhd::ntohx(packet_buff[0]) >> 28); +    std::cout << boost::format("header bits = 0b%d%d%d%d") % bool(header_bits & 8) %  bool(header_bits & 4) % bool(header_bits & 2) % bool(header_bits & 1) << std::endl; +    for (size_t i = 0; i < 5; i++) +    { +        std::cout << boost::format("packet_buff[%u] = 0x%08x") % i % uhd::ntohx(packet_buff[i]) << std::endl; +    } + +    if_packet_info_t if_packet_info_out; +    // Must be set a-priori as per contract +    if_packet_info_out.num_packet_words32 = if_packet_info_in.num_packet_words32; + +    //unpack the vrt header back into metadata +    chdr::if_hdr_unpack_be( +        packet_buff, if_packet_info_out +    ); + +    //check the the unpacked metadata is the same +    BOOST_CHECK_EQUAL(if_packet_info_in.packet_count, if_packet_info_out.packet_count); +    BOOST_CHECK_EQUAL(if_packet_info_in.num_header_words32, if_packet_info_out.num_header_words32); +    BOOST_CHECK_EQUAL(if_packet_info_in.num_payload_words32, if_packet_info_out.num_payload_words32); +    BOOST_CHECK(if_packet_info_out.has_sid); +    BOOST_CHECK_EQUAL(if_packet_info_in.sid, if_packet_info_out.sid); +    BOOST_CHECK(if_packet_info_out.has_sid); +    BOOST_CHECK_EQUAL(if_packet_info_in.has_tsf, if_packet_info_out.has_tsf); +    if (if_packet_info_in.has_tsf and if_packet_info_out.has_tsf){ +        BOOST_CHECK_EQUAL(if_packet_info_in.tsf, if_packet_info_out.tsf); +    } +} + +BOOST_AUTO_TEST_CASE(test_with_chdr){ +    if_packet_info_t if_packet_info; +    if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_DATA; +    if_packet_info.eob = false; +    if_packet_info.packet_count = 7; +    if_packet_info.has_tsf = true; +    if_packet_info.tsf = 0x1234567890ABCDEF; +    if_packet_info.sid = 0xAABBCCDD; +    if_packet_info.num_payload_words32 = 24; +    if_packet_info.num_payload_bytes = 95; +    pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_fc){ +    if_packet_info_t if_packet_info; +    if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_FC; +    if_packet_info.eob = false; +    if_packet_info.packet_count = 19; +    if_packet_info.has_tsf = false; +    if_packet_info.tsf = 0x1234567890ABCDEF; +    if_packet_info.sid = 0xAABBCCDD; +    if_packet_info.num_payload_words32 = 4; +    if_packet_info.num_payload_bytes = 16; +    pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_cmd){ +    if_packet_info_t if_packet_info; +    if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_CMD; +    if_packet_info.packet_count = 19; +    if_packet_info.has_tsf = true; +    if_packet_info.tsf = 0x1234567890ABCDEF; +    if_packet_info.sid = 0xAABBCCDD; +    if_packet_info.num_payload_words32 = 4; +    if_packet_info.num_payload_bytes = 16; +    pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_resp){ +    if_packet_info_t if_packet_info; +    if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_RESP; +    if_packet_info.packet_count = 123; +    if_packet_info.has_tsf = false; +    if_packet_info.tsf = 0x1234567890ABCDEF; +    if_packet_info.sid = 0xAABBCCDD; +    if_packet_info.num_payload_words32 = 4; +    if_packet_info.num_payload_bytes = 16; +    pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_err){ +    if_packet_info_t if_packet_info; +    if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_ERROR; +    if_packet_info.packet_count = 1928; +    if_packet_info.eob = false; +    if_packet_info.error = false; // Needs to be set explicitly +    if_packet_info.has_tsf = false; +    if_packet_info.tsf = 0x1234567890ABCDEF; +    if_packet_info.sid = 0xAABBCCDD; +    if_packet_info.num_payload_words32 = 4; +    if_packet_info.num_payload_bytes = 16; +    pack_and_unpack(if_packet_info); +} + diff --git a/host/tests/math_test.cpp b/host/tests/math_test.cpp new file mode 100644 index 000000000..6c890c484 --- /dev/null +++ b/host/tests/math_test.cpp @@ -0,0 +1,29 @@ +// +// Copyright 2014 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 <boost/test/unit_test.hpp> +#include <boost/cstdint.hpp> +#include <uhd/utils/math.hpp> + +// NOTE: This is not the only math test case, see e.g. special tests +// for fp comparison. + +BOOST_AUTO_TEST_CASE(test_log2){ +    double y = uhd::math::log2(16.0); +    BOOST_CHECK_EQUAL(y, 4.0); +} + diff --git a/host/tests/sid_t_test.cpp b/host/tests/sid_t_test.cpp new file mode 100644 index 000000000..71ab2c213 --- /dev/null +++ b/host/tests/sid_t_test.cpp @@ -0,0 +1,158 @@ +// +// Copyright 2014 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 <iostream> +#include <sstream> +#include <boost/test/unit_test.hpp> +#include <uhd/types/sid.hpp> +#include <uhd/exception.hpp> + +using uhd::sid_t; + +BOOST_AUTO_TEST_CASE(test_sid_t) { +    boost::uint32_t sid_value = 0x01020310; +    sid_t sid(sid_value); + +    BOOST_CHECK_EQUAL(sid.is_set(), true); +    BOOST_CHECK_EQUAL(sid.to_pp_string(), "1.2>3.16"); +    BOOST_CHECK_EQUAL(sid.to_pp_string_hex(), "01:02>03:10"); +    BOOST_CHECK_EQUAL(sid.get_src(), 0x0102); +    BOOST_CHECK_EQUAL(sid.get_dst(), 0x0310); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x01); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x02); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x10); +    BOOST_CHECK_EQUAL(sid == sid, true); +    BOOST_CHECK_EQUAL(sid == sid_value, true); + +    boost::uint32_t check_sid_val = (boost::uint32_t) sid; +    BOOST_CHECK_EQUAL(check_sid_val, sid_value); + +    std::stringstream ss_dec; +    ss_dec << sid; +    BOOST_CHECK_EQUAL(ss_dec.str(), "1.2>3.16"); + +    std::stringstream ss_hex; +    ss_hex << std::hex << sid; +    BOOST_CHECK_EQUAL(ss_hex.str(), "01:02>03:10"); + +    sid_t empty_sid; +    BOOST_CHECK_EQUAL(empty_sid.is_set(), false); +    BOOST_CHECK_EQUAL(empty_sid.to_pp_string(), "x.x>x.x"); +    BOOST_CHECK_EQUAL(empty_sid.to_pp_string_hex(), "xx:xx>xx:xx"); +    BOOST_CHECK_EQUAL(empty_sid == sid, false); +    BOOST_CHECK_EQUAL(empty_sid == sid_value, false); +    BOOST_CHECK_EQUAL((bool) empty_sid, false); + +    empty_sid = sid_value; // No longer empty +    BOOST_CHECK_EQUAL(empty_sid.is_set(), true); +    BOOST_CHECK_EQUAL(empty_sid == sid, true); +} + +BOOST_AUTO_TEST_CASE(test_sid_t_set) { +    boost::uint32_t sid_value = 0x0; +    sid_t sid(sid_value); + +    sid.set(0x01020304); +    BOOST_CHECK_EQUAL(sid.get(), 0x01020304); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x01); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x02); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); +    BOOST_CHECK_EQUAL(sid.get_dst_xbarport(), 0x0); +    BOOST_CHECK_EQUAL(sid.get_dst_blockport(), 0x4); + +    sid.set_src_addr(0x0a); +    BOOST_CHECK_EQUAL(sid.get(), 0x0a020304); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x02); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); + +    sid.set_src_endpoint(0x0b); +    BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0304); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); + +    sid.set_dst_addr(0x0c); +    BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0c04); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); + +    sid.set_dst_endpoint(0x0d); +    BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0c0d); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x0d); + +    sid.set_dst_xbarport(0xb); +    BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0cbd); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0xbd); + +    sid.set_dst_blockport(0xc); +    BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0cbc); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0xbc); + +    sid_t flipped_sid = sid.reversed(); +    BOOST_CHECK_EQUAL(flipped_sid.get(), 0x0cbc0a0b); + +    // In-place +    sid.reverse(); +    BOOST_CHECK_EQUAL(sid.get(), 0x0cbc0a0b); +} + +BOOST_AUTO_TEST_CASE(test_sid_t_from_str) { +    sid_t sid("1.2>3.4"); +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 2); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 3); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 4); + +    sid = "01:02>03:10"; +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 2); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 3); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 16); + +    sid = "01:06/03:10"; +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 6); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 3); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 16); + +    sid = "01:02:04:10"; +    BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); +    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 2); +    BOOST_CHECK_EQUAL(sid.get_dst_addr(), 4); +    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 16); + +    BOOST_REQUIRE_THROW(sid_t fail_sid("foobar"), uhd::value_error); +    BOOST_REQUIRE_THROW(sid_t fail_sid("01:02:03:4"), uhd::value_error); +    BOOST_REQUIRE_THROW(sid_t fail_sid("01:02:03:004"), uhd::value_error); +    BOOST_REQUIRE_THROW(sid_t fail_sid("1.2.3.0004"), uhd::value_error); +} diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp index 0cab6618d..78449a8a4 100644 --- a/host/utils/b2xx_fx3_utils.cpp +++ b/host/utils/b2xx_fx3_utils.cpp @@ -39,7 +39,7 @@  #include <uhd/transport/usb_control.hpp>  #include <uhd/transport/usb_device_handle.hpp>  #include <uhd/exception.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  namespace po = boost::program_options;  namespace fs = boost::filesystem; @@ -54,17 +54,21 @@ const static vid_pid_t known_vid_pids[] = {      {B200_VENDOR_ID, B200_PRODUCT_ID}      };  const static std::vector<vid_pid_t> known_vid_pid_vector(known_vid_pids, known_vid_pids + (sizeof(known_vid_pids) / sizeof(known_vid_pids[0]))); -const static boost::uint8_t eeprom_init_values[] = { -    0x43, -    0x59, -    0x14, -    0xB2, -    (B200_PRODUCT_ID & 0xff), -    (B200_PRODUCT_ID >> 8), -    (B200_VENDOR_ID & 0xff), -    (B200_VENDOR_ID >> 8) -    }; -const static uhd::byte_vector_t eeprom_init_value_vector(eeprom_init_values, eeprom_init_values + (sizeof(eeprom_init_values) / sizeof(eeprom_init_values[0]))); + +static const size_t EEPROM_INIT_VALUE_VECTOR_SIZE = 8; +static uhd::byte_vector_t construct_eeprom_init_value_vector(boost::uint16_t vid, boost::uint16_t pid) +{ +    uhd::byte_vector_t init_values(EEPROM_INIT_VALUE_VECTOR_SIZE); +    init_values.push_back(0x43); +    init_values.push_back(0x59); +    init_values.push_back(0x14); +    init_values.push_back(0xB2); +    init_values.push_back(static_cast<boost::uint8_t>(pid & 0xff)); +    init_values.push_back(static_cast<boost::uint8_t>(pid >> 8)); +    init_values.push_back(static_cast<boost::uint8_t>(vid & 0xff)); +    init_values.push_back(static_cast<boost::uint8_t>(vid >> 8)); +    return init_values; +}  //!used with lexical cast to parse a hex string  template <class T> struct to_hex{ @@ -153,15 +157,22 @@ uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, c      try {          // try caller's VID/PID first -        handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid); -        if (user_supplied && handles.size() == 0) -            std::cerr << (boost::format("Failed to open device with VID 0x%04x and PID 0x%04x - trying other known VID/PIDs") % vid % pid).str() << std::endl; - -        // try known VID/PIDs next -        for (size_t i = 0; handles.size() == 0 && i < known_vid_pid_vector.size(); i++) +        std::vector<uhd::transport::usb_device_handle::vid_pid_pair_t> vid_pid_pair_list(1,uhd::transport::usb_device_handle::vid_pid_pair_t(vid,pid)); +        handles = uhd::transport::usb_device_handle::get_device_list(vid_pid_pair_list); +        if (handles.size() == 0)          { -            vp = known_vid_pid_vector[i]; -            handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid); +            if (user_supplied) +            { +                std::cerr << (boost::format("Failed to open device with VID 0x%04x and PID 0x%04x - trying other known VID/PIDs") % vid % pid).str() << std::endl; +            } + +            // try known VID/PIDs next +            for (size_t i = 0; handles.size() == 0 && i < known_vid_pid_vector.size(); i++) +            { +                vp = known_vid_pid_vector[i]; +                handles = uhd::transport::usb_device_handle::get_device_list(vp.vid, vp.pid); +            } +                     }          if (handles.size() > 0) @@ -281,7 +292,7 @@ int erase_eeprom(b200_iface::sptr& b200)  boost::int32_t main(boost::int32_t argc, char *argv[]) {      boost::uint16_t vid, pid; -    std::string pid_str, vid_str, fw_file, fpga_file; +    std::string pid_str, vid_str, fw_file, fpga_file, writevid_str, writepid_str;      bool user_supplied_vid_pid = false;      po::options_description visible("Allowed options"); @@ -295,7 +306,6 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) {          ("reset-device,D", "Reset the B2xx Device.")          ("reset-fpga,F", "Reset the FPGA (does not require re-programming.")          ("reset-usb,U", "Reset the USB subsystem on your host computer.") -        ("init-device,I", "Initialize a B2xx device.")          ("load-fw,W", po::value<std::string>(&fw_file),              "Load a firmware (hex) file into the FX3.")          ("load-fpga,L", po::value<std::string>(&fpga_file), @@ -305,9 +315,14 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) {      // Hidden options provided for testing - use at your own risk!      po::options_description hidden("Hidden options");      hidden.add_options() -    ("uninit-device,U", "Uninitialize a B2xx device.") +    ("init-device,I", "Initialize a B2xx device.") +    ("uninit-device", "Uninitialize a B2xx device.")      ("read-eeprom,R", "Read first 8 bytes of EEPROM") -    ("erase-eeprom,E", "Erase first 8 bytes of EEPROM"); +    ("erase-eeprom,E", "Erase first 8 bytes of EEPROM") +    ("write-vid", po::value<std::string>(&writevid_str), +        "Write VID field of EEPROM") +    ("write-pid", po::value<std::string>(&writepid_str), +        "Write PID field of EEPROM");      po::options_description desc;      desc.add(visible); @@ -486,9 +501,24 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) {       * Cypress VID/PID for the initial FW load, but we can initialize from any state. */      if (vm.count("init-device"))      { +        uint16_t writevid = B200_VENDOR_ID; +        uint16_t writepid = B200_PRODUCT_ID; +          /* Now, initialize the device. */ -        if (write_and_verify_eeprom(b200, eeprom_init_value_vector)) -            return -1; +           // Added for testing purposes - not exposed +        if (vm.count("write-vid") && vm.count("write-pid")) +        { +            try { +                  writevid = atoh(writevid_str); +                  writepid = atoh(writepid_str); +            } catch (std::exception &e) { +                  std::cerr << "Exception while parsing write VID and PID: " << e.what() << std:: endl; +                  return ~0; +            } +        } + +        std::cout << "Writing VID and PID to EEPROM..." << std::endl << std::endl; +        if (write_and_verify_eeprom(b200, construct_eeprom_init_value_vector(writevid, writepid))) return -1;          std::cout << "EEPROM initialized, resetting device..."              << std::endl << std::endl; diff --git a/host/utils/octoclock_firmware_burner.cpp b/host/utils/octoclock_firmware_burner.cpp index 9551ddd20..0a48caabd 100644 --- a/host/utils/octoclock_firmware_burner.cpp +++ b/host/utils/octoclock_firmware_burner.cpp @@ -37,7 +37,7 @@  #include <uhd/types/device_addr.hpp>  #include <uhd/types/time_spec.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_main.hpp> diff --git a/host/utils/usrp_n2xx_simple_net_burner.cpp b/host/utils/usrp_n2xx_simple_net_burner.cpp index dc83b6fdf..b06e67bb2 100644 --- a/host/utils/usrp_n2xx_simple_net_burner.cpp +++ b/host/utils/usrp_n2xx_simple_net_burner.cpp @@ -38,7 +38,7 @@  #include <uhd/transport/udp_simple.hpp>  #include <uhd/types/dict.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_main.hpp>  #include <uhd/utils/safe_call.hpp> diff --git a/host/utils/usrp_x3xx_fpga_burner.cpp b/host/utils/usrp_x3xx_fpga_burner.cpp index b849cfb92..abd5815e8 100644 --- a/host/utils/usrp_x3xx_fpga_burner.cpp +++ b/host/utils/usrp_x3xx_fpga_burner.cpp @@ -45,7 +45,7 @@  #include <uhd/device.hpp>  #include <uhd/types/device_addr.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_main.hpp>  #include <uhd/utils/safe_call.hpp> | 
