diff options
40 files changed, 2519 insertions, 11 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b25c15b81 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/host/apps/omap_debug/Makefile b/host/apps/omap_debug/Makefile new file mode 100644 index 000000000..31229d45c --- /dev/null +++ b/host/apps/omap_debug/Makefile @@ -0,0 +1,36 @@ +CFLAGS=-Wall -I../../lib/usrp/usrp_e/ + +all : usrp-e-spi usrp-e-i2c usrp-e-rw usrp-e-uart usrp-e-led usrp-e-ctl usrp-e-button usrp-e-uart-rx fpga-downloader usrp-e-gpio + +usrp-e-spi : usrp-e-spi.c + +usrp-e-i2c : usrp-e-i2c.c + +usrp-e-rw : usrp-e-rw.c +	gcc -o $@ $< -lpthread + +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 + +fpga-downloader : fpga-downloader.cc + +usrp-e-gpio : usrp-e-gpio.c + +clean : +	rm -f usrp-e-spi +	rm -f usrp-e-i2c +	rm -f usrp-e-rw +	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 fpga-downloader +	rm -f usrp-e-gpio diff --git a/host/apps/omap_debug/README b/host/apps/omap_debug/README new file mode 100644 index 000000000..bbe0c2cc4 --- /dev/null +++ b/host/apps/omap_debug/README @@ -0,0 +1 @@ +OMAP development tools go here diff --git a/host/apps/omap_debug/fetch-bin.sh b/host/apps/omap_debug/fetch-bin.sh new file mode 100755 index 000000000..d1502f95c --- /dev/null +++ b/host/apps/omap_debug/fetch-bin.sh @@ -0,0 +1,6 @@ +if [ $GHQ ]; then +	scp $GHQ_USER@astro:/workspace/usrp1-e-dev/u1e.bin . +else +	scp -P 8822 balister@192.168.1.10:src/git/fpgapriv/usrp2/top/u1e/build/u1e.bin . +fi +sync diff --git a/host/apps/omap_debug/fetch-kernel.sh b/host/apps/omap_debug/fetch-kernel.sh new file mode 100755 index 000000000..f32666adf --- /dev/null +++ b/host/apps/omap_debug/fetch-kernel.sh @@ -0,0 +1,6 @@ +if [ $GHQ]; then +	scp $GHQ_USER@astro:/workspace/usrp1-e-dev/kernel_usrp/arch/arm/boot/uImage /media/mmcblk0p1/uImage +else +	scp balister@192.168.1.167:src/git/kernel_usrp/arch/arm/boot/uImage /media/mmcblk0p1/uImage +sync + diff --git a/host/apps/omap_debug/fetch-module.sh b/host/apps/omap_debug/fetch-module.sh new file mode 100755 index 000000000..52fbd4040 --- /dev/null +++ b/host/apps/omap_debug/fetch-module.sh @@ -0,0 +1,6 @@ +if [ $GHQ ]; then +	scp $GHQ_USER@astro:/workspace/usrp1-e-dev/kernel_usrp/drivers/misc/usrp_e.ko /lib/modules/2.6.33-rc3/kernel/drivers/misc +else +	scp balister@192.168.1.167:src/git/kernel_usrp/drivers/misc/usrp_e.ko /lib/modules/2.6.33-rc3/kernel/drivers/misc +fi +sync diff --git a/host/apps/omap_debug/fetch-u-boot.sh b/host/apps/omap_debug/fetch-u-boot.sh new file mode 100755 index 000000000..a2a488fb2 --- /dev/null +++ b/host/apps/omap_debug/fetch-u-boot.sh @@ -0,0 +1,6 @@ +if [ $GHQ ]; then +	scp $GHQ_USER@astro:/workspace/usrp1-e-dev/u-boot-overo/u-boot.bin /media/mmcblk0p1/ +else +	scp balister@192.168.1.167:src/git/u-boot/u-boot.bin /media/mmcblk0p1/  +sync + diff --git a/host/apps/omap_debug/fpga-downloader.cc b/host/apps/omap_debug/fpga-downloader.cc new file mode 100644 index 000000000..fb96b64a3 --- /dev/null +++ b/host/apps/omap_debug/fpga-downloader.cc @@ -0,0 +1,251 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2008,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. +*/ + +#include <iostream> +#include <sstream> +#include <fstream> +#include <string> +#include <cstdlib> + +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <linux/spi/spidev.h> + +/* + * Configuration connections + * + * CCK    - MCSPI1_CLK + * DIN    - MCSPI1_MOSI + * PROG_B - GPIO_175     - output (change mux) + * DONE   - GPIO_173     - input  (change mux) + * INIT_B - GPIO_114     - input  (change mux) + * +*/ + +const unsigned int PROG_B = 175; +const unsigned int DONE   = 173; +const unsigned int INIT_B = 114; + +static std::string bit_file = "safe_u1e.bin"; + +const int BUF_SIZE = 4096; + +enum gpio_direction {IN, OUT}; + +class gpio { +	public: + +	gpio(unsigned int gpio_num, gpio_direction pin_direction); + +	bool get_value(); +	void set_value(bool state); + +	private: + +	std::stringstream base_path; +	std::fstream value_file;	 +}; + +class spidev { +	public: + +	spidev(std::string dev_name); +	~spidev(); + +	void send(char *wbuf, char *rbuf, unsigned int nbytes); + +	private: + +	int fd; + +}; + +gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) +{ +	std::fstream export_file; + +	export_file.open("/sys/class/gpio/export", std::ios::out); +	if (!export_file.is_open())  ///\todo Poor error handling +		std::cout << "Failed to open gpio export file." << std::endl; + +	export_file << gpio_num << std::endl; + +	base_path << "/sys/class/gpio/gpio" << gpio_num << std::flush; + +	std::fstream direction_file; +	std::string direction_file_name; + +	direction_file_name = base_path.str() + "/direction"; + +	direction_file.open(direction_file_name.c_str());  +	if (!direction_file.is_open()) +		std::cout << "Failed to open direction file." << std::endl; +	if (pin_direction == OUT) +		direction_file << "out" << std::endl; +	else +		direction_file << "in" << std::endl; + +	std::string value_file_name; + +	value_file_name = base_path.str() + "/value"; + +	value_file.open(value_file_name.c_str(), std::ios_base::in | std::ios_base::out); +	if (!value_file.is_open()) +		std::cout << "Failed to open value file." << std::endl; +} + +bool gpio::get_value() +{ + +	std::string val; + +	std::getline(value_file, val); +	value_file.seekg(0); + +	if (val == "0") +		return false; +	else if (val == "1") +		return true; +	else +		std::cout << "Data read from value file|" << val << "|" << std::endl; + +	return false; +} + +void gpio::set_value(bool state) +{ + +	if (state) +		value_file << "1" << std::endl; +	else +		value_file << "0" << std::endl; +} + +static void prepare_fpga_for_configuration(gpio &prog, gpio &init) +{ + +	prog.set_value(true); +	prog.set_value(false); +	prog.set_value(true); + +#if 0 +	bool ready_to_program(false); +	unsigned int count(0); +	do { +		ready_to_program = init.get_value(); +		count++; + +		sleep(1); +	} while (count < 10 && !ready_to_program); + +	if (count == 10) { +		std::cout << "FPGA not ready for programming." << std::endl; +		exit(-1); +	} +#endif +} + +spidev::spidev(std::string fname) +{ +	int ret; +	int mode = 0; +	int speed = 12000000; +	int bits = 8; + +	fd = open(fname.c_str(), O_RDWR); + +	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); +	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); +	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); +} +	 + +spidev::~spidev() +{ +	close(fd); +} + +void spidev::send(char *buf, char *rbuf, unsigned int nbytes) +{ +	int ret; + +	struct spi_ioc_transfer tr; +	tr.tx_buf = (unsigned long) buf; +	tr.rx_buf = (unsigned long) rbuf; +	tr.len = nbytes; +	tr.delay_usecs = 0; +	tr.speed_hz = 48000000; +	tr.bits_per_word = 8; + +	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);	 + +} + +static void send_file_to_fpga(std::string &file_name, gpio &error, gpio &done) +{ +	std::ifstream bitstream; + +	std::cout << "File name - " << file_name.c_str() << std::endl; + +	bitstream.open(file_name.c_str(), std::ios::binary); +	if (!bitstream.is_open()) +		std::cout << "File " << file_name << " not opened succesfully." << std::endl; + +	spidev spi("/dev/spidev1.0"); +	char buf[BUF_SIZE]; +	char rbuf[BUF_SIZE]; + +	do { +		bitstream.read(buf, BUF_SIZE); +		spi.send(buf, rbuf, bitstream.gcount()); + +		if (error.get_value()) +			std::cout << "INIT_B went high, error occured." << std::endl; + +		if (!done.get_value()) +			std::cout << "Configuration complete." << std::endl; + +	} while (bitstream.gcount() == BUF_SIZE); +} + +int main(int argc, char *argv[]) +{ + +	gpio gpio_prog_b(PROG_B, OUT); +	gpio gpio_init_b(INIT_B, IN); +	gpio gpio_done  (DONE,   IN); + +	if (argc == 2) +		bit_file = argv[1]; + +	std::cout << "FPGA config file: " << bit_file << std::endl; + +	prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); + +	std::cout << "Done = " << gpio_done.get_value() << std::endl; + +	send_file_to_fpga(bit_file, gpio_init_b, gpio_done); +} + diff --git a/host/apps/omap_debug/set_debug_pins.py b/host/apps/omap_debug/set_debug_pins.py new file mode 100755 index 000000000..0f9ecd7b9 --- /dev/null +++ b/host/apps/omap_debug/set_debug_pins.py @@ -0,0 +1,35 @@ +#!/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 new file mode 100644 index 000000000..36f4d700a --- /dev/null +++ b/host/apps/omap_debug/test.c @@ -0,0 +1,34 @@ +#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 new file mode 100644 index 000000000..4e4c21d9e --- /dev/null +++ b/host/apps/omap_debug/u1e-read-stream.c @@ -0,0 +1,21 @@ +#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 new file mode 100644 index 000000000..f13291491 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-button.c @@ -0,0 +1,56 @@ +#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 new file mode 100644 index 000000000..69c48ee6f --- /dev/null +++ b/host/apps/omap_debug/usrp-e-ctl.c @@ -0,0 +1,48 @@ +#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-gpio.c b/host/apps/omap_debug/usrp-e-gpio.c new file mode 100644 index 000000000..adef877d3 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-gpio.c @@ -0,0 +1,83 @@ +#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 i, test, data_in; + +	test = 0; +	if (argc > 1) +		test = 1; + +	fp = open("/dev/usrp_e0", O_RDWR); +	printf("fp = %d\n", fp); + +	write_reg(UE_REG_GPIO_TX_DDR, 0x0); +	write_reg(UE_REG_GPIO_RX_DDR, 0xFFFF); + +	for (i=0; i < 16; i++) { +		write_reg(UE_REG_GPIO_RX_IO, 1 << i); +		sleep(1); +		if (test) { +			data_in = read_reg(UE_REG_GPIO_TX_IO); +			if (data_in != (1 << i)) +				printf("Read failed, wrote: %X read: %X\n", \ +					1 << i, data_in); +		} +	} + +	write_reg(UE_REG_GPIO_RX_DDR, 0x0); +	write_reg(UE_REG_GPIO_TX_DDR, 0xFFFF); + +	sleep(1); + +	for (i=0; i < 16; i++) { +		write_reg(UE_REG_GPIO_TX_IO, 1 << i); +		sleep(1); +		if (test) { +			data_in = read_reg(UE_REG_GPIO_RX_IO); +			if (data_in != (1 << i)) +				printf("Read failed, wrote: %X read: %X\n", \ +					1 << i, data_in); +		} +	} + +	write_reg(UE_REG_GPIO_RX_DDR, 0x0); +	write_reg(UE_REG_GPIO_TX_DDR, 0x0); + +	return 0; +} diff --git a/host/apps/omap_debug/usrp-e-i2c.c b/host/apps/omap_debug/usrp-e-i2c.c new file mode 100644 index 000000000..19d64731b --- /dev/null +++ b/host/apps/omap_debug/usrp-e-i2c.c @@ -0,0 +1,71 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.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; +	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"); +		exit(-1); +	} + +	if (strcmp(argv[1], "r") == 0) { +		direction = 0; +	} else if (strcmp(argv[1], "w") == 0) { +		direction = 1; +	} else { +		return -1; +	} + +	address = atoi(argv[2]); + +	fp = open("/dev/usrp_e0", O_RDWR); +	printf("fp = %d\n", fp); + +	if (direction) { +		count = argc - 3; +	} else { +		count = atoi(argv[3]); +	} + +	i2c_msg = malloc(sizeof(i2c_msg) + count * sizeof(char)); + +	i2c_msg->addr = address; +	i2c_msg->len = count; + +	if (direction) { +		// Write + +		for (i=0; i<count; i++) { +			i2c_msg->data[i] = atoi(argv[3+i]); +		} + +		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("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-led.c b/host/apps/omap_debug/usrp-e-led.c new file mode 100644 index 000000000..d1b6c8996 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-led.c @@ -0,0 +1,35 @@ +#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 new file mode 100644 index 000000000..d548f7ccd --- /dev/null +++ b/host/apps/omap_debug/usrp-e-ram.c @@ -0,0 +1,25 @@ +#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 new file mode 100644 index 000000000..c28f018d5 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-read.c @@ -0,0 +1,18 @@ +#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-rw.c b/host/apps/omap_debug/usrp-e-rw.c new file mode 100644 index 000000000..5607166b0 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-rw.c @@ -0,0 +1,97 @@ +#include <stdio.h> +#include <sys/types.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdlib.h> +#include <unistd.h> + +struct pkt { +	int checksum; +	int seq_num; +	short data[1020]; +}; + +static int fp; + +static int calc_checksum(struct pkt *p) +{ +	int i, sum; + +	i = 0; +	sum = 0; + +	for (i=0; i<1020; i++) +		sum += p->data[i]; + +	sum += p->seq_num; + +	return sum; +} + +static void *read_thread(void *threadid) +{ +	int cnt, prev_seq_num; +	struct pkt rx_data; + +	printf("Greetings from the reading thread!\n"); + +	prev_seq_num = 0; + +	while (1) { +		cnt = read(fp, &rx_data, 2048); + +		if (rx_data.seq_num != prev_seq_num + 1) +			printf("Sequence number fail, current = %d, previous = %d\n", +				rx_data.seq_num, prev_seq_num); +		prev_seq_num = rx_data.seq_num; + +		if (calc_checksum(&rx_data) != rx_data.checksum) +			printf("Checksum fail packet = %d, expected = %d\n", +				calc_checksum(&rx_data), rx_data.checksum); +	} + +} + +static void *write_thread(void *threadid) +{ +	int seq_number, i, cnt; +	struct pkt tx_data; + +	printf("Greetings from the write thread!\n"); + +	for (i=0; i<1020; i++) +		tx_data.data[i] = random() >> 16; + + +	seq_number = 1; + +	while (1) { +		tx_data.seq_num = seq_number++; +		tx_data.checksum = calc_checksum(&tx_data); +		cnt = write(fp, &tx_data, 2048); +	} +} + + +int main(int argc, char *argv[]) +{ +	pthread_t tx, rx; +	long int t; + +	fp = open("/dev/usrp_e0", O_RDWR); +	printf("fp = %d\n", fp); + +	if (pthread_create(&rx, NULL, read_thread, (void *) t)) { +		printf("Failed to create rx thread\n"); +		exit(-1); +	} + +	if (pthread_create(&tx, NULL, write_thread, (void *) t)) { +		printf("Failed to create tx thread\n"); +		exit(-1); +	} + +	sleep(10000); + +	printf("Done sleeping\n"); +} diff --git a/host/apps/omap_debug/usrp-e-spi.c b/host/apps/omap_debug/usrp-e-spi.c new file mode 100644 index 000000000..f693d7db1 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-spi.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include <stdlib.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); + +	spi_dat.slave = slave; +	spi_dat.data = data; +	spi_dat.length = length; +	spi_dat.flags = 0; + +	if (*argv[1] == 'r') { +		spi_dat.readback = 1; +		ret = ioctl(fp, USRP_E_SPI, &spi_dat); +		printf("Data returned = %d\n", ret); +	} 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 new file mode 100644 index 000000000..24b417980 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-uart-rx.c @@ -0,0 +1,53 @@ +#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 new file mode 100644 index 000000000..2956c407f --- /dev/null +++ b/host/apps/omap_debug/usrp-e-uart.c @@ -0,0 +1,48 @@ +#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 new file mode 100644 index 000000000..903c0071f --- /dev/null +++ b/host/apps/omap_debug/usrp-e-write.c @@ -0,0 +1,21 @@ +#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 new file mode 100644 index 000000000..aa8ef3d57 --- /dev/null +++ b/host/apps/omap_debug/usrp_e.h @@ -0,0 +1,72 @@ +/* + *  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]; +}; + +// SPI interface + +#define UE_SPI_TXONLY	0 +#define UE_SPI_TXRX	1 + +// Defines for spi ctrl register +#define UE_SPI_CTRL_ASS		(1<<13) +#define UE_SPI_CTRL_IE		(1<<12) +#define UE_SPI_CTRL_LSB		(1<<11) +#define UE_SPI_CTRL_TXNEG	(1<<10) +#define UE_SPI_CTRL_RXNEG	(1<<9) +#define UE_SPI_CTRL_GO_BSY	(1<<8) +#define UE_SPI_CTRL_CHAR_LEN_MASK	0x7f + +#define UE_SPI_PUSH_RISE	0 +#define UE_SPI_PUSH_FALL	UE_SPI_CTRL_TXNEG +#define UE_SPI_LATCH_RISE	0 +#define UE_SPI_LATCH_FALL	UE_SPI_CTRL_RXNEG + +struct usrp_e_spi { +	__u8 readback; +	__u32 slave; +	__u32 data; +	__u32 length; +	__u32 flags; +}; + +struct usrp_e_i2c { +	__u8 addr; +	__u32 len; +	__u8 data[]; +}; + +#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_SPI		_IOW(USRP_E_IOC_MAGIC, 0x24, struct usrp_e_spi) +#define USRP_E_I2C_READ		_IOR(USRP_E_IOC_MAGIC, 0x25, struct usrp_e_i2c) +#define USRP_E_I2C_WRITE	_IOW(USRP_E_IOC_MAGIC, 0x26, struct usrp_e_i2c) + +#endif diff --git a/host/apps/omap_debug/write-eeprom.sh b/host/apps/omap_debug/write-eeprom.sh new file mode 100755 index 000000000..301b06f07 --- /dev/null +++ b/host/apps/omap_debug/write-eeprom.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +if [ $# -ne 3 ] && [ $# -ne 5 ]; +then +	echo "Usage:" +	echo "" +	echo "writeprom.sh deviceid rev fab_rev [envvar envsetting]" +	echo	 +	echo " deviceid   - expansion board device number from table:" +	echo  +	echo "   Summit     0x01" +	echo "   Tobi       0x02" +	echo "   Tobi Duo   0x03" +	echo "   Palo35     0x04" +	echo "   Palo43     0x05" +	echo "   Chestnut43 0x06" +	echo "   Pinto      0x07" +	echo +	echo " rev          - board revision (e.g. 0x00)" +	echo " fab_rev      - revision marking from pcb (e.g. R2411)" +	echo " envvar       - optional u-boot env variable name" +	echo "                (e.g. dvimode)" +	echo " envsetting   - optional u-boot env variable setting" +	echo "                (e.g. 1024x768MR-16@60)" +	exit 1 +fi + +fabrevision=$3 +if [ ${#fabrevision} -ge 8 ]; then +	echo "Error: fab revision string must less than 8 characters" +	exit 1 +fi + +envvar=$4 +if [ ${#envar} -ge 16 ]; then +	echo "Error: environment variable name string must less than 16 characters" +	exit 1 +fi + +envsetting=$5 +if [ ${#ensetting} -ge 64 ]; then +	echo "Error: environment setting string must less than 64 characters" +	exit 1 +fi + +bus=3 +device=0x51 +vendorid=0x03 + +i2cset -y $bus $device 0x00 0x00 +i2cset -y $bus $device 0x01 $vendorid +i2cset -y $bus $device 0x02 0x00 +i2cset -y $bus $device 0x03 $1 +i2cset -y $bus $device 0x04 $2 +i2cset -y $bus $device 0x05 00 + +let i=6 +hexdumpargs="'${#fabrevision}/1 \"0x%02x \"'" +command="echo -n \"$fabrevision\" | hexdump -e $hexdumpargs" +hex=$(eval $command) +for character in $hex; do +	i2cset -y $bus $device $i $character +	let i=$i+1 +done +i2cset -y $bus $device $i 0x00 + +if [ $# -eq 5 ] +then +	i2cset -y $bus $device 0x05 0x01 + +	let i=14 +	hexdumpargs="'${#envvar}/1 \"0x%02x \"'" +	command="echo -n \"$envvar\" | hexdump -e $hexdumpargs" +	hex=$(eval $command) +	for character in $hex; do +		i2cset -y $bus $device $i $character +		let i=$i+1 +	done + 	i2cset -y $bus $device $i 0x00 + +	let i=30 +	hexdumpargs="'${#envsetting}/1 \"0x%02x \"'" +	command="echo -n \"$envsetting\" | hexdump -e $hexdumpargs" +	hex=$(eval $command) +	for character in $hex; do +		i2cset -y $bus $device $i $character +		let i=$i+1 +	done	  +	i2cset -y $bus $device $i 0x00 +fi + + diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 42d74ad90..9342fbb7b 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -29,6 +29,7 @@ namespace uhd{       */      struct UHD_API clock_config_t{          enum ref_source_t { +            REF_AUTO = 'a', //automatic (device specific)              REF_INT  = 'i', //internal reference              REF_SMA  = 's', //external sma port              REF_MIMO = 'm'  //mimo cable (usrp2 only) diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index 7815a4fb9..c00daaaf0 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -31,7 +31,7 @@ INSTALL(FILES      dboard_manager.hpp      ### usrp headers ### -    usrp1e.hpp +    usrp_e.hpp      usrp2.hpp      ### utilities ### diff --git a/host/include/uhd/usrp/usrp1e.hpp b/host/include/uhd/usrp/usrp_e.hpp index cee9dc3d5..557058261 100644 --- a/host/include/uhd/usrp/usrp1e.hpp +++ b/host/include/uhd/usrp/usrp_e.hpp @@ -15,8 +15,8 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#ifndef INCLUDED_UHD_USRP_USRP1E_HPP -#define INCLUDED_UHD_USRP_USRP1E_HPP +#ifndef INCLUDED_UHD_USRP_USRP_E_HPP +#define INCLUDED_UHD_USRP_USRP_E_HPP  #include <uhd/config.hpp>  #include <uhd/device.hpp> @@ -24,25 +24,31 @@  namespace uhd{ namespace usrp{  /*! - * The usrp1e device class. + * The USRP-Embedded device class.   */ -class UHD_API usrp1e : public device{ +class UHD_API usrp_e : public device{  public:      /*! -     * Find usrp1e devices on the system via the device node. -     * \param hint a device addr with the usrp1e address filled in -     * \return a vector of device addresses for all usrp1es found +     * Find usrp_e devices on the system via the device node. +     * \param hint a device addr with the usrp_e address filled in +     * \return a vector of device addresses for all usrp-e's found       */      static device_addrs_t find(const device_addr_t &hint);      /*! -     * Make a usrp1e from a device address. +     * Make a usrp_e from a device address.       * \param addr the device address -     * \return a device sptr to a new usrp1e +     * \return a device sptr to a new usrp_e       */      static device::sptr make(const device_addr_t &addr); + +    /*! +     * Load the FPGA with an image file. +     * \param bin_file the name of the fpga image file +     */ +    static void load_fpga(const std::string &bin_file);  };  }} //namespace -#endif /* INCLUDED_UHD_USRP_USRP1E_HPP */ +#endif /* INCLUDED_UHD_USRP_USRP_E_HPP */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 9d328310f..3dfd54312 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -49,6 +49,39 @@ LIST(APPEND libuhd_sources  )  ######################################################################## +# Conditionally add the usrp1e sources +######################################################################## +MESSAGE(STATUS "Configuring usrp-e support...") + +INCLUDE(CheckIncludeFiles) +SET(usrp_e_required_headers +    linux/ioctl.h +    linux/spi/spidev.h +    linux/usrp_e.h +) +CHECK_INCLUDE_FILES( +    "${usrp_e_required_headers}" +    HAVE_USRP_E_REQUIRED_HEADERS +) + +IF(HAVE_USRP_E_REQUIRED_HEADERS) +    MESSAGE(STATUS "  Building usrp-e support.") +    LIST(APPEND libuhd_sources +        usrp/usrp_e/dboard_impl.cpp +        usrp/usrp_e/dboard_interface.cpp +        usrp/usrp_e/dsp_impl.cpp +        usrp/usrp_e/fpga-downloader.cc +        usrp/usrp_e/mboard_impl.cpp +        usrp/usrp_e/usrp_e_impl.cpp +    ) +ELSE(HAVE_USRP_E_REQUIRED_HEADERS) +    MESSAGE(STATUS "  Skipping usrp-e support.") +    LIST(APPEND libuhd_sources +        usrp/usrp_e/usrp_e_none.cpp +    ) +ENDIF(HAVE_USRP_E_REQUIRED_HEADERS) + +########################################################################  # Setup defines for module loading  ########################################################################  MESSAGE(STATUS "Configuring module loading...") diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp new file mode 100644 index 000000000..7c87361e0 --- /dev/null +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -0,0 +1,75 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/bind.hpp> +#include "usrp_e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * Dboard Initialization + **********************************************************************/ +void usrp_e_impl::dboard_init(void){ +    dboard_id_t rx_dboard_id = dboard_id::NONE; //TODO get these from the eeprom +    dboard_id_t tx_dboard_id = dboard_id::NONE; + +    //create a new dboard interface and manager +    dboard_interface::sptr dboard_interface( +        make_usrp_e_dboard_interface(this) +    ); +    _dboard_manager = dboard_manager::make( +        rx_dboard_id, tx_dboard_id, dboard_interface +    ); + +    //setup the dboard proxies +    _rx_dboard_proxy = wax_obj_proxy::make( +        boost::bind(&usrp_e_impl::rx_dboard_get, this, _1, _2), +        boost::bind(&usrp_e_impl::rx_dboard_set, this, _1, _2) +    ); +    _tx_dboard_proxy = wax_obj_proxy::make( +        boost::bind(&usrp_e_impl::tx_dboard_get, this, _1, _2), +        boost::bind(&usrp_e_impl::tx_dboard_set, this, _1, _2) +    ); +} + +/*********************************************************************** + * RX Dboard Get + **********************************************************************/ +void usrp_e_impl::rx_dboard_get(const wax::obj &, wax::obj &){ +     +} + +/*********************************************************************** + * RX Dboard Set + **********************************************************************/ +void usrp_e_impl::rx_dboard_set(const wax::obj &, const wax::obj &){ +     +} + +/*********************************************************************** + * TX Dboard Get + **********************************************************************/ +void usrp_e_impl::tx_dboard_get(const wax::obj &, wax::obj &){ +     +} + +/*********************************************************************** + * TX Dboard Set + **********************************************************************/ +void usrp_e_impl::tx_dboard_set(const wax::obj &, const wax::obj &){ +     +} diff --git a/host/lib/usrp/usrp_e/dboard_interface.cpp b/host/lib/usrp/usrp_e/dboard_interface.cpp new file mode 100644 index 000000000..47948f3d0 --- /dev/null +++ b/host/lib/usrp/usrp_e/dboard_interface.cpp @@ -0,0 +1,212 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include <uhd/types/dict.hpp> +#include <uhd/utils/assert.hpp> +#include <boost/assign/list_of.hpp> +#include <algorithm> //std::copy +#include <linux/usrp_e.h> + +using namespace uhd::usrp; + +class usrp_e_dboard_interface : public dboard_interface{ +public: +    usrp_e_dboard_interface(usrp_e_impl *impl); +    ~usrp_e_dboard_interface(void); + +    void write_aux_dac(unit_type_t, int, int); +    int read_aux_adc(unit_type_t, int); + +    void set_atr_reg(gpio_bank_t, atr_reg_t, boost::uint16_t); +    void set_gpio_ddr(gpio_bank_t, boost::uint16_t); +    boost::uint16_t read_gpio(gpio_bank_t); + +    void write_i2c(int, const byte_vector_t &); +    byte_vector_t read_i2c(int, size_t); + +    double get_rx_clock_rate(void); +    double get_tx_clock_rate(void); + +private: +    byte_vector_t transact_spi( +        spi_dev_t dev, +        spi_edge_t edge, +        const byte_vector_t &buf, +        bool readback +    ); + +    usrp_e_impl *_impl; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +dboard_interface::sptr make_usrp_e_dboard_interface(usrp_e_impl *impl){ +    return dboard_interface::sptr(new usrp_e_dboard_interface(impl)); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp_e_dboard_interface::usrp_e_dboard_interface(usrp_e_impl *impl){ +    _impl = impl; +} + +usrp_e_dboard_interface::~usrp_e_dboard_interface(void){ +    /* NOP */ +} + +/*********************************************************************** + * Clock Rates + **********************************************************************/ +double usrp_e_dboard_interface::get_rx_clock_rate(void){ +    throw std::runtime_error("not implemented"); +} + +double usrp_e_dboard_interface::get_tx_clock_rate(void){ +    throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * GPIO + **********************************************************************/ +void usrp_e_dboard_interface::set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value){ +    //define mapping of gpio bank to register address +    static const uhd::dict<gpio_bank_t, boost::uint32_t> bank_to_addr = boost::assign::map_list_of +        (GPIO_BANK_RX, UE_REG_GPIO_RX_DDR) +        (GPIO_BANK_TX, UE_REG_GPIO_TX_DDR) +    ; +    _impl->poke16(bank_to_addr[bank], value); +} + +boost::uint16_t usrp_e_dboard_interface::read_gpio(gpio_bank_t bank){ +    //define mapping of gpio bank to register address +    static const uhd::dict<gpio_bank_t, boost::uint32_t> bank_to_addr = boost::assign::map_list_of +        (GPIO_BANK_RX, UE_REG_GPIO_RX_IO) +        (GPIO_BANK_TX, UE_REG_GPIO_TX_IO) +    ; +    return _impl->peek16(bank_to_addr[bank]); +} + +void usrp_e_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost::uint16_t value){ +    //define mapping of bank to atr regs to register address +    static const uhd::dict< +        gpio_bank_t, uhd::dict<atr_reg_t, boost::uint32_t> +    > bank_to_atr_to_addr = boost::assign::map_list_of +        (GPIO_BANK_RX, boost::assign::map_list_of +            (ATR_REG_IDLE,        UE_REG_ATR_IDLE_RXSIDE) +            (ATR_REG_TX_ONLY,     UE_REG_ATR_INTX_RXSIDE) +            (ATR_REG_RX_ONLY,     UE_REG_ATR_INRX_RXSIDE) +            (ATR_REG_FULL_DUPLEX, UE_REG_ATR_FULL_RXSIDE) +        ) +        (GPIO_BANK_TX, boost::assign::map_list_of +            (ATR_REG_IDLE,        UE_REG_ATR_IDLE_TXSIDE) +            (ATR_REG_TX_ONLY,     UE_REG_ATR_INTX_TXSIDE) +            (ATR_REG_RX_ONLY,     UE_REG_ATR_INRX_TXSIDE) +            (ATR_REG_FULL_DUPLEX, UE_REG_ATR_FULL_TXSIDE) +        ) +    ; +    _impl->poke16(bank_to_atr_to_addr[bank][atr], value); +} + +/*********************************************************************** + * SPI + **********************************************************************/ +dboard_interface::byte_vector_t usrp_e_dboard_interface::transact_spi( +    spi_dev_t dev, +    spi_edge_t edge, +    const byte_vector_t &buf, +    bool readback +){ +    //load data struct +    usrp_e_spi data; +    data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; +    data.slave = (dev == SPI_DEV_RX)? UE_SPI_CTRL_RXNEG : UE_SPI_CTRL_TXNEG; +    data.length = buf.size() * 8; //bytes to bits +    boost::uint8_t *data_bytes = reinterpret_cast<boost::uint8_t*>(&data.data); + +    //load the data +    ASSERT_THROW(buf.size() <= sizeof(data.data)); +    std::copy(buf.begin(), buf.end(), data_bytes); + +    //load the flags +    data.flags = 0; +    data.flags |= (edge == SPI_EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; +    data.flags |= (edge == SPI_EDGE_RISE)? UE_SPI_PUSH_RISE  : UE_SPI_PUSH_FALL; + +    //call the spi ioctl +    _impl->ioctl(USRP_E_SPI, &data); + +    //unload the data +    byte_vector_t ret(data.length/8); //bits to bytes +    ASSERT_THROW(ret.size() <= sizeof(data.data)); +    std::copy(data_bytes, data_bytes+ret.size(), ret.begin()); +    return ret; +} + +/*********************************************************************** + * I2C + **********************************************************************/ +static const size_t max_i2c_data_bytes = 10; + +void usrp_e_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){ +    //allocate some memory for this transaction +    ASSERT_THROW(buf.size() <= max_i2c_data_bytes); +    boost::uint8_t mem[sizeof(usrp_e_i2c) + max_i2c_data_bytes]; + +    //load the data struct +    usrp_e_i2c &data = reinterpret_cast<usrp_e_i2c&>(mem); +    data.addr = i2c_addr; +    data.len = buf.size(); +    std::copy(buf.begin(), buf.end(), data.data); + +    //call the spi ioctl +    _impl->ioctl(USRP_E_I2C_WRITE, &data); +} + +dboard_interface::byte_vector_t usrp_e_dboard_interface::read_i2c(int i2c_addr, size_t num_bytes){ +    //allocate some memory for this transaction +    ASSERT_THROW(num_bytes <= max_i2c_data_bytes); +    boost::uint8_t mem[sizeof(usrp_e_i2c) + max_i2c_data_bytes]; + +    //load the data struct +    usrp_e_i2c &data = reinterpret_cast<usrp_e_i2c&>(mem); +    data.addr = i2c_addr; +    data.len = num_bytes; + +    //call the spi ioctl +    _impl->ioctl(USRP_E_I2C_READ, &data); + +    //unload the data +    byte_vector_t ret(data.len); +    ASSERT_THROW(ret.size() == num_bytes); +    std::copy(data.data, data.data+ret.size(), ret.begin()); +    return ret; +} + +/*********************************************************************** + * Aux DAX/ADC + **********************************************************************/ +void usrp_e_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, int which, int value){ +    throw std::runtime_error("not implemented"); +} + +int usrp_e_dboard_interface::read_aux_adc(dboard_interface::unit_type_t unit, int which){ +    throw std::runtime_error("not implemented"); +} diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp new file mode 100644 index 000000000..e32c76a3d --- /dev/null +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -0,0 +1,69 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/bind.hpp> +#include "usrp_e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * RX DDC Initialization + **********************************************************************/ +void usrp_e_impl::rx_ddc_init(void){ +    _rx_ddc_proxy = wax_obj_proxy::make( +        boost::bind(&usrp_e_impl::rx_ddc_get, this, _1, _2), +        boost::bind(&usrp_e_impl::rx_ddc_set, this, _1, _2) +    ); +} + +/*********************************************************************** + * RX DDC Get + **********************************************************************/ +void usrp_e_impl::rx_ddc_get(const wax::obj &, wax::obj &){ +     +} + +/*********************************************************************** + * RX DDC Set + **********************************************************************/ +void usrp_e_impl::rx_ddc_set(const wax::obj &, const wax::obj &){ +     +} + +/*********************************************************************** + * TX DUC Initialization + **********************************************************************/ +void usrp_e_impl::tx_duc_init(void){ +    _tx_duc_proxy = wax_obj_proxy::make( +        boost::bind(&usrp_e_impl::tx_duc_get, this, _1, _2), +        boost::bind(&usrp_e_impl::tx_duc_set, this, _1, _2) +    ); +} + +/*********************************************************************** + * TX DUC Get + **********************************************************************/ +void usrp_e_impl::tx_duc_get(const wax::obj &, wax::obj &){ +     +} + +/*********************************************************************** + * TX DUC Set + **********************************************************************/ +void usrp_e_impl::tx_duc_set(const wax::obj &, const wax::obj &){ +     +} diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc new file mode 100644 index 000000000..4429786a9 --- /dev/null +++ b/host/lib/usrp/usrp_e/fpga-downloader.cc @@ -0,0 +1,262 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <iostream> +#include <sstream> +#include <fstream> +#include <string> +#include <cstdlib> + +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <linux/spi/spidev.h> + +/* + * Configuration connections + * + * CCK    - MCSPI1_CLK + * DIN    - MCSPI1_MOSI + * PROG_B - GPIO_175     - output (change mux) + * DONE   - GPIO_173     - input  (change mux) + * INIT_B - GPIO_114     - input  (change mux) + * +*/ + +const unsigned int PROG_B = 175; +const unsigned int DONE   = 173; +const unsigned int INIT_B = 114; + +//static std::string bit_file = "safe_u1e.bin"; + +const int BUF_SIZE = 4096; + +enum gpio_direction {IN, OUT}; + +class gpio { +	public: + +	gpio(unsigned int gpio_num, gpio_direction pin_direction); + +	bool get_value(); +	void set_value(bool state); + +	private: + +	std::stringstream base_path; +	std::fstream value_file;	 +}; + +class spidev { +	public: + +	spidev(std::string dev_name); +	~spidev(); + +	void send(char *wbuf, char *rbuf, unsigned int nbytes); + +	private: + +	int fd; + +}; + +gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) +{ +	std::fstream export_file; + +	export_file.open("/sys/class/gpio/export", std::ios::out); +	if (!export_file.is_open())  ///\todo Poor error handling +		std::cout << "Failed to open gpio export file." << std::endl; + +	export_file << gpio_num << std::endl; + +	base_path << "/sys/class/gpio/gpio" << gpio_num << std::flush; + +	std::fstream direction_file; +	std::string direction_file_name; + +	direction_file_name = base_path.str() + "/direction"; + +	direction_file.open(direction_file_name.c_str());  +	if (!direction_file.is_open()) +		std::cout << "Failed to open direction file." << std::endl; +	if (pin_direction == OUT) +		direction_file << "out" << std::endl; +	else +		direction_file << "in" << std::endl; + +	std::string value_file_name; + +	value_file_name = base_path.str() + "/value"; + +	value_file.open(value_file_name.c_str(), std::ios_base::in | std::ios_base::out); +	if (!value_file.is_open()) +		std::cout << "Failed to open value file." << std::endl; +} + +bool gpio::get_value() +{ + +	std::string val; + +	std::getline(value_file, val); +	value_file.seekg(0); + +	if (val == "0") +		return false; +	else if (val == "1") +		return true; +	else +		std::cout << "Data read from value file|" << val << "|" << std::endl; + +	return false; +} + +void gpio::set_value(bool state) +{ + +	if (state) +		value_file << "1" << std::endl; +	else +		value_file << "0" << std::endl; +} + +static void prepare_fpga_for_configuration(gpio &prog, gpio &)//init) +{ + +	prog.set_value(true); +	prog.set_value(false); +	prog.set_value(true); + +#if 0 +	bool ready_to_program(false); +	unsigned int count(0); +	do { +		ready_to_program = init.get_value(); +		count++; + +		sleep(1); +	} while (count < 10 && !ready_to_program); + +	if (count == 10) { +		std::cout << "FPGA not ready for programming." << std::endl; +		exit(-1); +	} +#endif +} + +spidev::spidev(std::string fname) +{ +	int ret; +	int mode = 0; +	int speed = 12000000; +	int bits = 8; + +	fd = open(fname.c_str(), O_RDWR); + +	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); +	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); +	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); +} +	 + +spidev::~spidev() +{ +	close(fd); +} + +void spidev::send(char *buf, char *rbuf, unsigned int nbytes) +{ +	int ret; + +	struct spi_ioc_transfer tr; +	tr.tx_buf = (unsigned long) buf; +	tr.rx_buf = (unsigned long) rbuf; +	tr.len = nbytes; +	tr.delay_usecs = 0; +	tr.speed_hz = 48000000; +	tr.bits_per_word = 8; + +	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);	 + +} + +static void send_file_to_fpga(const std::string &file_name, gpio &error, gpio &done) +{ +	std::ifstream bitstream; + +	std::cout << "File name - " << file_name.c_str() << std::endl; + +	bitstream.open(file_name.c_str(), std::ios::binary); +	if (!bitstream.is_open()) +		std::cout << "File " << file_name << " not opened succesfully." << std::endl; + +	spidev spi("/dev/spidev1.0"); +	char buf[BUF_SIZE]; +	char rbuf[BUF_SIZE]; + +	do { +		bitstream.read(buf, BUF_SIZE); +		spi.send(buf, rbuf, bitstream.gcount()); + +		if (error.get_value()) +			std::cout << "INIT_B went high, error occured." << std::endl; + +		if (!done.get_value()) +			std::cout << "Configuration complete." << std::endl; + +	} while (bitstream.gcount() == BUF_SIZE); +} + +/* +int main(int argc, char *argv[]) +{ + +	gpio gpio_prog_b(PROG_B, OUT); +	gpio gpio_init_b(INIT_B, IN); +	gpio gpio_done  (DONE,   IN); + +	if (argc == 2) +		bit_file = argv[1]; + +	std::cout << "FPGA config file: " << bit_file << std::endl; + +	prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); + +	std::cout << "Done = " << gpio_done.get_value() << std::endl; + +	send_file_to_fpga(bit_file, gpio_init_b, gpio_done); +} +*/ + +#include <uhd/usrp/usrp_e.hpp> +void uhd::usrp::usrp_e::load_fpga(const std::string &bin_file){ +	gpio gpio_prog_b(PROG_B, OUT); +	gpio gpio_init_b(INIT_B, IN); +	gpio gpio_done  (DONE,   IN); + +	std::cout << "FPGA config file: " << bin_file << std::endl; + +	prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); + +	std::cout << "Done = " << gpio_done.get_value() << std::endl; + +	send_file_to_fpga(bin_file, gpio_init_b, gpio_done); +} diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp new file mode 100644 index 000000000..ba15c394d --- /dev/null +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -0,0 +1,116 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include "usrp_e_impl.hpp" +#include <uhd/utils/assert.hpp> +#include <uhd/usrp/mboard_props.hpp> +#include <boost/bind.hpp> + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Mboard Initialization + **********************************************************************/ +void usrp_e_impl::mboard_init(void){ +    _mboard_proxy = wax_obj_proxy::make( +        boost::bind(&usrp_e_impl::mboard_get, this, _1, _2), +        boost::bind(&usrp_e_impl::mboard_set, this, _1, _2) +    ); + +    //init the clock config +    _clock_config.ref_source = clock_config_t::REF_AUTO; +    _clock_config.pps_source = clock_config_t::PPS_SMA; + +    //TODO poke the clock config regs +} + +/*********************************************************************** + * Mboard Get + **********************************************************************/ +void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ +    wax::obj key; std::string name; +    boost::tie(key, name) = extract_named_prop(key_); + + +    //handle the get request conditioned on the key +    switch(key.as<mboard_prop_t>()){ +    case MBOARD_PROP_NAME: +        val = std::string("usrp-e mboard"); +        return; + +    case MBOARD_PROP_OTHERS: +        val = prop_names_t(); +        return; + +    case MBOARD_PROP_RX_DBOARD: +        ASSERT_THROW(name == ""); +        val = _rx_dboard_proxy->get_link(); +        return; + +    case MBOARD_PROP_RX_DBOARD_NAMES: +        val = prop_names_t(1, ""); //vector of size 1 with empty string +        return; + +    case MBOARD_PROP_TX_DBOARD: +        ASSERT_THROW(name == ""); +        val = _tx_dboard_proxy->get_link(); +        return; + +    case MBOARD_PROP_TX_DBOARD_NAMES: +        val = prop_names_t(1, ""); //vector of size 1 with empty string +        return; + +    case MBOARD_PROP_CLOCK_RATE: +        //val = TODO probably remove this property +        return; + +    case MBOARD_PROP_RX_DSP: +        ASSERT_THROW(name == "ddc0"); +        val = _rx_ddc_proxy->get_link(); +        return; + +    case MBOARD_PROP_RX_DSP_NAMES: +        val = prop_names_t(1, "ddc0"); +        return; + +    case MBOARD_PROP_TX_DSP: +        ASSERT_THROW(name == "duc0"); +        val = _tx_duc_proxy->get_link(); +        return; + +    case MBOARD_PROP_TX_DSP_NAMES: +        val = prop_names_t(1, "duc0"); +        return; + +    case MBOARD_PROP_CLOCK_CONFIG: +        val = _clock_config; +        return; + +    case MBOARD_PROP_TIME_NOW: +    case MBOARD_PROP_TIME_NEXT_PPS: +        throw std::runtime_error("Error: trying to get write-only property on usrp-e mboard"); + +    } +} + +/*********************************************************************** + * Mboard Set + **********************************************************************/ +void usrp_e_impl::mboard_set(const wax::obj &, const wax::obj &){ +     +} diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp new file mode 100644 index 000000000..3fefd6787 --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -0,0 +1,227 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include "usrp_e_impl.hpp" +#include <uhd/usrp/device_props.hpp> +#include <uhd/utils/assert.hpp> +#include <uhd/utils/static.hpp> +#include <boost/format.hpp> +#include <boost/filesystem.hpp> +#include <fcntl.h> //open +#include <sys/ioctl.h> //ioctl +#include <linux/usrp_e.h> + +using namespace uhd; +using namespace uhd::usrp; +namespace fs = boost::filesystem; + +UHD_STATIC_BLOCK(register_usrp_e_device){ +    device::register_device(&usrp_e::find, &usrp_e::make); +} + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static std::string abs_path(const std::string &file_path){ +    return fs::system_complete(fs::path(file_path)).file_string(); +} + +/*********************************************************************** + * Discovery + **********************************************************************/ +device_addrs_t usrp_e::find(const device_addr_t &device_addr){ +    device_addrs_t usrp_e_addrs; + +    //if a node was provided, use it and only it +    if (device_addr.has_key("node")){ +        if (not fs::exists(device_addr["node"])) return usrp_e_addrs; +        device_addr_t new_addr; +        new_addr["name"] = "USRP-E"; +        new_addr["node"] = abs_path(device_addr["node"]); +        usrp_e_addrs.push_back(new_addr); +    } + +    //otherwise look for a few nodes at small indexes +    else{ +        for(size_t i = 0; i < 5; i++){ +            std::string node = str(boost::format("/dev/usrp1_e%d") % i); +            if (not fs::exists(node)) continue; +            device_addr_t new_addr; +            new_addr["name"] = "USRP-E"; +            new_addr["node"] = abs_path(node); +            usrp_e_addrs.push_back(new_addr); +        } +    } + +    return usrp_e_addrs; +} + +/*********************************************************************** + * Make + **********************************************************************/ +device::sptr usrp_e::make(const device_addr_t &device_addr){ +    return sptr(new usrp_e_impl(device_addr["node"])); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp_e_impl::usrp_e_impl(const std::string &node){ +    //open the device node and check file descriptor +    if ((_node_fd = ::open(node.c_str(), O_RDWR)) < 0){ +        throw std::runtime_error(str( +            boost::format("Failed to open %s") % node +        )); +    } + +    //initialize the mboard +    mboard_init(); + +    //initialize the dboards +    dboard_init(); + +    //initialize the dsps +    rx_ddc_init(); +    tx_duc_init(); +} + +usrp_e_impl::~usrp_e_impl(void){ +    //close the device node file descriptor +    ::close(_node_fd); +} + +/*********************************************************************** + * Misc Methods + **********************************************************************/ +void usrp_e_impl::ioctl(int request, void *mem){ +    if (::ioctl(_node_fd, request, mem) < 0){ +        throw std::runtime_error(str( +            boost::format("ioctl failed with request %d") % request +        )); +    } +} + +void usrp_e_impl::poke32(boost::uint32_t addr, boost::uint32_t value){ +    //load the data struct +    usrp_e_ctl32 data; +    data.offset = addr; +    data.count = 1; +    data.buf[0] = value; + +    //call the ioctl +    this->ioctl(USRP_E_WRITE_CTL32, &data); +} + +void usrp_e_impl::poke16(boost::uint32_t addr, boost::uint16_t value){ +    //load the data struct +    usrp_e_ctl16 data; +    data.offset = addr; +    data.count = 1; +    data.buf[0] = value; + +    //call the ioctl +    this->ioctl(USRP_E_WRITE_CTL16, &data); +} + +boost::uint32_t usrp_e_impl::peek32(boost::uint32_t addr){ +    //load the data struct +    usrp_e_ctl32 data; +    data.offset = addr; +    data.count = 1; + +    //call the ioctl +    this->ioctl(USRP_E_READ_CTL32, &data); + +    return data.buf[0]; +} + +boost::uint16_t usrp_e_impl::peek16(boost::uint32_t addr){ +    //load the data struct +    usrp_e_ctl16 data; +    data.offset = addr; +    data.count = 1; + +    //call the ioctl +    this->ioctl(USRP_E_READ_CTL16, &data); + +    return data.buf[0]; +} + +/*********************************************************************** + * Device Get + **********************************************************************/ +void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ +    wax::obj key; std::string name; +    boost::tie(key, name) = extract_named_prop(key_); + +    //handle the get request conditioned on the key +    switch(key.as<device_prop_t>()){ +    case DEVICE_PROP_NAME: +        val = std::string("usrp-e device"); +        return; + +    case DEVICE_PROP_MBOARD: +        ASSERT_THROW(name == ""); +        val = _mboard_proxy->get_link(); +        return; + +    case DEVICE_PROP_MBOARD_NAMES: +        val = prop_names_t(1, ""); //vector of size 1 with empty string +        return; + +    case DEVICE_PROP_MAX_RX_SAMPLES: +        val = size_t(_max_num_samples); +        return; + +    case DEVICE_PROP_MAX_TX_SAMPLES: +        val = size_t(_max_num_samples); +        return; + +    } +} + +/*********************************************************************** + * Device Set + **********************************************************************/ +void usrp_e_impl::set(const wax::obj &, const wax::obj &){ +    throw std::runtime_error("Cannot set in usrp-e device"); +} + +/*********************************************************************** + * Device IO (TODO) + **********************************************************************/ +size_t usrp_e_impl::send( +    const boost::asio::const_buffer &, +    const uhd::tx_metadata_t &, +    const io_type_t & +){ +    if (true){ +        throw std::runtime_error(str(boost::format("usrp-e send: cannot handle type \"%s\"") % "")); +    } +    return 0; +} + +size_t usrp_e_impl::recv( +    const boost::asio::mutable_buffer &, +    uhd::rx_metadata_t &, +    const io_type_t & +){ +    if (true){ +        throw std::runtime_error(str(boost::format("usrp-e recv: cannot handle type \"%s\"") % "")); +    } +    return 0; +} diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp new file mode 100644 index 000000000..21023ae55 --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -0,0 +1,144 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/types/clock_config.hpp> +#include <uhd/usrp/usrp_e.hpp> +#include <uhd/usrp/dboard_manager.hpp> + +#ifndef INCLUDED_USRP_E_IMPL_HPP +#define INCLUDED_USRP_E_IMPL_HPP + +class usrp_e_impl; // dummy class declaration + +/*! + * Make a usrp_e dboard interface. + * \param impl a pointer to the usrp_e impl object + * \return a sptr to a new dboard interface + */ +uhd::usrp::dboard_interface::sptr make_usrp_e_dboard_interface(usrp_e_impl *impl); + +/*! + * Simple wax obj proxy class: + * Provides a wax obj interface for a set and a get function. + * This allows us to create nested properties structures + * while maintaining flattened code within the implementation. + */ +class wax_obj_proxy : public wax::obj{ +public: +    typedef boost::function<void(const wax::obj &, wax::obj &)>       get_t; +    typedef boost::function<void(const wax::obj &, const wax::obj &)> set_t; +    typedef boost::shared_ptr<wax_obj_proxy> sptr; + +    static sptr make(const get_t &get, const set_t &set){ +        return sptr(new wax_obj_proxy(get, set)); +    } + +    ~wax_obj_proxy(void){ +        /* NOP */ +    } + +private: +    get_t _get; +    set_t _set; + +    wax_obj_proxy(const get_t &get, const set_t &set){ +        _get = get; +        _set = set; +    }; + +    void get(const wax::obj &key, wax::obj &val){ +        return _get(key, val); +    } + +    void set(const wax::obj &key, const wax::obj &val){ +        return _set(key, val); +    } +}; + +/*! + * USRP1E implementation guts: + * The implementation details are encapsulated here. + * Handles properties on the mboard, dboard, dsps... + */ +class usrp_e_impl : public uhd::device{ +public: +    //structors +    usrp_e_impl(const std::string &node); +    ~usrp_e_impl(void); + +    //the io interface +    size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &); +    size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &); + +    /*! +     * Perform an ioctl call on the device node file descriptor. +     * This will throw when the internal ioctl call fails. +     * \param request the control word +     * \param mem pointer to some memory +     */ +    void ioctl(int request, void *mem); + +    //peekers and pokers +    void poke32(boost::uint32_t addr, boost::uint32_t value); +    void poke16(boost::uint32_t addr, boost::uint16_t value); +    boost::uint32_t peek32(boost::uint32_t addr); +    boost::uint16_t peek16(boost::uint32_t addr); + +private: +    static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); +    int _node_fd; + +    uhd::clock_config_t _clock_config; + +    //device functions and settings +    void get(const wax::obj &, wax::obj &); +    void set(const wax::obj &, const wax::obj &); + +    //mboard functions and settings +    void mboard_init(void); +    void mboard_get(const wax::obj &, wax::obj &); +    void mboard_set(const wax::obj &, const wax::obj &); +    wax_obj_proxy::sptr _mboard_proxy; + +    //xx dboard functions and settings +    void dboard_init(void); +    uhd::usrp::dboard_manager::sptr _dboard_manager; + +    //rx dboard functions and settings +    void rx_dboard_get(const wax::obj &, wax::obj &); +    void rx_dboard_set(const wax::obj &, const wax::obj &); +    wax_obj_proxy::sptr _rx_dboard_proxy; + +    //tx dboard functions and settings +    void tx_dboard_get(const wax::obj &, wax::obj &); +    void tx_dboard_set(const wax::obj &, const wax::obj &); +    wax_obj_proxy::sptr _tx_dboard_proxy; + +    //rx ddc functions and settings +    void rx_ddc_init(void); +    void rx_ddc_get(const wax::obj &, wax::obj &); +    void rx_ddc_set(const wax::obj &, const wax::obj &); +    wax_obj_proxy::sptr _rx_ddc_proxy; + +    //tx duc functions and settings +    void tx_duc_init(void); +    void tx_duc_get(const wax::obj &, wax::obj &); +    void tx_duc_set(const wax::obj &, const wax::obj &); +    wax_obj_proxy::sptr _tx_duc_proxy; +}; + +#endif /* INCLUDED_USRP_E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp_e/usrp_e_none.cpp b/host/lib/usrp/usrp_e/usrp_e_none.cpp new file mode 100644 index 000000000..09a3c6946 --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_none.cpp @@ -0,0 +1,38 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/usrp_e.hpp> + +using namespace uhd; +using namespace uhd::usrp; + +/*! + * This file defines the usrp1e discover and make functions + * when the required kernel module headers are not present. + */ + +device_addrs_t usrp_e::find(const device_addr_t &){ +    return device_addrs_t(); //return empty list +} + +device::sptr usrp_e::make(const device_addr_t &){ +    throw std::runtime_error("this build has no usrp1e support"); +} + +void usrp_e::load_fpga(const std::string &){ +    throw std::runtime_error("this build has no usrp1e support"); +} diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp new file mode 100644 index 000000000..edd87e649 --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -0,0 +1,106 @@ + + +//////////////////////////////////////////////////////////////// +// +//         Memory map for embedded wishbone bus +// +//////////////////////////////////////////////////////////////// + +// All addresses are byte addresses.  All accesses are word (16-bit) accesses. +//  This means that address bit 0 is usually 0. +//  There are 11 bits of address for the control. + +#ifndef __USRP_E_REGS_H +#define __USRP_E_REGS_H + +///////////////////////////////////////////////////// +// Slave pointers + +#define UE_REG_SLAVE(n) ((n)<<7) + +///////////////////////////////////////////////////// +// Slave 0 -- Misc Regs + +#define UE_REG_MISC_BASE UE_REG_SLAVE(0) + +#define UE_REG_MISC_LED        UE_REG_MISC_BASE + 0 +#define UE_REG_MISC_SW         UE_REG_MISC_BASE + 2 +#define UE_REG_MISC_CGEN_CTRL  UE_REG_MISC_BASE + 4 +#define UE_REG_MISC_CGEN_ST    UE_REG_MISC_BASE + 6 +#define UE_REG_MISC_TEST       UE_REG_MISC_BASE + 8 + +///////////////////////////////////////////////////// +// Slave 1 -- UART +//   CLKDIV is 16 bits, others are only 8 + +#define UE_REG_UART_BASE UE_REG_SLAVE(1) + +#define UE_REG_UART_CLKDIV  UE_REG_UART_BASE + 0 +#define UE_REG_UART_TXLEVEL UE_REG_UART_BASE + 2 +#define UE_REG_UART_RXLEVEL UE_REG_UART_BASE + 4 +#define UE_REG_UART_TXCHAR  UE_REG_UART_BASE + 6 +#define UE_REG_UART_RXCHAR  UE_REG_UART_BASE + 8 + +///////////////////////////////////////////////////// +// Slave 2 -- SPI Core +//   This should be accessed through the IOCTL +//   Users should not touch directly + +#define UE_REG_SPI_BASE UE_REG_SLAVE(2) + + +//////////////////////////////////////////////// +// Slave 3 -- I2C Core +//   This should be accessed through the IOCTL +//   Users should not touch directly + +#define UE_REG_I2C_BASE UE_REG_SLAVE(3) + + +//////////////////////////////////////////////// +// Slave 4 -- GPIO + +#define UE_REG_GPIO_BASE UE_REG_SLAVE(4) + +#define UE_REG_GPIO_RX_IO      UE_REG_GPIO_BASE + 0 +#define UE_REG_GPIO_TX_IO      UE_REG_GPIO_BASE + 2 +#define UE_REG_GPIO_RX_DDR     UE_REG_GPIO_BASE + 4 +#define UE_REG_GPIO_TX_DDR     UE_REG_GPIO_BASE + 6 +#define UE_REG_GPIO_RX_SEL     UE_REG_GPIO_BASE + 8 +#define UE_REG_GPIO_TX_SEL     UE_REG_GPIO_BASE + 10 +#define UE_REG_GPIO_RX_DBG     UE_REG_GPIO_BASE + 12 +#define UE_REG_GPIO_TX_DBG     UE_REG_GPIO_BASE + 14 + +// each 2-bit sel field is layed out this way +#define GPIO_SEL_SW	   0 // if pin is an output, set by software in the io reg +#define	GPIO_SEL_ATR	   1 // if pin is an output, set by ATR logic +#define	GPIO_SEL_DEBUG_0   0 // if pin is an output, debug lines from FPGA fabric +#define	GPIO_SEL_DEBUG_1   1 // if pin is an output, debug lines from FPGA fabric + + +//////////////////////////////////////////////////// +// Slave 5 -- Settings Bus +// +// Output-only, no readback, 32 registers total +//  Each register must be written 32 bits at a time +//  First the address xxx_xx00 and then xxx_xx10 + +#define UE_REG_SETTINGS_BASE UE_REG_SLAVE(5) + +/////////////////////////////////////////////////// +// Slave 6 -- ATR Controller +//   16 regs + +#define UE_REG_ATR_BASE  UE_REG_SLAVE(6) + +#define	UE_REG_ATR_IDLE_RXSIDE	UE_REG_ATR_BASE + 0 +#define	UE_REG_ATR_IDLE_TXSIDE	UE_REG_ATR_BASE + 2 +#define UE_REG_ATR_INTX_RXSIDE  UE_REG_ATR_BASE + 4 +#define UE_REG_ATR_INTX_TXSIDE  UE_REG_ATR_BASE + 6 +#define	UE_REG_ATR_INRX_RXSIDE  UE_REG_ATR_BASE + 8 +#define	UE_REG_ATR_INRX_TXSIDE  UE_REG_ATR_BASE + 10 +#define	UE_REG_ATR_FULL_RXSIDE  UE_REG_ATR_BASE + 12 +#define	UE_REG_ATR_FULL_TXSIDE  UE_REG_ATR_BASE + 14 + +#endif + diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index aa01d1e35..0b1e058ef 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -19,6 +19,10 @@ ADD_EXECUTABLE(uhd_find_devices uhd_find_devices.cpp)  TARGET_LINK_LIBRARIES(uhd_find_devices uhd)  INSTALL(TARGETS uhd_find_devices RUNTIME DESTINATION ${RUNTIME_DIR}) +ADD_EXECUTABLE(usrp_e_load_fpga usrp_e_load_fpga.cpp) +TARGET_LINK_LIBRARIES(usrp_e_load_fpga uhd) +INSTALL(TARGETS usrp_e_load_fpga RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) +  ADD_EXECUTABLE(usrp2_burner usrp2_burner.cpp)  TARGET_LINK_LIBRARIES(usrp2_burner uhd)  INSTALL(TARGETS usrp2_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) diff --git a/host/utils/usrp_e_load_fpga.cpp b/host/utils/usrp_e_load_fpga.cpp new file mode 100644 index 000000000..403130b53 --- /dev/null +++ b/host/utils/usrp_e_load_fpga.cpp @@ -0,0 +1,47 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/usrp_e.hpp> +#include <boost/program_options.hpp> +#include <boost/format.hpp> +#include <iostream> + +namespace po = boost::program_options; + +int main(int argc, char *argv[]){ +    po::options_description desc("Allowed options"); +    desc.add_options() +        ("help", "help message") +        ("file", po::value<std::string>(), "path to fpga bin file") +    ; + +    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("file") == 0){ +        std::cout << boost::format("USRP1E Load FPGA %s") % desc << std::endl; +        return ~0; +    } + +    //load the fpga +    std::string file = vm["file"].as<std::string>(); +    uhd::usrp::usrp_e::load_fpga(file); + +    return 0; +}  | 
