diff options
Diffstat (limited to 'host')
33 files changed, 1941 insertions, 3 deletions
diff --git a/host/apps/omap_debug/Makefile b/host/apps/omap_debug/Makefile new file mode 100644 index 000000000..13b834e28 --- /dev/null +++ b/host/apps/omap_debug/Makefile @@ -0,0 +1,19 @@ +CFLAGS=-Wall + +all : usrp-e-spi usrp-e-i2c usrp-e-rw usrp-e-uart + +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 + +clean : + rm -f usrp-e-spi + rm -f usrp-e-i2c + rm -f usrp-e-rw + rm -f usrp-e-uart + 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..beff7ffcd --- /dev/null +++ b/host/apps/omap_debug/fetch-bin.sh @@ -0,0 +1,2 @@ +scp balister@astro:/workspace/usrp1-e-dev/u1e.bin . +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..7023f5d28 --- /dev/null +++ b/host/apps/omap_debug/fetch-kernel.sh @@ -0,0 +1,3 @@ +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..45cf1f052 --- /dev/null +++ b/host/apps/omap_debug/fetch-module.sh @@ -0,0 +1,3 @@ +scp balister@192.168.1.167:src/git/kernel_usrp/drivers/misc/usrp_e.ko /lib/modules/2.6.33-rc3/kernel/drivers/misc +scp balister@192.168.1.167:src/git/kernel_usrp/include/linux/usrp_e.h . +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..63d4edcf2 --- /dev/null +++ b/host/apps/omap_debug/fetch-u-boot.sh @@ -0,0 +1,3 @@ +scp balister@astro:/workspace/usrp1-e-dev/u-boot-overo/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..fdd085c9e --- /dev/null +++ b/host/apps/omap_debug/set_debug_pins.py @@ -0,0 +1,34 @@ +#!/usr/bin/python + +import os + +# Memory Map +misc_base = 0 << 7 +uart_base = 1 << 7 +spi_base = 2 << 7 +i2c_base = 3 << 7 +gpio_base = 4 << 7 +settings_base = 5 << 7 + +# 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-ctl.c b/host/apps/omap_debug/usrp-e-ctl.c new file mode 100644 index 000000000..045e7ce19 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-ctl.c @@ -0,0 +1,52 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <fcntl.h> +#include <linux/ioctl.h> + +#include "usrp1_e.h" + +// Usage: usrp1_e_ctl w|r offset number_of_values val1 val2 .... + +int main(int argc, char *argv[]) +{ + int fp, i, cnt, ret; + struct usrp1_e_ctl *ctl_data; + + if (argc < 4) { + printf("Usage: usrp1_e_ctl w|r offset number_of_values val1 val2 ....\n"); + exit(-1); + } + + cnt = atoi(argv[3]); + + ctl_data = malloc(sizeof(struct usrp1_e_ctl) + cnt*2); + + ctl_data->offset = atoi(argv[2]); + ctl_data->count = cnt; + + printf("Sizeof usrp1_e_ctl struct = %d\n", sizeof(struct usrp1_e_ctl)); + + fp = open("/dev/usrp1_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, USRP1_E_WRITE_CTL, ctl_data); + printf("Return value from write ioctl = %d\n", ret); + } + + if (*argv[1] == 'r') { + ret = ioctl(fp, USRP1_E_READ_CTL, 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-i2c.c b/host/apps/omap_debug/usrp-e-i2c.c new file mode 100644 index 000000000..417d6d580 --- /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 - 2; + } 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-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..1af47b172 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-spi.c @@ -0,0 +1,42 @@ +#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, data, ret; + struct usrp_e_spi spi_dat; + + if (argc < 4) { + printf("Usage: usrp_e_spi w|rb slave data\n"); + exit(-1); + } + + slave = atoi(argv[2]); + data = atoi(argv[3]); + + fp = open("/dev/usrp_e0", O_RDWR); + printf("fp = %d\n", fp); + + spi_dat.slave = slave; + spi_dat.data = data; + spi_dat.length = 2; + 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.c b/host/apps/omap_debug/usrp-e-uart.c new file mode 100644 index 000000000..239df9444 --- /dev/null +++ b/host/apps/omap_debug/usrp-e-uart.c @@ -0,0 +1,37 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <fcntl.h> +#include <string.h> +#include <sys/ioctl.h> + +#include "usrp_e.h" + +// Usage: usrp_e_uart <string> + +#define UART_WRITE_ADDR (0x80 + 12) + +int main(int argc, char *argv[]) +{ + int fp, i, ret; + struct usrp_e_ctl16 d; + char *str = argv[1]; + + if (argc < 2) { + printf("Usage: usrp_e_uart <string>n"); + exit(-1); + } + + fp = open("/dev/usrp_e0", O_RDWR); + printf("fp = %d\n", fp); + + for (i=0; i<strlen(str); i++) { + d.offset = UART_WRITE_ADDR; + 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/apps/usrp1e_load_fpga.cpp b/host/apps/usrp1e_load_fpga.cpp new file mode 100644 index 000000000..d5960b391 --- /dev/null +++ b/host/apps/usrp1e_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/usrp1e.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::usrp1e::load_fpga(file); + + return 0; +} diff --git a/host/include/uhd/usrp/usrp1e.hpp b/host/include/uhd/usrp/usrp1e.hpp index cee9dc3d5..75da58453 100644 --- a/host/include/uhd/usrp/usrp1e.hpp +++ b/host/include/uhd/usrp/usrp1e.hpp @@ -41,6 +41,12 @@ public: * \return a device sptr to a new usrp1e */ 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 diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 55034c780..323b69b14 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -51,10 +51,34 @@ LIST(APPEND libuhd_sources ######################################################################## # Conditionally add the usrp1e sources ######################################################################## -LIST(APPEND libuhd_sources - usrp/usrp1e/usrp1e_none.cpp +INCLUDE(CheckIncludeFiles) +SET(usrp1e_required_headers + linux/ioctl.h + linux/spi/spidev.h + linux/usrp1_e.h +) +CHECK_INCLUDE_FILES( + "${usrp1e_required_headers}" + HAS_USRP1E_REQUIRED_HEADERS ) +IF(HAS_USRP1E_REQUIRED_HEADERS) + MESSAGE(STATUS "Building usrp1e support...") + LIST(APPEND libuhd_sources + usrp/usrp1e/dboard_impl.cpp + usrp/usrp1e/dboard_interface.cpp + usrp/usrp1e/dsp_impl.cpp + usrp/usrp1e/fpga-downloader.cc + usrp/usrp1e/mboard_impl.cpp + usrp/usrp1e/usrp1e_impl.cpp + ) +ELSE(HAS_USRP1E_REQUIRED_HEADERS) + MESSAGE(STATUS "Skipping usrp1e support...") + LIST(APPEND libuhd_sources + usrp/usrp1e/usrp1e_none.cpp + ) +ENDIF(HAS_USRP1E_REQUIRED_HEADERS) + ######################################################################## # Setup defines for module loading ######################################################################## diff --git a/host/lib/usrp/usrp1e/dboard_impl.cpp b/host/lib/usrp/usrp1e/dboard_impl.cpp new file mode 100644 index 000000000..a2798dce3 --- /dev/null +++ b/host/lib/usrp/usrp1e/dboard_impl.cpp @@ -0,0 +1,76 @@ +// +// 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 <uhd/utils.hpp> +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * Dboard Initialization + **********************************************************************/ +void usrp1e_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_usrp1e_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(&usrp1e_impl::rx_dboard_get, this, _1, _2), + boost::bind(&usrp1e_impl::rx_dboard_set, this, _1, _2) + ); + _tx_dboard_proxy = wax_obj_proxy::make( + boost::bind(&usrp1e_impl::tx_dboard_get, this, _1, _2), + boost::bind(&usrp1e_impl::tx_dboard_set, this, _1, _2) + ); +} + +/*********************************************************************** + * RX Dboard Get + **********************************************************************/ +void usrp1e_impl::rx_dboard_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * RX Dboard Set + **********************************************************************/ +void usrp1e_impl::rx_dboard_set(const wax::obj &, const wax::obj &){ + +} + +/*********************************************************************** + * TX Dboard Get + **********************************************************************/ +void usrp1e_impl::tx_dboard_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * TX Dboard Set + **********************************************************************/ +void usrp1e_impl::tx_dboard_set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/dboard_interface.cpp b/host/lib/usrp/usrp1e/dboard_interface.cpp new file mode 100644 index 000000000..ef91014ac --- /dev/null +++ b/host/lib/usrp/usrp1e/dboard_interface.cpp @@ -0,0 +1,189 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/utils.hpp> +#include <algorithm> //std::copy +#include "usrp1e_impl.hpp" +#include <linux/usrp1_e.h> + +using namespace uhd::usrp; + +class usrp1e_dboard_interface : public dboard_interface{ +public: + usrp1e_dboard_interface(usrp1e_impl *impl); + ~usrp1e_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, boost::uint16_t, boost::uint16_t, boost::uint16_t); + void set_gpio_ddr(gpio_bank_t, boost::uint16_t, boost::uint16_t); + void write_gpio(gpio_bank_t, boost::uint16_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_latch_t latch, + spi_push_t push, + const byte_vector_t &buf, + bool readback + ); + + usrp1e_impl *_impl; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +dboard_interface::sptr make_usrp1e_dboard_interface(usrp1e_impl *impl){ + return dboard_interface::sptr(new usrp1e_dboard_interface(impl)); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp1e_dboard_interface::usrp1e_dboard_interface(usrp1e_impl *impl){ + _impl = impl; +} + +usrp1e_dboard_interface::~usrp1e_dboard_interface(void){ + /* NOP */ +} + +/*********************************************************************** + * Clock Rates + **********************************************************************/ +double usrp1e_dboard_interface::get_rx_clock_rate(void){ + throw std::runtime_error("not implemented"); +} + +double usrp1e_dboard_interface::get_tx_clock_rate(void){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * GPIO + **********************************************************************/ +void usrp1e_dboard_interface::set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ + throw std::runtime_error("not implemented"); +} + +void usrp1e_dboard_interface::write_gpio(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ + throw std::runtime_error("not implemented"); +} + +boost::uint16_t usrp1e_dboard_interface::read_gpio(gpio_bank_t bank){ + throw std::runtime_error("not implemented"); +} + +void usrp1e_dboard_interface::set_atr_reg(gpio_bank_t bank, boost::uint16_t tx_value, boost::uint16_t rx_value, boost::uint16_t mask){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * SPI + **********************************************************************/ +dboard_interface::byte_vector_t usrp1e_dboard_interface::transact_spi( + spi_dev_t dev, + spi_latch_t latch, + spi_push_t push, + 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_RX_DEV)? 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 |= (latch == SPI_LATCH_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; + data.flags |= (push == SPI_PUSH_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 usrp1e_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 usrp1e_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 usrp1e_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, int which, int value){ + throw std::runtime_error("not implemented"); +} + +int usrp1e_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/usrp1e/dsp_impl.cpp b/host/lib/usrp/usrp1e/dsp_impl.cpp new file mode 100644 index 000000000..862b89184 --- /dev/null +++ b/host/lib/usrp/usrp1e/dsp_impl.cpp @@ -0,0 +1,70 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/bind.hpp> +#include <uhd/utils.hpp> +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * RX DDC Initialization + **********************************************************************/ +void usrp1e_impl::rx_ddc_init(void){ + _rx_ddc_proxy = wax_obj_proxy::make( + boost::bind(&usrp1e_impl::rx_ddc_get, this, _1, _2), + boost::bind(&usrp1e_impl::rx_ddc_set, this, _1, _2) + ); +} + +/*********************************************************************** + * RX DDC Get + **********************************************************************/ +void usrp1e_impl::rx_ddc_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * RX DDC Set + **********************************************************************/ +void usrp1e_impl::rx_ddc_set(const wax::obj &, const wax::obj &){ + +} + +/*********************************************************************** + * TX DUC Initialization + **********************************************************************/ +void usrp1e_impl::tx_duc_init(void){ + _tx_duc_proxy = wax_obj_proxy::make( + boost::bind(&usrp1e_impl::tx_duc_get, this, _1, _2), + boost::bind(&usrp1e_impl::tx_duc_set, this, _1, _2) + ); +} + +/*********************************************************************** + * TX DUC Get + **********************************************************************/ +void usrp1e_impl::tx_duc_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * TX DUC Set + **********************************************************************/ +void usrp1e_impl::tx_duc_set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/fpga-downloader.cc b/host/lib/usrp/usrp1e/fpga-downloader.cc new file mode 100644 index 000000000..f7c78b875 --- /dev/null +++ b/host/lib/usrp/usrp1e/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/usrp1e.hpp> +void uhd::usrp::usrp1e::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/usrp1e/mboard_impl.cpp b/host/lib/usrp/usrp1e/mboard_impl.cpp new file mode 100644 index 000000000..b480f7616 --- /dev/null +++ b/host/lib/usrp/usrp1e/mboard_impl.cpp @@ -0,0 +1,46 @@ +// +// 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 <uhd/utils.hpp> +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * Mboard Initialization + **********************************************************************/ +void usrp1e_impl::mboard_init(void){ + _mboard_proxy = wax_obj_proxy::make( + boost::bind(&usrp1e_impl::mboard_get, this, _1, _2), + boost::bind(&usrp1e_impl::mboard_set, this, _1, _2) + ); +} + +/*********************************************************************** + * Mboard Get + **********************************************************************/ +void usrp1e_impl::mboard_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * Mboard Set + **********************************************************************/ +void usrp1e_impl::mboard_set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp new file mode 100644 index 000000000..8230cc8e4 --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -0,0 +1,178 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/utils.hpp> +#include <boost/format.hpp> +#include <boost/filesystem.hpp> +#include "usrp1e_impl.hpp" +#include <fcntl.h> //open +#include <sys/ioctl.h> //ioctl + +using namespace uhd; +using namespace uhd::usrp; +namespace fs = boost::filesystem; + +STATIC_BLOCK(register_usrp1e_device){ + device::register_device(&usrp1e::discover, &usrp1e::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 usrp1e::discover(const device_addr_t &device_addr){ + device_addrs_t usrp1e_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 usrp1e_addrs; + device_addr_t new_addr; + new_addr["name"] = "USRP1E"; + new_addr["node"] = abs_path(device_addr["node"]); + usrp1e_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"] = "USRP1E"; + new_addr["node"] = abs_path(node); + usrp1e_addrs.push_back(new_addr); + } + } + + return usrp1e_addrs; +} + +/*********************************************************************** + * Make + **********************************************************************/ +device::sptr usrp1e::make(const device_addr_t &device_addr){ + return sptr(new usrp1e_impl(device_addr["node"])); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp1e_impl::usrp1e_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(); +} + +usrp1e_impl::~usrp1e_impl(void){ + //close the device node file descriptor + ::close(_node_fd); +} + +/*********************************************************************** + * Misc Methods + **********************************************************************/ +void usrp1e_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 + )); + } +} + +/*********************************************************************** + * Device Get + **********************************************************************/ +void usrp1e_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("usrp1e 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 usrp1e_impl::set(const wax::obj &, const wax::obj &){ + throw std::runtime_error("Cannot set in usrp1e device"); +} + +/*********************************************************************** + * Device IO (TODO) + **********************************************************************/ +size_t usrp1e_impl::send( + const boost::asio::const_buffer &, + const uhd::tx_metadata_t &, + const std::string &type +){ + if (type != "16sc"){ + throw std::runtime_error(str(boost::format("usrp1e send: cannot handle type \"%s\"") % type)); + } + return 0; +} + +size_t usrp1e_impl::recv( + const boost::asio::mutable_buffer &, + uhd::rx_metadata_t &, + const std::string &type +){ + if (type != "16sc"){ + throw std::runtime_error(str(boost::format("usrp1e recv: cannot handle type \"%s\"") % type)); + } + return 0; +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp new file mode 100644 index 000000000..c199a0465 --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -0,0 +1,135 @@ +// +// 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/usrp1e.hpp> +#include <uhd/usrp/dboard_manager.hpp> + +#ifndef INCLUDED_USRP1E_IMPL_HPP +#define INCLUDED_USRP1E_IMPL_HPP + +class usrp1e_impl; // dummy class declaration + +/*! + * Make a usrp1e dboard interface. + * \param impl a pointer to the usrp1e impl object + * \return a sptr to a new dboard interface + */ +uhd::usrp::dboard_interface::sptr make_usrp1e_dboard_interface(usrp1e_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 usrp1e_impl : public uhd::device{ +public: + //structors + usrp1e_impl(const std::string &node); + ~usrp1e_impl(void); + + //the io interface + size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &); + size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &); + + /*! + * 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); + +private: + static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); + int _node_fd; + + //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_USRP1E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp1e/usrp1e_none.cpp b/host/lib/usrp/usrp1e/usrp1e_none.cpp index 84fb9276c..94243523d 100644 --- a/host/lib/usrp/usrp1e/usrp1e_none.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_none.cpp @@ -32,3 +32,7 @@ device_addrs_t usrp1e::find(const device_addr_t &){ device::sptr usrp1e::make(const device_addr_t &){ throw std::runtime_error("this build has no usrp1e support"); } + +void usrp1e::load_fpga(const std::string &){ + throw std::runtime_error("this build has no usrp1e support"); +} diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index b0ee395fb..67fbdf8d2 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -29,7 +29,7 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -UHD_STATIC_BLOCK(register_usrp2_device){ +STATIC_BLOCK(register_usrp2_device){ device::register_device(&usrp2::find, &usrp2::make); } diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index aa01d1e35..99e648d8a 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -19,6 +19,9 @@ ADD_EXECUTABLE(uhd_find_devices uhd_find_devices.cpp) TARGET_LINK_LIBRARIES(uhd_find_devices uhd) INSTALL(TARGETS uhd_find_devices RUNTIME DESTINATION ${RUNTIME_DIR}) +ADD_EXECUTABLE(usrp1e_load_fpga usrp1e_load_fpga.cpp) +TARGET_LINK_LIBRARIES(usrp1e_load_fpga uhd) + ADD_EXECUTABLE(usrp2_burner usrp2_burner.cpp) TARGET_LINK_LIBRARIES(usrp2_burner uhd) INSTALL(TARGETS usrp2_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) |