From a9f8ba6e37e1349ce61b5022ddaff1c64dd52bd3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Feb 2010 18:26:00 +0000 Subject: added usrp1e conditional compilation, and checking of device node (aka file for now) --- host/lib/usrp/usrp1e/usrp1e_impl.cpp | 69 ++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/usrp1e_impl.hpp | 23 ++++++++++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 1 - 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 host/lib/usrp/usrp1e/usrp1e_impl.cpp create mode 100644 host/lib/usrp/usrp1e/usrp1e_impl.hpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp new file mode 100644 index 000000000..93265ab17 --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_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 . +// + +#include +#include +#include "usrp1e_impl.hpp" + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static bool file_exists(const std::string &file_path){ + return access(file_path.c_str(), F_OK) == 0; +} + +/*********************************************************************** + * 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 file_exists(device_addr["node"])) return usrp1e_addrs; + device_addr_t new_addr; + new_addr["name"] = "USRP1E"; + new_addr["type"] = "usrp1e"; + new_addr["node"] = 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 file_exists(node)) continue; + device_addr_t new_addr; + new_addr["name"] = "USRP1E"; + new_addr["type"] = "usrp1e"; + new_addr["node"] = node; + usrp1e_addrs.push_back(new_addr); + } + } + + return usrp1e_addrs; +} + +/*********************************************************************** + * Make + **********************************************************************/ +device::sptr usrp1e::make(const device_addr_t &){ + throw std::runtime_error("not implemented yet"); +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp new file mode 100644 index 000000000..3f5f89ec6 --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -0,0 +1,23 @@ +// +// 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 . +// + +#include + +#ifndef INCLUDED_USRP1E_IMPL_HPP +#define INCLUDED_USRP1E_IMPL_HPP + +#endif /* INCLUDED_USRP1E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 06876d241..5aa5d6e8d 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -62,7 +62,6 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ device_addr_t new_addr; new_addr["name"] = "USRP2"; new_addr["type"] = "usrp2"; - new_addr["transport"] = "udp"; new_addr["addr"] = ip_addr.to_string(); usrp2_addrs.push_back(new_addr); break; -- cgit v1.2.3 From 778a41b393b7d517463950c4ac014d3a2eb8eceb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Feb 2010 19:43:20 +0000 Subject: added usrp1e fpga loader --- host/include/uhd/usrp/usrp1e.hpp | 6 + host/lib/CMakeLists.txt | 21 ++- host/lib/usrp/usrp1e/fpga-downloader.cc | 262 ++++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/usrp1e_none.cpp | 4 + 4 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 host/lib/usrp/usrp1e/fpga-downloader.cc (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/usrp1e.hpp b/host/include/uhd/usrp/usrp1e.hpp index 00748e55f..60a6a191a 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 96fba6e53..33314e729 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -41,17 +41,28 @@ SET(libuhd_sources ######################################################################## # Conditionally add the usrp1e sources ######################################################################## -INCLUDE(CheckIncludeFile) -CHECK_INCLUDE_FILE("linux/ioctl.h" HAS_LINUX_IOCTL_H) -IF(HAS_LINUX_IOCTL_H) +INCLUDE(CheckIncludeFiles) +SET(usrp1e_required_headers + linux/ioctl.h + linux/spi/spidev.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/fpga-downloader.cc usrp/usrp1e/usrp1e_impl.cpp ) -ELSE(HAS_LINUX_IOCTL_H) +ELSE(HAS_USRP1E_REQUIRED_HEADERS) + MESSAGE(STATUS "Skipping usrp1e support...") LIST(APPEND libuhd_sources usrp/usrp1e/usrp1e_none.cpp ) -ENDIF(HAS_LINUX_IOCTL_H) +ENDIF(HAS_USRP1E_REQUIRED_HEADERS) ######################################################################## # Setup libuhd library diff --git a/host/lib/usrp/usrp1e/fpga-downloader.cc b/host/lib/usrp/usrp1e/fpga-downloader.cc new file mode 100644 index 000000000..15023d945 --- /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 . +// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * 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); +} +*/ + +#include +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(bit_file, gpio_init_b, gpio_done); +} diff --git a/host/lib/usrp/usrp1e/usrp1e_none.cpp b/host/lib/usrp/usrp1e/usrp1e_none.cpp index 1c8cf9a5b..ac0b12a75 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::discover(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"); +} -- cgit v1.2.3 From 1b965831ae7588c7879d84de4e5fbd78ca614761 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 26 Feb 2010 11:01:19 +0000 Subject: made app to load usrp1e fpga images, and tested it to be working --- host/apps/CMakeLists.txt | 4 ++- host/apps/usrp1e_load_fpga.cpp | 47 +++++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/fpga-downloader.cc | 6 ++--- 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 host/apps/usrp1e_load_fpga.cpp (limited to 'host/lib/usrp') diff --git a/host/apps/CMakeLists.txt b/host/apps/CMakeLists.txt index f4428f958..a7068e5a4 100644 --- a/host/apps/CMakeLists.txt +++ b/host/apps/CMakeLists.txt @@ -16,7 +16,9 @@ # ADD_EXECUTABLE(discover_usrps discover_usrps.cpp) - TARGET_LINK_LIBRARIES(discover_usrps uhd) +ADD_EXECUTABLE(usrp1e_load_fpga usrp1e_load_fpga.cpp) +TARGET_LINK_LIBRARIES(usrp1e_load_fpga uhd) + INSTALL(TARGETS discover_usrps RUNTIME DESTINATION ${RUNTIME_DIR}) 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 . +// + +#include +#include +#include +#include + +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(), "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(); + uhd::usrp::usrp1e::load_fpga(file); + + return 0; +} diff --git a/host/lib/usrp/usrp1e/fpga-downloader.cc b/host/lib/usrp/usrp1e/fpga-downloader.cc index 15023d945..f7c78b875 100644 --- a/host/lib/usrp/usrp1e/fpga-downloader.cc +++ b/host/lib/usrp/usrp1e/fpga-downloader.cc @@ -43,7 +43,7 @@ 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"; +//static std::string bit_file = "safe_u1e.bin"; const int BUF_SIZE = 4096; @@ -198,7 +198,7 @@ void spidev::send(char *buf, char *rbuf, unsigned int nbytes) } -static void send_file_to_fpga(std::string &file_name, gpio &error, gpio &done) +static void send_file_to_fpga(const std::string &file_name, gpio &error, gpio &done) { std::ifstream bitstream; @@ -258,5 +258,5 @@ void uhd::usrp::usrp1e::load_fpga(const std::string &bin_file){ std::cout << "Done = " << gpio_done.get_value() << std::endl; - send_file_to_fpga(bit_file, gpio_init_b, gpio_done); + send_file_to_fpga(bin_file, gpio_init_b, gpio_done); } -- cgit v1.2.3 From 10ee8022dd22f13f942d8bfeeca3b380224fff52 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 18 Mar 2010 19:38:06 +0000 Subject: added usrp1e implementation skeleton, began filling it in... --- host/include/uhd/usrp/dboard_id.hpp | 3 +- host/lib/CMakeLists.txt | 4 + host/lib/usrp/usrp1e/dboard_impl.cpp | 76 +++++++++++++++++ host/lib/usrp/usrp1e/dboard_interface.cpp | 135 ++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/dsp_impl.cpp | 63 ++++++++++++++ host/lib/usrp/usrp1e/mboard_impl.cpp | 42 ++++++++++ host/lib/usrp/usrp1e/usrp1e_impl.cpp | 33 ++++++++ host/lib/usrp/usrp1e/usrp1e_impl.hpp | 97 +++++++++++++++++++++ 8 files changed, 452 insertions(+), 1 deletion(-) create mode 100644 host/lib/usrp/usrp1e/dboard_impl.cpp create mode 100644 host/lib/usrp/usrp1e/dboard_interface.cpp create mode 100644 host/lib/usrp/usrp1e/dsp_impl.cpp create mode 100644 host/lib/usrp/usrp1e/mboard_impl.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 62c61661c..370cd1fbb 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -25,9 +25,10 @@ namespace uhd{ namespace usrp{ typedef boost::uint16_t dboard_id_t; -static const dboard_id_t ID_NONE = 0xffff; +static const dboard_id_t ID_NONE = 0xffff; //TODO: REMOVE ME namespace dboard_id{ + static const dboard_id_t NONE = 0xffff; std::string to_string(const dboard_id_t &id); } diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 7d7fcbea9..e547fef85 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -63,7 +63,11 @@ CHECK_INCLUDE_FILES( 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) diff --git a/host/lib/usrp/usrp1e/dboard_impl.cpp b/host/lib/usrp/usrp1e/dboard_impl.cpp new file mode 100644 index 000000000..7d46366bc --- /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 . +// + +#include +#include +#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( + 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( + 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..b3e06f7be --- /dev/null +++ b/host/lib/usrp/usrp1e/dboard_interface.cpp @@ -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 . +// + +#include +#include "usrp1e_impl.hpp" + +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 +){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * I2C + **********************************************************************/ +void usrp1e_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){ + throw std::runtime_error("not implemented"); +} + +dboard_interface::byte_vector_t usrp1e_dboard_interface::read_i2c(int i2c_addr, size_t num_bytes){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * 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..b6076ef97 --- /dev/null +++ b/host/lib/usrp/usrp1e/dsp_impl.cpp @@ -0,0 +1,63 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * RX DDC Initialization + **********************************************************************/ +void usrp1e_impl::rx_ddc_init(void){ + +} + +/*********************************************************************** + * 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 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/mboard_impl.cpp b/host/lib/usrp/usrp1e/mboard_impl.cpp new file mode 100644 index 000000000..c79ed1820 --- /dev/null +++ b/host/lib/usrp/usrp1e/mboard_impl.cpp @@ -0,0 +1,42 @@ +// +// 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 . +// + +#include +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * Mboard Initialization + **********************************************************************/ +void usrp1e_impl::mboard_init(void){ + +} + +/*********************************************************************** + * 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 index 441f6d060..14c4b7278 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -70,3 +70,36 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ device::sptr usrp1e::make(const device_addr_t &){ throw std::runtime_error("not implemented yet"); } + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp1e_impl::usrp1e_impl(void){ + //initialize the mboard + mboard_init(); + + //initialize the dboards + dboard_init(); + + //initialize the dsps + rx_ddc_init(); + tx_duc_init(); +} + +usrp1e_impl::~usrp1e_impl(void){ + /* NOP */ +} + +/*********************************************************************** + * Device Get + **********************************************************************/ +void usrp1e_impl::get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * Device Set + **********************************************************************/ +void usrp1e_impl::set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp index 3f5f89ec6..3b2fcdd57 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.hpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -16,8 +16,105 @@ // #include +#include #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 get_t; + typedef boost::function set_t; + + wax_obj_proxy(void){ + /* NOP */ + } + + wax_obj_proxy(const get_t &get, const set_t &set){ + _get = get; + _set = set; + }; + + ~wax_obj_proxy(void){ + /* NOP */ + } + + 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); + } + +private: + get_t _get; + set_t _set; +}; + +/*! + * USRP1E implementation guts: + * The implementation details are encapsulated here. + * Handles properties on the mboard, dboard, dsps... + */ +class usrp1e_impl : public uhd::device{ +public: + typedef boost::shared_ptr sptr; + + usrp1e_impl(void); + ~usrp1e_impl(void); + +private: + //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 _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 _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 _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 _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 _tx_duc_proxy; +}; + #endif /* INCLUDED_USRP1E_IMPL_HPP */ -- cgit v1.2.3 From a31761cb0c37b61f7243836d6dd8c40cbf49efc0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Mar 2010 13:12:03 +0000 Subject: filled in more skeleton code, filled in dboard interface spi and i2c with ioctls, added file descriptor opening, and checking for usrp1 kernel header --- host/lib/CMakeLists.txt | 1 + host/lib/usrp/usrp1e/dboard_impl.cpp | 4 +- host/lib/usrp/usrp1e/dboard_interface.cpp | 60 +++++++++++++++++++++-- host/lib/usrp/usrp1e/dsp_impl.cpp | 11 ++++- host/lib/usrp/usrp1e/mboard_impl.cpp | 6 ++- host/lib/usrp/usrp1e/usrp1e_impl.cpp | 79 ++++++++++++++++++++++++++----- host/lib/usrp/usrp1e/usrp1e_impl.hpp | 48 ++++++++++++------- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 - 8 files changed, 172 insertions(+), 39 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a7dded86b..46cce729e 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -56,6 +56,7 @@ INCLUDE(CheckIncludeFiles) SET(usrp1e_required_headers linux/ioctl.h linux/spi/spidev.h + linux/usrp1_e.h ) CHECK_INCLUDE_FILES( "${usrp1e_required_headers}" diff --git a/host/lib/usrp/usrp1e/dboard_impl.cpp b/host/lib/usrp/usrp1e/dboard_impl.cpp index 7d46366bc..a2798dce3 100644 --- a/host/lib/usrp/usrp1e/dboard_impl.cpp +++ b/host/lib/usrp/usrp1e/dboard_impl.cpp @@ -37,11 +37,11 @@ void usrp1e_impl::dboard_init(void){ ); //setup the dboard proxies - _rx_dboard_proxy = wax_obj_proxy( + _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( + _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) ); diff --git a/host/lib/usrp/usrp1e/dboard_interface.cpp b/host/lib/usrp/usrp1e/dboard_interface.cpp index b3e06f7be..ef91014ac 100644 --- a/host/lib/usrp/usrp1e/dboard_interface.cpp +++ b/host/lib/usrp/usrp1e/dboard_interface.cpp @@ -16,7 +16,9 @@ // #include +#include //std::copy #include "usrp1e_impl.hpp" +#include using namespace uhd::usrp; @@ -109,18 +111,70 @@ dboard_interface::byte_vector_t usrp1e_dboard_interface::transact_spi( const byte_vector_t &buf, bool readback ){ - throw std::runtime_error("not implemented"); + //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(&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){ - throw std::runtime_error("not implemented"); + //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(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){ - throw std::runtime_error("not implemented"); + //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(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; } /*********************************************************************** diff --git a/host/lib/usrp/usrp1e/dsp_impl.cpp b/host/lib/usrp/usrp1e/dsp_impl.cpp index b6076ef97..862b89184 100644 --- a/host/lib/usrp/usrp1e/dsp_impl.cpp +++ b/host/lib/usrp/usrp1e/dsp_impl.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include #include #include "usrp1e_impl.hpp" @@ -24,7 +25,10 @@ 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) + ); } /*********************************************************************** @@ -45,7 +49,10 @@ 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) + ); } /*********************************************************************** diff --git a/host/lib/usrp/usrp1e/mboard_impl.cpp b/host/lib/usrp/usrp1e/mboard_impl.cpp index c79ed1820..b480f7616 100644 --- a/host/lib/usrp/usrp1e/mboard_impl.cpp +++ b/host/lib/usrp/usrp1e/mboard_impl.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include #include #include "usrp1e_impl.hpp" @@ -24,7 +25,10 @@ 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) + ); } /*********************************************************************** diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp index 14c4b7278..d3b0264a7 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -19,9 +19,12 @@ #include #include #include "usrp1e_impl.hpp" +#include //open +#include //ioctl using namespace uhd; using namespace uhd::usrp; +namespace fs = boost::filesystem; STATIC_BLOCK(register_usrp1e_device){ device::register_device(&usrp1e::discover, &usrp1e::make); @@ -30,8 +33,8 @@ STATIC_BLOCK(register_usrp1e_device){ /*********************************************************************** * Helper Functions **********************************************************************/ -static bool file_exists(const std::string &file_path){ - return boost::filesystem::exists(file_path); +static std::string abs_path(const std::string &file_path){ + return fs::system_complete(fs::path(file_path)).file_string(); } /*********************************************************************** @@ -42,10 +45,10 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ //if a node was provided, use it and only it if (device_addr.has_key("node")){ - if (not file_exists(device_addr["node"])) return usrp1e_addrs; + if (not fs::exists(device_addr["node"])) return usrp1e_addrs; device_addr_t new_addr; new_addr["name"] = "USRP1E"; - new_addr["node"] = device_addr["node"]; + new_addr["node"] = abs_path(device_addr["node"]); usrp1e_addrs.push_back(new_addr); } @@ -53,10 +56,10 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ else{ for(size_t i = 0; i < 5; i++){ std::string node = str(boost::format("/dev/usrp1_e%d") % i); - if (not file_exists(node)) continue; + if (not fs::exists(node)) continue; device_addr_t new_addr; new_addr["name"] = "USRP1E"; - new_addr["node"] = node; + new_addr["node"] = abs_path(node); usrp1e_addrs.push_back(new_addr); } } @@ -67,14 +70,23 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ /*********************************************************************** * Make **********************************************************************/ -device::sptr usrp1e::make(const device_addr_t &){ - throw std::runtime_error("not implemented yet"); +device::sptr usrp1e::make(const device_addr_t &device_addr){ + std::string node = device_addr["node"]; + int node_fd = open(node.c_str(), 0); + if (node_fd < 0){ + throw std::runtime_error(str( + boost::format("Failed to open %s") % node + )); + } + return sptr(new usrp1e_impl(node_fd)); } /*********************************************************************** * Structors **********************************************************************/ -usrp1e_impl::usrp1e_impl(void){ +usrp1e_impl::usrp1e_impl(int node_fd){ + _node_fd = node_fd; + //initialize the mboard mboard_init(); @@ -90,16 +102,59 @@ usrp1e_impl::~usrp1e_impl(void){ /* NOP */ } +/*********************************************************************** + * 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 &, wax::obj &){ - +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()){ + 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(0); //TODO + return; + + case DEVICE_PROP_MAX_TX_SAMPLES: + val = size_t(0); //TODO + 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 &){return 0;} +size_t usrp1e_impl::recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &){return 0;} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp index 3b2fcdd57..7a09254ec 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.hpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -40,20 +40,25 @@ class wax_obj_proxy : public wax::obj{ public: typedef boost::function get_t; typedef boost::function set_t; + typedef boost::shared_ptr sptr; - wax_obj_proxy(void){ + 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; }; - ~wax_obj_proxy(void){ - /* NOP */ - } - void get(const wax::obj &key, wax::obj &val){ return _get(key, val); } @@ -61,10 +66,6 @@ public: void set(const wax::obj &key, const wax::obj &val){ return _set(key, val); } - -private: - get_t _get; - set_t _set; }; /*! @@ -74,12 +75,25 @@ private: */ class usrp1e_impl : public uhd::device{ public: - typedef boost::shared_ptr sptr; - - usrp1e_impl(void); + //structors + usrp1e_impl(int node_fd); ~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: + int _node_fd; + //device functions and settings void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); @@ -88,7 +102,7 @@ private: void mboard_init(void); void mboard_get(const wax::obj &, wax::obj &); void mboard_set(const wax::obj &, const wax::obj &); - wax_obj_proxy _mboard_proxy; + wax_obj_proxy::sptr _mboard_proxy; //xx dboard functions and settings void dboard_init(void); @@ -97,24 +111,24 @@ private: //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 _rx_dboard_proxy; + 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 _tx_dboard_proxy; + 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 _rx_ddc_proxy; + 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 _tx_duc_proxy; + wax_obj_proxy::sptr _tx_duc_proxy; }; #endif /* INCLUDED_USRP1E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 70420fd49..55ac0b192 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -86,8 +86,6 @@ private: */ class usrp2_impl : public uhd::device{ public: - typedef boost::shared_ptr sptr; - /*! * Create a new usrp2 impl base. * \param ctrl_transport the udp transport for control -- cgit v1.2.3 From 09a21dd6d4bc5b7f032e07cfabcba9f55d25b0f6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Mar 2010 15:31:16 +0000 Subject: bit of io work --- host/lib/usrp/usrp1e/usrp1e_impl.cpp | 48 +++++++++++++++++++++++++----------- host/lib/usrp/usrp1e/usrp1e_impl.hpp | 3 ++- 2 files changed, 35 insertions(+), 16 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp index d3b0264a7..8230cc8e4 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -71,21 +71,19 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ * Make **********************************************************************/ device::sptr usrp1e::make(const device_addr_t &device_addr){ - std::string node = device_addr["node"]; - int node_fd = open(node.c_str(), 0); - if (node_fd < 0){ - throw std::runtime_error(str( - boost::format("Failed to open %s") % node - )); - } - return sptr(new usrp1e_impl(node_fd)); + return sptr(new usrp1e_impl(device_addr["node"])); } /*********************************************************************** * Structors **********************************************************************/ -usrp1e_impl::usrp1e_impl(int node_fd){ - _node_fd = node_fd; +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(); @@ -99,7 +97,8 @@ usrp1e_impl::usrp1e_impl(int node_fd){ } usrp1e_impl::~usrp1e_impl(void){ - /* NOP */ + //close the device node file descriptor + ::close(_node_fd); } /*********************************************************************** @@ -136,11 +135,11 @@ void usrp1e_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MAX_RX_SAMPLES: - val = size_t(0); //TODO + val = size_t(_max_num_samples); return; case DEVICE_PROP_MAX_TX_SAMPLES: - val = size_t(0); //TODO + val = size_t(_max_num_samples); return; } @@ -156,5 +155,24 @@ void usrp1e_impl::set(const wax::obj &, const wax::obj &){ /*********************************************************************** * Device IO (TODO) **********************************************************************/ -size_t usrp1e_impl::send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &){return 0;} -size_t usrp1e_impl::recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &){return 0;} +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 index 7a09254ec..c199a0465 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.hpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -76,7 +76,7 @@ private: class usrp1e_impl : public uhd::device{ public: //structors - usrp1e_impl(int node_fd); + usrp1e_impl(const std::string &node); ~usrp1e_impl(void); //the io interface @@ -92,6 +92,7 @@ public: 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 -- cgit v1.2.3 From c81a975766a8831cab1e3123af94b4fe4a09d9bc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 30 Mar 2010 14:12:11 +0000 Subject: compiling with master merge, renamed usrp1e to usrp_e --- host/apps/usrp1e_load_fpga.cpp | 47 ------ host/include/uhd/usrp/CMakeLists.txt | 2 +- host/include/uhd/usrp/usrp1e.hpp | 54 ------ host/include/uhd/usrp/usrp_e.hpp | 54 ++++++ host/lib/CMakeLists.txt | 20 ++- host/lib/usrp/usrp1e/dboard_impl.cpp | 76 --------- host/lib/usrp/usrp1e/dboard_interface.cpp | 189 --------------------- host/lib/usrp/usrp1e/dsp_impl.cpp | 70 -------- host/lib/usrp/usrp1e/fpga-downloader.cc | 262 ------------------------------ host/lib/usrp/usrp1e/mboard_impl.cpp | 46 ------ host/lib/usrp/usrp1e/usrp1e_impl.cpp | 178 -------------------- host/lib/usrp/usrp1e/usrp1e_impl.hpp | 135 --------------- host/lib/usrp/usrp1e/usrp1e_none.cpp | 38 ----- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- host/lib/usrp/usrp_e/dboard_impl.cpp | 76 +++++++++ host/lib/usrp/usrp_e/dboard_interface.cpp | 189 +++++++++++++++++++++ host/lib/usrp/usrp_e/dsp_impl.cpp | 69 ++++++++ host/lib/usrp/usrp_e/fpga-downloader.cc | 262 ++++++++++++++++++++++++++++++ host/lib/usrp/usrp_e/mboard_impl.cpp | 45 +++++ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 179 ++++++++++++++++++++ host/lib/usrp/usrp_e/usrp_e_impl.hpp | 135 +++++++++++++++ host/lib/usrp/usrp_e/usrp_e_none.cpp | 38 +++++ host/utils/CMakeLists.txt | 5 +- host/utils/usrp_e_load_fpga.cpp | 47 ++++++ 24 files changed, 1110 insertions(+), 1108 deletions(-) delete mode 100644 host/apps/usrp1e_load_fpga.cpp delete mode 100644 host/include/uhd/usrp/usrp1e.hpp create mode 100644 host/include/uhd/usrp/usrp_e.hpp delete mode 100644 host/lib/usrp/usrp1e/dboard_impl.cpp delete mode 100644 host/lib/usrp/usrp1e/dboard_interface.cpp delete mode 100644 host/lib/usrp/usrp1e/dsp_impl.cpp delete mode 100644 host/lib/usrp/usrp1e/fpga-downloader.cc delete mode 100644 host/lib/usrp/usrp1e/mboard_impl.cpp delete mode 100644 host/lib/usrp/usrp1e/usrp1e_impl.cpp delete mode 100644 host/lib/usrp/usrp1e/usrp1e_impl.hpp delete mode 100644 host/lib/usrp/usrp1e/usrp1e_none.cpp create mode 100644 host/lib/usrp/usrp_e/dboard_impl.cpp create mode 100644 host/lib/usrp/usrp_e/dboard_interface.cpp create mode 100644 host/lib/usrp/usrp_e/dsp_impl.cpp create mode 100644 host/lib/usrp/usrp_e/fpga-downloader.cc create mode 100644 host/lib/usrp/usrp_e/mboard_impl.cpp create mode 100644 host/lib/usrp/usrp_e/usrp_e_impl.cpp create mode 100644 host/lib/usrp/usrp_e/usrp_e_impl.hpp create mode 100644 host/lib/usrp/usrp_e/usrp_e_none.cpp create mode 100644 host/utils/usrp_e_load_fpga.cpp (limited to 'host/lib/usrp') diff --git a/host/apps/usrp1e_load_fpga.cpp b/host/apps/usrp1e_load_fpga.cpp deleted file mode 100644 index d5960b391..000000000 --- a/host/apps/usrp1e_load_fpga.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#include -#include - -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(), "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(); - uhd::usrp::usrp1e::load_fpga(file); - - return 0; -} diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index bab01fdeb..b9be370bd 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -21,7 +21,7 @@ INSTALL(FILES dboard_id.hpp dboard_interface.hpp dboard_manager.hpp - usrp1e.hpp + usrp_e.hpp usrp2.hpp DESTINATION ${INCLUDE_DIR}/uhd/usrp ) diff --git a/host/include/uhd/usrp/usrp1e.hpp b/host/include/uhd/usrp/usrp1e.hpp deleted file mode 100644 index 75da58453..000000000 --- a/host/include/uhd/usrp/usrp1e.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_UHD_USRP_USRP1E_HPP -#define INCLUDED_UHD_USRP_USRP1E_HPP - -#include -#include - -namespace uhd{ namespace usrp{ - -/*! - * The usrp1e device class. - */ -class UHD_API usrp1e : 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 - */ - static device_addrs_t find(const device_addr_t &hint); - - /*! - * Make a usrp1e from a device address. - * \param addr the device address - * \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 - -#endif /* INCLUDED_UHD_USRP_USRP1E_HPP */ diff --git a/host/include/uhd/usrp/usrp_e.hpp b/host/include/uhd/usrp/usrp_e.hpp new file mode 100644 index 000000000..557058261 --- /dev/null +++ b/host/include/uhd/usrp/usrp_e.hpp @@ -0,0 +1,54 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_USRP_USRP_E_HPP +#define INCLUDED_UHD_USRP_USRP_E_HPP + +#include +#include + +namespace uhd{ namespace usrp{ + +/*! + * The USRP-Embedded device class. + */ +class UHD_API usrp_e : public device{ +public: + /*! + * 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 usrp_e from a device address. + * \param addr the device address + * \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_USRP_E_HPP */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 323b69b14..db5e9d273 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -51,6 +51,8 @@ LIST(APPEND libuhd_sources ######################################################################## # Conditionally add the usrp1e sources ######################################################################## +MESSAGE(STATUS "Configuring usrp-e support...") + INCLUDE(CheckIncludeFiles) SET(usrp1e_required_headers linux/ioctl.h @@ -63,19 +65,19 @@ CHECK_INCLUDE_FILES( ) IF(HAS_USRP1E_REQUIRED_HEADERS) - MESSAGE(STATUS "Building usrp1e support...") + 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 + 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(HAS_USRP1E_REQUIRED_HEADERS) - MESSAGE(STATUS "Skipping usrp1e support...") + MESSAGE(STATUS " Skipping usrp1e support.") LIST(APPEND libuhd_sources - usrp/usrp1e/usrp1e_none.cpp + usrp/usrp_e/usrp_e_none.cpp ) ENDIF(HAS_USRP1E_REQUIRED_HEADERS) diff --git a/host/lib/usrp/usrp1e/dboard_impl.cpp b/host/lib/usrp/usrp1e/dboard_impl.cpp deleted file mode 100644 index a2798dce3..000000000 --- a/host/lib/usrp/usrp1e/dboard_impl.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#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 deleted file mode 100644 index ef91014ac..000000000 --- a/host/lib/usrp/usrp1e/dboard_interface.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include //std::copy -#include "usrp1e_impl.hpp" -#include - -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(&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(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(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 deleted file mode 100644 index 862b89184..000000000 --- a/host/lib/usrp/usrp1e/dsp_impl.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#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 deleted file mode 100644 index f7c78b875..000000000 --- a/host/lib/usrp/usrp1e/fpga-downloader.cc +++ /dev/null @@ -1,262 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -/* - * 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 -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 deleted file mode 100644 index b480f7616..000000000 --- a/host/lib/usrp/usrp1e/mboard_impl.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#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 deleted file mode 100644 index 8230cc8e4..000000000 --- a/host/lib/usrp/usrp1e/usrp1e_impl.cpp +++ /dev/null @@ -1,178 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#include -#include "usrp1e_impl.hpp" -#include //open -#include //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()){ - 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 deleted file mode 100644 index c199a0465..000000000 --- a/host/lib/usrp/usrp1e/usrp1e_impl.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include - -#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 get_t; - typedef boost::function set_t; - typedef boost::shared_ptr 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 deleted file mode 100644 index 94243523d..000000000 --- a/host/lib/usrp/usrp1e/usrp1e_none.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include - -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 usrp1e::find(const device_addr_t &){ - return device_addrs_t(); //return empty list -} - -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 67fbdf8d2..b0ee395fb 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; -STATIC_BLOCK(register_usrp2_device){ +UHD_STATIC_BLOCK(register_usrp2_device){ device::register_device(&usrp2::find, &usrp2::make); } 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..88d04ce7a --- /dev/null +++ b/host/lib/usrp/usrp_e/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 . +// + +#include +#include +#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..c7c7d8c1f --- /dev/null +++ b/host/lib/usrp/usrp_e/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 . +// + +#include +#include //std::copy +#include "usrp_e_impl.hpp" +#include + +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, 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 + ); + + 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, boost::uint16_t mask){ + throw std::runtime_error("not implemented"); +} + +void usrp_e_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 usrp_e_dboard_interface::read_gpio(gpio_bank_t bank){ + throw std::runtime_error("not implemented"); +} + +void usrp_e_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 usrp_e_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(&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 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(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(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 . +// + +#include +#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 . +// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * 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 +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..333fb2e51 --- /dev/null +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -0,0 +1,45 @@ +// +// 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 . +// + +#include +#include "usrp_e_impl.hpp" + +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) + ); +} + +/*********************************************************************** + * Mboard Get + **********************************************************************/ +void usrp_e_impl::mboard_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * 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..e821add8c --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -0,0 +1,179 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include +#include +#include +#include +#include //open +#include //ioctl + +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 + )); + } +} + +/*********************************************************************** + * 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()){ + 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..e593b13ad --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_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 . +// + +#include +#include + +#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 get_t; + typedef boost::function set_t; + typedef boost::shared_ptr 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); + +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_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 . +// + +#include + +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/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 99e648d8a..0b1e058ef 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -19,8 +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(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) 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 . +// + +#include +#include +#include +#include + +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(), "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(); + uhd::usrp::usrp_e::load_fpga(file); + + return 0; +} -- cgit v1.2.3 From 03be4d0673c5e0f597db7d27f535956a591bbeb7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 30 Mar 2010 17:52:27 +0000 Subject: filled in some gpio handling code, some mboard impl, added usrp_e_regs (like memory map) --- host/include/uhd/types/clock_config.hpp | 1 + host/lib/usrp/usrp_e/dboard_impl.cpp | 1 - host/lib/usrp/usrp_e/dboard_interface.cpp | 89 +++++++++++++++++++++++++++---- host/lib/usrp/usrp_e/mboard_impl.cpp | 77 ++++++++++++++++++++++++-- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 3 ++ host/lib/usrp/usrp_e/usrp_e_regs.hpp | 49 +++++++++++++++++ 6 files changed, 206 insertions(+), 14 deletions(-) create mode 100644 host/lib/usrp/usrp_e/usrp_e_regs.hpp (limited to 'host/lib/usrp') 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/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 88d04ce7a..7c87361e0 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -16,7 +16,6 @@ // #include -#include #include "usrp_e_impl.hpp" using namespace uhd::usrp; diff --git a/host/lib/usrp/usrp_e/dboard_interface.cpp b/host/lib/usrp/usrp_e/dboard_interface.cpp index c7c7d8c1f..a343d93b8 100644 --- a/host/lib/usrp/usrp_e/dboard_interface.cpp +++ b/host/lib/usrp/usrp_e/dboard_interface.cpp @@ -15,10 +15,14 @@ // along with this program. If not, see . // +#include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include #include +#include #include //std::copy -#include "usrp_e_impl.hpp" -#include +#include +#include using namespace uhd::usrp; @@ -31,8 +35,8 @@ public: 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); + void set_gpio_ddr(gpio_bank_t, boost::uint16_t); + void write_gpio(gpio_bank_t, boost::uint16_t); boost::uint16_t read_gpio(gpio_bank_t); void write_i2c(int, const byte_vector_t &); @@ -85,20 +89,85 @@ double usrp_e_dboard_interface::get_tx_clock_rate(void){ /*********************************************************************** * GPIO **********************************************************************/ -void usrp_e_dboard_interface::set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ - throw std::runtime_error("not implemented"); +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 bank_to_addr = boost::assign::map_list_of + (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_ddr)) + (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_ddr)) + ; + + //load the data struct + usrp_e_ctl16 data; + data.offset = bank_to_addr[bank]; + data.count = 1; + data.buf[0] = value; + + //call the ioctl + _impl->ioctl(USRP_E_WRITE_CTL16, &data); } -void usrp_e_dboard_interface::write_gpio(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ - throw std::runtime_error("not implemented"); +void usrp_e_dboard_interface::write_gpio(gpio_bank_t bank, boost::uint16_t value){ + //define mapping of gpio bank to register address + static const uhd::dict bank_to_addr = boost::assign::map_list_of + (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_io)) + (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_io)) + ; + + //load the data struct + usrp_e_ctl16 data; + data.offset = bank_to_addr[bank]; + data.count = 1; + data.buf[0] = value; + + //call the ioctl + _impl->ioctl(USRP_E_WRITE_CTL16, &data); } boost::uint16_t usrp_e_dboard_interface::read_gpio(gpio_bank_t bank){ - throw std::runtime_error("not implemented"); + //define mapping of gpio bank to register address + static const uhd::dict bank_to_addr = boost::assign::map_list_of + (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_io)) + (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_io)) + ; + + //load the data struct + usrp_e_ctl16 data; + data.offset = bank_to_addr[bank]; + data.count = 1; + + //call the ioctl + _impl->ioctl(USRP_E_READ_CTL16, &data); + + return data.buf[0]; } void usrp_e_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"); + //define mapping of gpio bank to register address + static const uhd::dict bank_to_addr = boost::assign::map_list_of + (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_sel_low)) + (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_sel_low)) + ; + + //set the gpio selection mux to atr or software controlled + boost::uint16_t low_sel = 0, high_sel = 0; + for(size_t i = 0; i < 16; i++){ + boost::uint16_t code = (mask & (1 << i))? GPIO_SEL_ATR : GPIO_SEL_SW; + if(i < 8) low_sel |= code << (2*i-0); + else high_sel |= code << (2*i-8); + } + + //load the data struct + usrp_e_ctl16 data; + data.offset = bank_to_addr[bank]; + data.count = 2; + data.buf[0] = low_sel; + data.buf[1] = high_sel; + + //call the ioctl + _impl->ioctl(USRP_E_READ_CTL16, &data); + + //----------------------------------------> TODO + //TODO set the atr regs } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 333fb2e51..1d3f9f466 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -15,9 +15,12 @@ // along with this program. If not, see . // -#include #include "usrp_e_impl.hpp" +#include +#include +#include +using namespace uhd; using namespace uhd::usrp; /*********************************************************************** @@ -28,13 +31,81 @@ void usrp_e_impl::mboard_init(void){ 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 &, wax::obj &){ - +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()){ + 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"); + + } } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index e593b13ad..643589754 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include #include #include @@ -95,6 +96,8 @@ 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 &); 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..219f459a5 --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -0,0 +1,49 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E_REGS_HPP +#define INCLUDED_USRP_E_REGS_HPP + +#include + +//////////////////////////////////////////////// +// GPIO, Slave 4 +// +// These go to the daughterboard i/o pins + +#define GPIO_BASE 0x40 + +struct gpio_regs_t{ + boost::uint16_t rx_io; // tx data in high 16, rx in low 16 + boost::uint16_t tx_io; + boost::uint16_t rx_ddr; // 32 bits, 1 means output. tx in high 16, rx in low 16 + boost::uint16_t tx_ddr; + boost::uint16_t tx_sel_low; // 16 2-bit fields select which source goes to TX DB + boost::uint16_t tx_sel_high; + boost::uint16_t rx_sel_low; // 16 2-bit fields select which source goes to RX DB + boost::uint16_t rx_sel_high; +}; + +// 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 2 // if pin is an output, debug lines from FPGA fabric +#define GPIO_SEL_DEBUG_1 3 // if pin is an output, debug lines from FPGA fabric + +//#define gpio_base ((gpio_regs_t *) GPIO_BASE) + +#endif /* INCLUDED_USRP_E_REGS_HPP */ -- cgit v1.2.3 From 38233271a2d2ab84adfc5cc8c9700601933b717a Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 1 Apr 2010 16:55:44 -0700 Subject: preliminary registers definition --- .gitignore | 1 + host/lib/usrp/usrp_e/usrp_e_regs.hpp | 131 +++++++++++++++++++++++++---------- 2 files changed, 95 insertions(+), 37 deletions(-) create mode 100644 .gitignore (limited to 'host/lib/usrp') diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b25c15b81 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index 219f459a5..edd87e649 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -1,49 +1,106 @@ + + +//////////////////////////////////////////////////////////////// // -// 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 . +// 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) -#ifndef INCLUDED_USRP_E_REGS_HPP -#define INCLUDED_USRP_E_REGS_HPP +#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) -#include //////////////////////////////////////////////// -// GPIO, Slave 4 -// -// These go to the daughterboard i/o pins +// 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 GPIO_BASE 0x40 +#define UE_REG_GPIO_BASE UE_REG_SLAVE(4) -struct gpio_regs_t{ - boost::uint16_t rx_io; // tx data in high 16, rx in low 16 - boost::uint16_t tx_io; - boost::uint16_t rx_ddr; // 32 bits, 1 means output. tx in high 16, rx in low 16 - boost::uint16_t tx_ddr; - boost::uint16_t tx_sel_low; // 16 2-bit fields select which source goes to TX DB - boost::uint16_t tx_sel_high; - boost::uint16_t rx_sel_low; // 16 2-bit fields select which source goes to RX DB - boost::uint16_t rx_sel_high; -}; +#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 2 // if pin is an output, debug lines from FPGA fabric -#define GPIO_SEL_DEBUG_1 3 // if pin is an output, debug lines from FPGA fabric +#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 -//#define gpio_base ((gpio_regs_t *) GPIO_BASE) +#endif -#endif /* INCLUDED_USRP_E_REGS_HPP */ -- cgit v1.2.3 From bcd80dae09776eddaf4fdf9c6fb925c0b2586a11 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 1 Apr 2010 17:32:43 +0000 Subject: added peek and poke, using in dboard interface --- host/lib/usrp/usrp_e/dboard_interface.cpp | 106 +++++++++--------------------- host/lib/usrp/usrp_e/mboard_impl.cpp | 2 +- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 48 ++++++++++++++ host/lib/usrp/usrp_e/usrp_e_impl.hpp | 6 ++ 4 files changed, 85 insertions(+), 77 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_interface.cpp b/host/lib/usrp/usrp_e/dboard_interface.cpp index a343d93b8..47948f3d0 100644 --- a/host/lib/usrp/usrp_e/dboard_interface.cpp +++ b/host/lib/usrp/usrp_e/dboard_interface.cpp @@ -22,7 +22,6 @@ #include #include //std::copy #include -#include using namespace uhd::usrp; @@ -34,9 +33,8 @@ public: 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_atr_reg(gpio_bank_t, atr_reg_t, boost::uint16_t); void set_gpio_ddr(gpio_bank_t, boost::uint16_t); - void write_gpio(gpio_bank_t, boost::uint16_t); boost::uint16_t read_gpio(gpio_bank_t); void write_i2c(int, const byte_vector_t &); @@ -48,8 +46,7 @@ public: private: byte_vector_t transact_spi( spi_dev_t dev, - spi_latch_t latch, - spi_push_t push, + spi_edge_t edge, const byte_vector_t &buf, bool readback ); @@ -92,82 +89,40 @@ double usrp_e_dboard_interface::get_tx_clock_rate(void){ 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 bank_to_addr = boost::assign::map_list_of - (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_ddr)) - (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_ddr)) + (GPIO_BANK_RX, UE_REG_GPIO_RX_DDR) + (GPIO_BANK_TX, UE_REG_GPIO_TX_DDR) ; - - //load the data struct - usrp_e_ctl16 data; - data.offset = bank_to_addr[bank]; - data.count = 1; - data.buf[0] = value; - - //call the ioctl - _impl->ioctl(USRP_E_WRITE_CTL16, &data); -} - -void usrp_e_dboard_interface::write_gpio(gpio_bank_t bank, boost::uint16_t value){ - //define mapping of gpio bank to register address - static const uhd::dict bank_to_addr = boost::assign::map_list_of - (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_io)) - (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_io)) - ; - - //load the data struct - usrp_e_ctl16 data; - data.offset = bank_to_addr[bank]; - data.count = 1; - data.buf[0] = value; - - //call the ioctl - _impl->ioctl(USRP_E_WRITE_CTL16, &data); + _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 bank_to_addr = boost::assign::map_list_of - (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_io)) - (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_io)) + (GPIO_BANK_RX, UE_REG_GPIO_RX_IO) + (GPIO_BANK_TX, UE_REG_GPIO_TX_IO) ; - - //load the data struct - usrp_e_ctl16 data; - data.offset = bank_to_addr[bank]; - data.count = 1; - - //call the ioctl - _impl->ioctl(USRP_E_READ_CTL16, &data); - - return data.buf[0]; + return _impl->peek16(bank_to_addr[bank]); } -void usrp_e_dboard_interface::set_atr_reg(gpio_bank_t bank, boost::uint16_t tx_value, boost::uint16_t rx_value, boost::uint16_t mask){ - //define mapping of gpio bank to register address - static const uhd::dict bank_to_addr = boost::assign::map_list_of - (GPIO_RX_BANK, GPIO_BASE + offsetof(gpio_regs_t, rx_sel_low)) - (GPIO_TX_BANK, GPIO_BASE + offsetof(gpio_regs_t, tx_sel_low)) +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 + > 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) + ) ; - - //set the gpio selection mux to atr or software controlled - boost::uint16_t low_sel = 0, high_sel = 0; - for(size_t i = 0; i < 16; i++){ - boost::uint16_t code = (mask & (1 << i))? GPIO_SEL_ATR : GPIO_SEL_SW; - if(i < 8) low_sel |= code << (2*i-0); - else high_sel |= code << (2*i-8); - } - - //load the data struct - usrp_e_ctl16 data; - data.offset = bank_to_addr[bank]; - data.count = 2; - data.buf[0] = low_sel; - data.buf[1] = high_sel; - - //call the ioctl - _impl->ioctl(USRP_E_READ_CTL16, &data); - - //----------------------------------------> TODO - //TODO set the atr regs + _impl->poke16(bank_to_atr_to_addr[bank][atr], value); } /*********************************************************************** @@ -175,15 +130,14 @@ void usrp_e_dboard_interface::set_atr_reg(gpio_bank_t bank, boost::uint16_t tx_v **********************************************************************/ dboard_interface::byte_vector_t usrp_e_dboard_interface::transact_spi( spi_dev_t dev, - spi_latch_t latch, - spi_push_t push, + 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_RX_DEV)? UE_SPI_CTRL_RXNEG : UE_SPI_CTRL_TXNEG; + 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(&data.data); @@ -193,8 +147,8 @@ dboard_interface::byte_vector_t usrp_e_dboard_interface::transact_spi( //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; + 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); diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 1d3f9f466..ba15c394d 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -17,7 +17,7 @@ #include "usrp_e_impl.hpp" #include -#include +#include #include using namespace uhd; diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index e821add8c..3fefd6787 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -16,12 +16,14 @@ // #include "usrp_e_impl.hpp" +#include #include #include #include #include #include //open #include //ioctl +#include using namespace uhd; using namespace uhd::usrp; @@ -113,6 +115,52 @@ void usrp_e_impl::ioctl(int request, void *mem){ } } +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 **********************************************************************/ diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 643589754..21023ae55 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -92,6 +92,12 @@ public: */ 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; -- cgit v1.2.3 From 34854116a4fd287fe681222f2b7a881692e418d3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 13:54:50 +0000 Subject: put the dummy package back in --- host/lib/CMakeLists.txt | 7 +++++++ host/lib/usrp/usrp1e/usrp1e_none.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 host/lib/usrp/usrp1e/usrp1e_none.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 9d328310f..a5345cae4 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -48,6 +48,13 @@ LIST(APPEND libuhd_sources transport/udp_zero_copy_asio.cpp ) +######################################################################## +# Conditionally add the usrp1e sources +######################################################################## +LIST(APPEND libuhd_sources + usrp/usrp1e/usrp1e_none.cpp +) + ######################################################################## # Setup defines for module loading ######################################################################## diff --git a/host/lib/usrp/usrp1e/usrp1e_none.cpp b/host/lib/usrp/usrp1e/usrp1e_none.cpp new file mode 100644 index 000000000..84fb9276c --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_none.cpp @@ -0,0 +1,34 @@ +// +// 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 . +// + +#include + +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 usrp1e::find(const device_addr_t &){ + return device_addrs_t(); //return empty list +} + +device::sptr usrp1e::make(const device_addr_t &){ + throw std::runtime_error("this build has no usrp1e support"); +} -- cgit v1.2.3 From 839d9c39542db356ad1b955e3a3d9e7aabb071bc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 16 Apr 2010 12:58:42 +0000 Subject: pulled in master and got usrp-e code compiling --- host/apps/omap_debug/fetch-kernel.sh | 2 +- host/apps/omap_debug/fetch-module.sh | 2 +- host/lib/CMakeLists.txt | 3 +- host/lib/usrp/usrp_e/dboard_iface.cpp | 218 ++++++++++++++++++++++++++++++ host/lib/usrp/usrp_e/dboard_impl.cpp | 6 +- host/lib/usrp/usrp_e/dboard_interface.cpp | 212 ----------------------------- host/lib/usrp/usrp_e/mboard_impl.cpp | 4 +- host/lib/usrp/usrp_e/usrp_e_iface.cpp | 135 ++++++++++++++++++ host/lib/usrp/usrp_e/usrp_e_iface.hpp | 97 +++++++++++++ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 89 ++---------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 26 +--- 11 files changed, 478 insertions(+), 316 deletions(-) create mode 100644 host/lib/usrp/usrp_e/dboard_iface.cpp delete mode 100644 host/lib/usrp/usrp_e/dboard_interface.cpp create mode 100644 host/lib/usrp/usrp_e/usrp_e_iface.cpp create mode 100644 host/lib/usrp/usrp_e/usrp_e_iface.hpp (limited to 'host/lib/usrp') diff --git a/host/apps/omap_debug/fetch-kernel.sh b/host/apps/omap_debug/fetch-kernel.sh index a3cddb339..f25f139fa 100755 --- a/host/apps/omap_debug/fetch-kernel.sh +++ b/host/apps/omap_debug/fetch-kernel.sh @@ -1,4 +1,4 @@ -if [ $GHQ]; then +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 diff --git a/host/apps/omap_debug/fetch-module.sh b/host/apps/omap_debug/fetch-module.sh index 52fbd4040..0957ad7b4 100755 --- a/host/apps/omap_debug/fetch-module.sh +++ b/host/apps/omap_debug/fetch-module.sh @@ -1,5 +1,5 @@ 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 + scp $GHQ_USER@astro:/workspace/usrp1-e-dev/kernel_usrp/drivers/misc/usrp_e.ko /lib/modules/2.6.34-rc1/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 diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index dfcb88ec9..ff7f2c0df 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -138,11 +138,12 @@ 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/dboard_iface.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 + usrp/usrp_e/usrp_e_iface.cpp ) ELSE(HAVE_USRP_E_REQUIRED_HEADERS) MESSAGE(STATUS " Skipping usrp-e support.") diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp new file mode 100644 index 000000000..12e8fe206 --- /dev/null +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -0,0 +1,218 @@ +// +// 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 . +// + +#include "usrp_e_iface.hpp" +#include "usrp_e_regs.hpp" +#include +#include +#include +#include +#include //i2c and spi constants + +using namespace uhd::usrp; + +class usrp_e_dboard_iface : public dboard_iface{ +public: + usrp_e_dboard_iface(usrp_e_iface::sptr iface); + ~usrp_e_dboard_iface(void); + + void write_aux_dac(unit_t, int, float); + float read_aux_adc(unit_t, int); + + void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); + void set_gpio_ddr(unit_t, boost::uint16_t); + boost::uint16_t read_gpio(unit_t); + + void write_i2c(int, const byte_vector_t &); + byte_vector_t read_i2c(int, size_t); + + void write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + + boost::uint32_t read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + + double get_clock_rate(unit_t); + void set_clock_enabled(unit_t, bool); + +private: + usrp_e_iface::sptr _iface; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +dboard_iface::sptr make_usrp_e_dboard_iface(usrp_e_iface::sptr iface){ + return dboard_iface::sptr(new usrp_e_dboard_iface(iface)); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp_e_dboard_iface::usrp_e_dboard_iface(usrp_e_iface::sptr iface){ + _iface = iface; +} + +usrp_e_dboard_iface::~usrp_e_dboard_iface(void){ + /* NOP */ +} + +/*********************************************************************** + * Clock Rates + **********************************************************************/ +double usrp_e_dboard_iface::get_clock_rate(unit_t){ + throw std::runtime_error("not implemented"); +} + +void usrp_e_dboard_iface::set_clock_enabled(unit_t, bool){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * GPIO + **********************************************************************/ +void usrp_e_dboard_iface::set_gpio_ddr(unit_t bank, boost::uint16_t value){ + //define mapping of gpio bank to register address + static const uhd::dict bank_to_addr = boost::assign::map_list_of + (UNIT_RX, UE_REG_GPIO_RX_DDR) + (UNIT_TX, UE_REG_GPIO_TX_DDR) + ; + _iface->poke16(bank_to_addr[bank], value); +} + +boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t bank){ + //define mapping of gpio bank to register address + static const uhd::dict bank_to_addr = boost::assign::map_list_of + (UNIT_RX, UE_REG_GPIO_RX_IO) + (UNIT_TX, UE_REG_GPIO_TX_IO) + ; + return _iface->peek16(bank_to_addr[bank]); +} + +void usrp_e_dboard_iface::set_atr_reg(unit_t bank, atr_reg_t atr, boost::uint16_t value){ + //define mapping of bank to atr regs to register address + static const uhd::dict< + unit_t, uhd::dict + > bank_to_atr_to_addr = boost::assign::map_list_of + (UNIT_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) + ) + (UNIT_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) + ) + ; + _iface->poke16(bank_to_atr_to_addr[bank][atr], value); +} + +/*********************************************************************** + * SPI + **********************************************************************/ +/*! + * Static function to convert a unit type to a spi slave device number. + * \param unit the dboard interface unit type enum + * \return the slave device number + */ +static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit){ + switch(unit){ + case dboard_iface::UNIT_TX: return UE_SPI_CTRL_TXNEG; + case dboard_iface::UNIT_RX: return UE_SPI_CTRL_RXNEG; + } + throw std::invalid_argument("unknown unit type"); +} + +void usrp_e_dboard_iface::write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); +} + +boost::uint32_t usrp_e_dboard_iface::read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); +} + +/*********************************************************************** + * I2C + **********************************************************************/ +static const size_t max_i2c_data_bytes = 10; + +void usrp_e_dboard_iface::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(mem); + data.addr = i2c_addr; + data.len = buf.size(); + std::copy(buf.begin(), buf.end(), data.data); + + //call the spi ioctl + _iface->ioctl(USRP_E_I2C_WRITE, &data); +} + +dboard_iface::byte_vector_t usrp_e_dboard_iface::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(mem); + data.addr = i2c_addr; + data.len = num_bytes; + + //call the spi ioctl + _iface->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_iface::write_aux_dac(dboard_iface::unit_t unit, int which, float value){ + throw std::runtime_error("not implemented"); +} + +float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, int which){ + throw std::runtime_error("not implemented"); +} diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 7c87361e0..df0f1d9a9 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -28,11 +28,11 @@ void usrp_e_impl::dboard_init(void){ 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_iface::sptr dboard_iface( + make_usrp_e_dboard_iface(_iface) ); _dboard_manager = dboard_manager::make( - rx_dboard_id, tx_dboard_id, dboard_interface + rx_dboard_id, tx_dboard_id, dboard_iface ); //setup the dboard proxies diff --git a/host/lib/usrp/usrp_e/dboard_interface.cpp b/host/lib/usrp/usrp_e/dboard_interface.cpp deleted file mode 100644 index 47948f3d0..000000000 --- a/host/lib/usrp/usrp_e/dboard_interface.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" -#include -#include -#include -#include //std::copy -#include - -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 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 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 - > 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(&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(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(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/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index ba15c394d..2d225c6ea 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -75,8 +75,8 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = prop_names_t(1, ""); //vector of size 1 with empty string return; - case MBOARD_PROP_CLOCK_RATE: - //val = TODO probably remove this property + case MBOARD_PROP_STREAM_CMD: + //val = TODO return; case MBOARD_PROP_RX_DSP: diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp new file mode 100644 index 000000000..d4c988211 --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_iface.cpp @@ -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 . +// + +#include "usrp_e_iface.hpp" +#include //ioctl +#include //ioctl structures and constants +#include +#include + +class usrp_e_iface_impl : public usrp_e_iface{ +public: + + /******************************************************************* + * Structors + ******************************************************************/ + usrp_e_iface_impl(int node_fd){ + _node_fd = node_fd; + } + + ~usrp_e_iface_impl(void){ + /* NOP */ + } + + /******************************************************************* + * IOCTL: provides the communication base for all other calls + ******************************************************************/ + void 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 + )); + } + } + + /******************************************************************* + * Peek and Poke + ******************************************************************/ + void 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 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 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 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]; + } + + /******************************************************************* + * SPI + ******************************************************************/ + boost::uint32_t transact_spi( + int which_slave, + const uhd::usrp::spi_config_t &config, + boost::uint32_t bits, + size_t num_bits, + bool readback + ){ + //load data struct + usrp_e_spi data; + data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; + data.slave = which_slave; + data.length = num_bits; + data.data = bits; + + //load the flags + data.flags = 0; + data.flags |= (config.miso_edge == uhd::usrp::spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; + data.flags |= (config.mosi_edge == uhd::usrp::spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; + + //call the spi ioctl + this->ioctl(USRP_E_SPI, &data); + + //unload the data + return data.data; + } + +private: int _node_fd; +}; + +/*********************************************************************** + * Public Make Function + **********************************************************************/ +usrp_e_iface::sptr usrp_e_iface::make(int node_fd){ + return sptr(new usrp_e_iface_impl(node_fd)); +} diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.hpp b/host/lib/usrp/usrp_e/usrp_e_iface.hpp new file mode 100644 index 000000000..4fc3bb33d --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_iface.hpp @@ -0,0 +1,97 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E_IFACE_HPP +#define INCLUDED_USRP_E_IFACE_HPP + +#include +#include //spi config +#include +#include +#include + +/*! + * The usrp-e interface class: + * Provides a set of functions to implementation layer. + * Including spi, peek, poke, control... + */ +class usrp_e_iface : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new usrp-e interface with the control transport. + * \param node_fd the file descriptor for the kernel module node + * \return a new usrp-e interface object + */ + static sptr make(int node_fd); + + /*! + * 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 + */ + virtual void ioctl(int request, void *mem) = 0; + + /*! + * Write a register (32 bits) + * \param addr the address + * \param data the 32bit data + */ + virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; + + /*! + * Read a register (32 bits) + * \param addr the address + * \return the 32bit data + */ + virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; + + /*! + * Write a register (16 bits) + * \param addr the address + * \param data the 16bit data + */ + virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; + + /*! + * Read a register (16 bits) + * \param addr the address + * \return the 16bit data + */ + virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; + + /*! + * Perform an spi transaction. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write + * \param num_bits how many bits in data + * \param readback true to readback a value + * \return spi data if readback set + */ + virtual boost::uint32_t transact_spi( + int which_slave, + const uhd::usrp::spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ) = 0; +}; + +#endif /* INCLUDED_USRP_E_IFACE_HPP */ diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 3fefd6787..4d08210e2 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -22,8 +22,6 @@ #include #include #include //open -#include //ioctl -#include using namespace uhd; using namespace uhd::usrp; @@ -43,30 +41,24 @@ static std::string abs_path(const std::string &file_path){ /*********************************************************************** * Discovery **********************************************************************/ -device_addrs_t usrp_e::find(const device_addr_t &device_addr){ +device_addrs_t usrp_e::find(const device_addr_t &hint){ 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 node not provided, assume its 0 + if (not hint.has_key("node")){ + device_addr_t new_addr = hint; + new_addr["node"] = "/dev/usrp_e0"; + return usrp_e::find(new_addr); + } + + //use the given device node name + if (fs::exists(hint["node"])){ device_addr_t new_addr; new_addr["name"] = "USRP-E"; - new_addr["node"] = abs_path(device_addr["node"]); + new_addr["node"] = abs_path(hint["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; } @@ -88,6 +80,8 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ )); } + _iface = usrp_e_iface::make(_node_fd); + //initialize the mboard mboard_init(); @@ -104,63 +98,6 @@ usrp_e_impl::~usrp_e_impl(void){ ::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 **********************************************************************/ diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 21023ae55..08ace2ffb 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -15,21 +15,20 @@ // along with this program. If not, see . // -#include +#include "usrp_e_iface.hpp" #include +#include #include #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 + * Make a usrp-e dboard interface. + * \param iface the usrp-e interface object * \return a sptr to a new dboard interface */ -uhd::usrp::dboard_interface::sptr make_usrp_e_dboard_interface(usrp_e_impl *impl); +uhd::usrp::dboard_iface::sptr make_usrp_e_dboard_iface(usrp_e_iface::sptr iface); /*! * Simple wax obj proxy class: @@ -84,22 +83,9 @@ public: 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); + usrp_e_iface::sptr _iface; int _node_fd; uhd::clock_config_t _clock_config; -- cgit v1.2.3 From 61d8449f95c5c9f2c21c310f298e2ef7d66afdbb Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 21 Apr 2010 15:40:59 +0000 Subject: Add register definitions for new transfer scheme. --- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index edd87e649..e7f89db7b 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -28,6 +28,8 @@ #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 +#define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 +#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 ///////////////////////////////////////////////////// // Slave 1 -- UART -- cgit v1.2.3 From 1b924876d7d7216504e604137ed0ade36460169f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 28 Apr 2010 11:25:26 -0700 Subject: usrp-e branch compiling with recent master pulled in --- host/lib/usrp/usrp_e/dboard_iface.cpp | 19 ++++++++++--------- host/lib/usrp/usrp_e/dboard_impl.cpp | 8 ++++---- host/lib/usrp/usrp_e/dsp_impl.cpp | 8 ++++---- host/lib/usrp/usrp_e/mboard_impl.cpp | 15 ++++++--------- host/lib/usrp/usrp_e/usrp_e_iface.cpp | 6 +++--- host/lib/usrp/usrp_e/usrp_e_iface.hpp | 4 ++-- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 5 +++-- 7 files changed, 32 insertions(+), 33 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index 12e8fe206..c4784d29c 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -23,6 +23,7 @@ #include #include //i2c and spi constants +using namespace uhd; using namespace uhd::usrp; class usrp_e_dboard_iface : public dboard_iface{ @@ -37,8 +38,8 @@ public: void set_gpio_ddr(unit_t, boost::uint16_t); boost::uint16_t read_gpio(unit_t); - void write_i2c(int, const byte_vector_t &); - byte_vector_t read_i2c(int, size_t); + void write_i2c(boost::uint8_t, const byte_vector_t &); + byte_vector_t read_i2c(boost::uint8_t, size_t); void write_spi( unit_t unit, @@ -171,14 +172,14 @@ boost::uint32_t usrp_e_dboard_iface::read_write_spi( **********************************************************************/ static const size_t max_i2c_data_bytes = 10; -void usrp_e_dboard_iface::write_i2c(int i2c_addr, const byte_vector_t &buf){ +void usrp_e_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &buf){ //allocate some memory for this transaction - ASSERT_THROW(buf.size() <= max_i2c_data_bytes); + UHD_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(mem); - data.addr = i2c_addr; + data.addr = addr; data.len = buf.size(); std::copy(buf.begin(), buf.end(), data.data); @@ -186,14 +187,14 @@ void usrp_e_dboard_iface::write_i2c(int i2c_addr, const byte_vector_t &buf){ _iface->ioctl(USRP_E_I2C_WRITE, &data); } -dboard_iface::byte_vector_t usrp_e_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){ +byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ //allocate some memory for this transaction - ASSERT_THROW(num_bytes <= max_i2c_data_bytes); + UHD_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(mem); - data.addr = i2c_addr; + data.addr = addr; data.len = num_bytes; //call the spi ioctl @@ -201,7 +202,7 @@ dboard_iface::byte_vector_t usrp_e_dboard_iface::read_i2c(int i2c_addr, size_t n //unload the data byte_vector_t ret(data.len); - ASSERT_THROW(ret.size() == num_bytes); + UHD_ASSERT_THROW(ret.size() == num_bytes); std::copy(data.data, data.data+ret.size(), ret.begin()); return ret; } diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index df0f1d9a9..e87a2c0a5 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -50,26 +50,26 @@ void usrp_e_impl::dboard_init(void){ * RX Dboard Get **********************************************************************/ void usrp_e_impl::rx_dboard_get(const wax::obj &, wax::obj &){ - + UHD_THROW_PROP_GET_ERROR(); } /*********************************************************************** * RX Dboard Set **********************************************************************/ void usrp_e_impl::rx_dboard_set(const wax::obj &, const wax::obj &){ - + UHD_THROW_PROP_SET_ERROR(); } /*********************************************************************** * TX Dboard Get **********************************************************************/ void usrp_e_impl::tx_dboard_get(const wax::obj &, wax::obj &){ - + UHD_THROW_PROP_GET_ERROR(); } /*********************************************************************** * TX Dboard Set **********************************************************************/ void usrp_e_impl::tx_dboard_set(const wax::obj &, const wax::obj &){ - + UHD_THROW_PROP_SET_ERROR(); } diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index e32c76a3d..272ac71b3 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -34,14 +34,14 @@ void usrp_e_impl::rx_ddc_init(void){ * RX DDC Get **********************************************************************/ void usrp_e_impl::rx_ddc_get(const wax::obj &, wax::obj &){ - + UHD_THROW_PROP_GET_ERROR(); } /*********************************************************************** * RX DDC Set **********************************************************************/ void usrp_e_impl::rx_ddc_set(const wax::obj &, const wax::obj &){ - + UHD_THROW_PROP_SET_ERROR(); } /*********************************************************************** @@ -58,12 +58,12 @@ void usrp_e_impl::tx_duc_init(void){ * TX DUC Get **********************************************************************/ void usrp_e_impl::tx_duc_get(const wax::obj &, wax::obj &){ - + UHD_THROW_PROP_GET_ERROR(); } /*********************************************************************** * TX DUC Set **********************************************************************/ void usrp_e_impl::tx_duc_set(const wax::obj &, const wax::obj &){ - + UHD_THROW_PROP_SET_ERROR(); } diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 2d225c6ea..00ce4b782 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -58,7 +58,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DBOARD: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _rx_dboard_proxy->get_link(); return; @@ -67,7 +67,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DBOARD: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _tx_dboard_proxy->get_link(); return; @@ -80,7 +80,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DSP: - ASSERT_THROW(name == "ddc0"); + UHD_ASSERT_THROW(name == "ddc0"); val = _rx_ddc_proxy->get_link(); return; @@ -89,7 +89,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DSP: - ASSERT_THROW(name == "duc0"); + UHD_ASSERT_THROW(name == "duc0"); val = _tx_duc_proxy->get_link(); return; @@ -101,10 +101,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ 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"); - + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -112,5 +109,5 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ * Mboard Set **********************************************************************/ void usrp_e_impl::mboard_set(const wax::obj &, const wax::obj &){ - + UHD_THROW_PROP_SET_ERROR(); } diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp index d4c988211..f12eee177 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.cpp @@ -100,7 +100,7 @@ public: ******************************************************************/ boost::uint32_t transact_spi( int which_slave, - const uhd::usrp::spi_config_t &config, + const uhd::spi_config_t &config, boost::uint32_t bits, size_t num_bits, bool readback @@ -114,8 +114,8 @@ public: //load the flags data.flags = 0; - data.flags |= (config.miso_edge == uhd::usrp::spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; - data.flags |= (config.mosi_edge == uhd::usrp::spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; + data.flags |= (config.miso_edge == uhd::spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; + data.flags |= (config.mosi_edge == uhd::spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; //call the spi ioctl this->ioctl(USRP_E_SPI, &data); diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.hpp b/host/lib/usrp/usrp_e/usrp_e_iface.hpp index 4fc3bb33d..850e15ac4 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.hpp @@ -19,7 +19,7 @@ #define INCLUDED_USRP_E_IFACE_HPP #include -#include //spi config +#include #include #include #include @@ -87,7 +87,7 @@ public: */ virtual boost::uint32_t transact_spi( int which_slave, - const uhd::usrp::spi_config_t &config, + const uhd::spi_config_t &config, boost::uint32_t data, size_t num_bits, bool readback diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 4d08210e2..211b939ee 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -112,7 +112,7 @@ void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MBOARD: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _mboard_proxy->get_link(); return; @@ -128,6 +128,7 @@ void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ val = size_t(_max_num_samples); return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -135,7 +136,7 @@ void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ * Device Set **********************************************************************/ void usrp_e_impl::set(const wax::obj &, const wax::obj &){ - throw std::runtime_error("Cannot set in usrp-e device"); + UHD_THROW_PROP_SET_ERROR(); } /*********************************************************************** -- cgit v1.2.3 From 1c4e9bd614dc8b7a17dc2bd95c322bbea940ca35 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 28 Apr 2010 11:33:10 -0700 Subject: moved i2c into usrp-e interface, used by dboard interface and eeprom --- host/lib/usrp/usrp_e/dboard_iface.cpp | 35 +++---------------------- host/lib/usrp/usrp_e/usrp_e_iface.cpp | 49 ++++++++++++++++++++++++++++++++--- host/lib/usrp/usrp_e/usrp_e_iface.hpp | 2 +- 3 files changed, 50 insertions(+), 36 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index c4784d29c..f69cdd2b4 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -170,41 +170,12 @@ boost::uint32_t usrp_e_dboard_iface::read_write_spi( /*********************************************************************** * I2C **********************************************************************/ -static const size_t max_i2c_data_bytes = 10; - -void usrp_e_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &buf){ - //allocate some memory for this transaction - UHD_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(mem); - data.addr = addr; - data.len = buf.size(); - std::copy(buf.begin(), buf.end(), data.data); - - //call the spi ioctl - _iface->ioctl(USRP_E_I2C_WRITE, &data); +void usrp_e_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ + return _iface->write_i2c(addr, bytes); } byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ - //allocate some memory for this transaction - UHD_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(mem); - data.addr = addr; - data.len = num_bytes; - - //call the spi ioctl - _iface->ioctl(USRP_E_I2C_READ, &data); - - //unload the data - byte_vector_t ret(data.len); - UHD_ASSERT_THROW(ret.size() == num_bytes); - std::copy(data.data, data.data+ret.size(), ret.begin()); - return ret; + return _iface->read_i2c(addr, num_bytes); } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp index f12eee177..41737a716 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.cpp @@ -16,11 +16,14 @@ // #include "usrp_e_iface.hpp" +#include #include //ioctl #include //ioctl structures and constants #include #include +using namespace uhd; + class usrp_e_iface_impl : public usrp_e_iface{ public: @@ -95,12 +98,52 @@ public: return data.buf[0]; } + /******************************************************************* + * I2C + ******************************************************************/ + static const size_t max_i2c_data_bytes = 10; + + void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ + //allocate some memory for this transaction + UHD_ASSERT_THROW(bytes.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(mem); + data.addr = addr; + data.len = bytes.size(); + std::copy(bytes.begin(), bytes.end(), data.data); + + //call the spi ioctl + this->ioctl(USRP_E_I2C_WRITE, &data); + } + + byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ + //allocate some memory for this transaction + UHD_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(mem); + data.addr = addr; + data.len = num_bytes; + + //call the spi ioctl + this->ioctl(USRP_E_I2C_READ, &data); + + //unload the data + byte_vector_t bytes(data.len); + UHD_ASSERT_THROW(bytes.size() == num_bytes); + std::copy(data.data, data.data+bytes.size(), bytes.begin()); + return bytes; + } + /******************************************************************* * SPI ******************************************************************/ boost::uint32_t transact_spi( int which_slave, - const uhd::spi_config_t &config, + const spi_config_t &config, boost::uint32_t bits, size_t num_bits, bool readback @@ -114,8 +157,8 @@ public: //load the flags data.flags = 0; - data.flags |= (config.miso_edge == uhd::spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; - data.flags |= (config.mosi_edge == uhd::spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; + data.flags |= (config.miso_edge == spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; + data.flags |= (config.mosi_edge == spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; //call the spi ioctl this->ioctl(USRP_E_SPI, &data); diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.hpp b/host/lib/usrp/usrp_e/usrp_e_iface.hpp index 850e15ac4..763d19581 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.hpp @@ -29,7 +29,7 @@ * Provides a set of functions to implementation layer. * Including spi, peek, poke, control... */ -class usrp_e_iface : boost::noncopyable{ +class usrp_e_iface : boost::noncopyable, public uhd::i2c_iface{ public: typedef boost::shared_ptr sptr; -- cgit v1.2.3 From 3a8577aeb3c76dce0d0dcf0c9c7ce8d9aaf0a1d8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 29 Apr 2010 11:50:56 +0000 Subject: work on clock control init, added dummy spi slaves: must fix --- host/lib/CMakeLists.txt | 1 + host/lib/ic_reg_maps/.gitignore | 1 + host/lib/ic_reg_maps/gen_ad9522_regs.py | 4 +- host/lib/usrp/usrp_e/clock_ctrl.cpp | 129 ++++++++++++++++++++++++++++++++ host/lib/usrp/usrp_e/clock_ctrl.hpp | 55 ++++++++++++++ host/lib/usrp/usrp_e/dboard_iface.cpp | 4 +- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 9 +++ 7 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 host/lib/usrp/usrp_e/clock_ctrl.cpp create mode 100644 host/lib/usrp/usrp_e/clock_ctrl.hpp (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 310c81bfb..75d4ac2c4 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -177,6 +177,7 @@ CHECK_INCLUDE_FILES( IF(HAVE_USRP_E_REQUIRED_HEADERS) MESSAGE(STATUS " Building usrp-e support.") LIST(APPEND libuhd_sources + usrp/usrp_e/clock_ctrl.cpp usrp/usrp_e/dboard_impl.cpp usrp/usrp_e/dboard_iface.cpp usrp/usrp_e/dsp_impl.cpp diff --git a/host/lib/ic_reg_maps/.gitignore b/host/lib/ic_reg_maps/.gitignore index a74b07aee..053049d05 100644 --- a/host/lib/ic_reg_maps/.gitignore +++ b/host/lib/ic_reg_maps/.gitignore @@ -1 +1,2 @@ /*.pyc +/*.pyo diff --git a/host/lib/ic_reg_maps/gen_ad9522_regs.py b/host/lib/ic_reg_maps/gen_ad9522_regs.py index 63d8abe24..9da51205b 100755 --- a/host/lib/ic_reg_maps/gen_ad9522_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9522_regs.py @@ -42,7 +42,7 @@ reset_all_counters 0x016[4] 0 b_counter_bypass 0x016[3] 0 normal, div1 prescaler_p 0x016[2:0] 6 div1, div2, div2_3, div4_5, div8_9, div16_17, div32_33, div3 status_pin_control 0x017[7:2] 0 -antibacklash_pulse_width 0x017[1:0] 0 2_9ns, 1_3ns, 6_0ns, 2_9ns +antibacklash_pulse_width 0x017[1:0] 0 2_9ns, 1_3ns, 6_0ns enb_cmos_ref_input_dc_off 0x018[7] 0 lock_detect_counter 0x018[6:5] 0 5cyc, 16cyc, 64cyc, 255cyc digital_lock_detect_window 0x018[4] 0 high_range, low_range @@ -60,7 +60,7 @@ enable_ref2_freq_monitor 0x01B[6] 0 enable_ref1_freq_monitor 0x01B[5] 0 refmon_pin_control 0x01B[4:0] 0 disable_switchover_deglitch 0x01C[7] 0 -select_ref2 0x01C[6] 0 ref1, ref2 +select_ref 0x01C[6] 0 ref1, ref2 use_ref_sel_pin 0x01C[5] 0 register, ref_sel enb_auto_ref_switchover 0x01C[4] 0 manual, auto stay_on_ref2 0x01C[3] 0 return_ref1, stay_ref2 diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp new file mode 100644 index 000000000..5f6fb4bfb --- /dev/null +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -0,0 +1,129 @@ +// +// 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 . +// + +#include "clock_ctrl.hpp" +#include "ad9522_regs.hpp" +#include +#include "usrp_e_regs.hpp" //spi slave constants +#include +#include +#include + +using namespace uhd; + +/*********************************************************************** + * Clock Control Implementation + **********************************************************************/ +class clock_ctrl_impl : public clock_ctrl{ +public: + //structors + clock_ctrl_impl(usrp_e_iface::sptr iface); + ~clock_ctrl_impl(void); + + void enable_rx_dboard_clock(bool enb); + void enable_tx_dboard_clock(bool enb); + +private: + usrp_e_iface::sptr _iface; + ad9522_regs_t _ad9522_regs; + + void latch_regs(void){ + _ad9522_regs.io_update = 1; + this->send_reg(0x232); + } + void send_reg(boost::uint16_t addr); +}; + +/*********************************************************************** + * Clock Control Methods + **********************************************************************/ +clock_ctrl_impl::clock_ctrl_impl(usrp_e_iface::sptr iface){ + _iface = iface; + + //init the clock gen registers + //Note: out0 should already be clocking the FPGA or this isnt going to work + _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; + _ad9522_regs.status_pin_control = 0x1; //n divider + _ad9522_regs.ld_pin_control = 0x32; //show ref2 + _ad9522_regs.refmon_pin_control = 0x12; //show ref2 + + _ad9522_regs.enable_ref2 = 1; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; + + _ad9522_regs.r_counter_lsb = 1; + _ad9522_regs.r_counter_msb = 0; + _ad9522_regs.a_counter = 0; + _ad9522_regs.b_counter_lsb = 20; + _ad9522_regs.b_counter_msb = 0; + _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; + + _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; + _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_3_0MA; + + _ad9522_regs.vco_calibration_now = 1; //calibrate it! + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; + _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; + + _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; + _ad9522_regs.divider0_low_cycles = 2; //3 low + _ad9522_regs.divider0_high_cycles = 1; //2 high + + //setup a list of register ranges to write + typedef std::pair range_t; + static const std::vector ranges = boost::assign::list_of + (range_t(0x000, 0x000)) (range_t(0x010, 0x01F)) + (range_t(0x0F0, 0x0FD)) (range_t(0x190, 0x19B)) + (range_t(0x1E0, 0x1E1)) (range_t(0x230, 0x230)) + ; + + //write initial register values and latch/update + BOOST_FOREACH(const range_t &range, ranges){ + for(boost::uint16_t addr = range.first; addr <= range.second; addr++){ + this->send_reg(addr); + } + } + this->latch_regs(); +} + +clock_ctrl_impl::~clock_ctrl_impl(void){ + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); +} + +void clock_ctrl_impl::enable_rx_dboard_clock(bool enb){ + +} + +void clock_ctrl_impl::enable_tx_dboard_clock(bool enb){ + +} + +void clock_ctrl_impl::send_reg(boost::uint16_t addr){ + _iface->transact_spi( + UE_SPI_SS_AD9522, + spi_config_t::EDGE_RISE, + _ad9522_regs.get_write_reg(addr), + 24, false /*no rb*/ + ); +} + +/*********************************************************************** + * Clock Control Make + **********************************************************************/ +clock_ctrl::sptr clock_ctrl::make(usrp_e_iface::sptr iface){ + return sptr(new clock_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/usrp_e/clock_ctrl.hpp b/host/lib/usrp/usrp_e/clock_ctrl.hpp new file mode 100644 index 000000000..d0b896a8f --- /dev/null +++ b/host/lib/usrp/usrp_e/clock_ctrl.hpp @@ -0,0 +1,55 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E_CLOCK_CTRL_HPP +#define INCLUDED_USRP_E_CLOCK_CTRL_HPP + +#include "usrp_e_iface.hpp" +#include +#include + +/*! + * The usrp-e clock control: + * - Setup system clocks. + * - Disable/enable clock lines. + */ +class clock_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new clock control object. + * \param iface the usrp_e iface object + * \return the clock control object + */ + static sptr make(usrp_e_iface::sptr iface); + + /*! + * Enable/disable the rx dboard clock. + * \param enb true to enable + */ + virtual void enable_rx_dboard_clock(bool enb) = 0; + + /*! + * Enable/disable the tx dboard clock. + * \param enb true to enable + */ + virtual void enable_tx_dboard_clock(bool enb) = 0; + +}; + +#endif /* INCLUDED_USRP_E_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index f69cdd2b4..2a3976ba1 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -143,8 +143,8 @@ void usrp_e_dboard_iface::set_atr_reg(unit_t bank, atr_reg_t atr, boost::uint16_ */ static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit){ switch(unit){ - case dboard_iface::UNIT_TX: return UE_SPI_CTRL_TXNEG; - case dboard_iface::UNIT_RX: return UE_SPI_CTRL_RXNEG; + case dboard_iface::UNIT_TX: return UE_SPI_SS_TX_DB; + case dboard_iface::UNIT_RX: return UE_SPI_SS_RX_DB; } throw std::invalid_argument("unknown unit type"); } diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index e7f89db7b..46df8d089 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -50,6 +50,15 @@ #define UE_REG_SPI_BASE UE_REG_SLAVE(2) +//spi slave constants (copied from usrp2, TODO FIXME) +#define UE_SPI_SS_AD9522 1 +#define UE_SPI_SS_AD9777 2 +#define UE_SPI_SS_RX_DAC 4 +#define UE_SPI_SS_RX_ADC 8 +#define UE_SPI_SS_RX_DB 16 +#define UE_SPI_SS_TX_DAC 32 +#define UE_SPI_SS_TX_ADC 64 +#define UE_SPI_SS_TX_DB 128 //////////////////////////////////////////////// // Slave 3 -- I2C Core -- cgit v1.2.3 From 2e222f4a77df389551d08b42a1bf947487d1442f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 3 May 2010 11:30:17 +0000 Subject: spi working, talked to ad9522 --- host/include/uhd/utils/assert.hpp | 9 ++++++++- host/lib/usrp/usrp_e/clock_ctrl.cpp | 14 ++++++++++++-- host/lib/usrp/usrp_e/dboard_impl.cpp | 6 +++--- host/lib/usrp/usrp_e/usrp_e_iface.hpp | 9 +++++++++ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 6 ++++++ host/lib/usrp/usrp_e/usrp_e_impl.hpp | 3 +++ host/lib/usrp/usrp_e/usrp_e_regs.hpp | 14 +++++--------- host/test/error_test.cpp | 5 +++-- host/utils/uhd_find_devices.cpp | 2 +- 9 files changed, 50 insertions(+), 18 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/utils/assert.hpp b/host/include/uhd/utils/assert.hpp index 6aca64f8c..577050aff 100644 --- a/host/include/uhd/utils/assert.hpp +++ b/host/include/uhd/utils/assert.hpp @@ -29,7 +29,14 @@ #include #ifndef BOOST_THROW_EXCEPTION -#define BOOST_THROW_EXCEPTION(x) throw std::runtime_error("") + #include + #include + #define BOOST_THROW_EXCEPTION(x)\ + ::boost::throw_exception( ::boost::enable_error_info(x) <<\ + ::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\ + ::boost::throw_file(__FILE__) <<\ + ::boost::throw_line((int)__LINE__) ) + #endif namespace uhd{ diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 5f6fb4bfb..fa4028cc5 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace uhd; @@ -97,6 +98,14 @@ clock_ctrl_impl::clock_ctrl_impl(usrp_e_iface::sptr iface){ } } this->latch_regs(); + //test read: + //boost::uint32_t reg = _ad9522_regs.get_read_reg(0x01b); + //boost::uint32_t result = _iface->transact_spi( + // UE_SPI_SS_AD9522, + // spi_config_t::EDGE_RISE, + // reg, 24, true /*no*/ + //); + //std::cout << "result " << std::hex << result << std::endl; } clock_ctrl_impl::~clock_ctrl_impl(void){ @@ -113,11 +122,12 @@ void clock_ctrl_impl::enable_tx_dboard_clock(bool enb){ } void clock_ctrl_impl::send_reg(boost::uint16_t addr){ + boost::uint32_t reg = _ad9522_regs.get_write_reg(addr); + std::cout << "clock control write reg: " << std::hex << reg << std::endl; _iface->transact_spi( UE_SPI_SS_AD9522, spi_config_t::EDGE_RISE, - _ad9522_regs.get_write_reg(addr), - 24, false /*no rb*/ + reg, 24, false /*no rb*/ ); } diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index e87a2c0a5..00b5d77d7 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -24,15 +24,15 @@ 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; + _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); + _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); //create a new dboard interface and manager dboard_iface::sptr dboard_iface( make_usrp_e_dboard_iface(_iface) ); _dboard_manager = dboard_manager::make( - rx_dboard_id, tx_dboard_id, dboard_iface + _rx_db_eeprom.id, _tx_db_eeprom.id, dboard_iface ); //setup the dboard proxies diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.hpp b/host/lib/usrp/usrp_e/usrp_e_iface.hpp index 763d19581..016d7448f 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.hpp @@ -24,6 +24,15 @@ #include #include +//////////////////////////////////////////////////////////////////////// +// I2C addresses +//////////////////////////////////////////////////////////////////////// +#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx +#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) +#define I2C_ADDR_TX_DB (I2C_DEV_EEPROM | 0x4) +#define I2C_ADDR_RX_DB (I2C_DEV_EEPROM | 0x5) +//////////////////////////////////////////////////////////////////////// + /*! * The usrp-e interface class: * Provides a set of functions to implementation layer. diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 211b939ee..52bbcdd32 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -21,7 +21,9 @@ #include #include #include +#include #include //open +#include "clock_ctrl.hpp" using namespace uhd; using namespace uhd::usrp; @@ -73,6 +75,8 @@ device::sptr usrp_e::make(const device_addr_t &device_addr){ * Structors **********************************************************************/ usrp_e_impl::usrp_e_impl(const std::string &node){ + std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; + //open the device node and check file descriptor if ((_node_fd = ::open(node.c_str(), O_RDWR)) < 0){ throw std::runtime_error(str( @@ -82,6 +86,8 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ _iface = usrp_e_iface::make(_node_fd); + clock_ctrl::sptr my_clk_ctrl = clock_ctrl::make(_iface); + //initialize the mboard mboard_init(); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 08ace2ffb..23e36ed05 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -17,6 +17,7 @@ #include "usrp_e_iface.hpp" #include +#include #include #include @@ -105,11 +106,13 @@ private: uhd::usrp::dboard_manager::sptr _dboard_manager; //rx dboard functions and settings + uhd::usrp::dboard_eeprom_t _rx_db_eeprom; 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 + uhd::usrp::dboard_eeprom_t _tx_db_eeprom; 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; diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index 46df8d089..7f35212f4 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -50,15 +50,11 @@ #define UE_REG_SPI_BASE UE_REG_SLAVE(2) -//spi slave constants (copied from usrp2, TODO FIXME) -#define UE_SPI_SS_AD9522 1 -#define UE_SPI_SS_AD9777 2 -#define UE_SPI_SS_RX_DAC 4 -#define UE_SPI_SS_RX_ADC 8 -#define UE_SPI_SS_RX_DB 16 -#define UE_SPI_SS_TX_DAC 32 -#define UE_SPI_SS_TX_ADC 64 -#define UE_SPI_SS_TX_DB 128 +//spi slave constants +#define UE_SPI_SS_AD9522 (1 << 3) +#define UE_SPI_SS_AD9862 (1 << 2) +#define UE_SPI_SS_TX_DB (1 << 1) +#define UE_SPI_SS_RX_DB (1 << 0) //////////////////////////////////////////////// // Slave 3 -- I2C Core diff --git a/host/test/error_test.cpp b/host/test/error_test.cpp index c5b0af45e..3f2479f99 100644 --- a/host/test/error_test.cpp +++ b/host/test/error_test.cpp @@ -17,7 +17,7 @@ #include #include -#include +//#include #include #include @@ -30,11 +30,12 @@ BOOST_AUTO_TEST_CASE(test_assert_has){ //verify the std::has utility BOOST_CHECK(std::has(vec, 2)); BOOST_CHECK(not std::has(vec, 1)); - +/* std::cout << "The output of the assert_has error:" << std::endl; try{ uhd::assert_has(vec, 1, "prime"); }catch(const boost::exception &e){ std::cout << boost::diagnostic_information(e) << std::endl; } +*/ } diff --git a/host/utils/uhd_find_devices.cpp b/host/utils/uhd_find_devices.cpp index b778eeb68..8281c92bc 100644 --- a/host/utils/uhd_find_devices.cpp +++ b/host/utils/uhd_find_devices.cpp @@ -53,7 +53,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << "-- UHD Device " << i << std::endl; std::cout << "--------------------------------------------------" << std::endl; std::cout << device_addrs[i].to_pp_string() << std::endl << std::endl; - //uhd::device::make(device_addrs[i]); //test make + uhd::device::make(device_addrs[i]); //test make } return 0; -- cgit v1.2.3 From 8f21adbed40db490bec8ead6b8d50d2b3d1a4136 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 4 May 2010 09:32:38 +0000 Subject: created codec control for ad9862, wip --- host/lib/CMakeLists.txt | 1 + host/lib/ic_reg_maps/gen_ad9862_regs.py | 16 ++--- host/lib/usrp/usrp_e/clock_ctrl.cpp | 39 +++++++++- host/lib/usrp/usrp_e/codec_ctrl.cpp | 122 ++++++++++++++++++++++++++++++++ host/lib/usrp/usrp_e/codec_ctrl.hpp | 73 +++++++++++++++++++ host/lib/usrp/usrp_e/usrp_e_iface.cpp | 7 +- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 8 ++- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 8 +++ 8 files changed, 259 insertions(+), 15 deletions(-) create mode 100644 host/lib/usrp/usrp_e/codec_ctrl.cpp create mode 100644 host/lib/usrp/usrp_e/codec_ctrl.hpp (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 20373cd59..be57699fc 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -185,6 +185,7 @@ IF(HAVE_USRP_E_REQUIRED_HEADERS) MESSAGE(STATUS " Building usrp-e support.") LIST(APPEND libuhd_sources usrp/usrp_e/clock_ctrl.cpp + usrp/usrp_e/codec_ctrl.cpp usrp/usrp_e/dboard_impl.cpp usrp/usrp_e/dboard_iface.cpp usrp/usrp_e/dsp_impl.cpp diff --git a/host/lib/ic_reg_maps/gen_ad9862_regs.py b/host/lib/ic_reg_maps/gen_ad9862_regs.py index fdbea5828..2094f5e4b 100755 --- a/host/lib/ic_reg_maps/gen_ad9862_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9862_regs.py @@ -30,14 +30,14 @@ soft_reset 0[5] 0 ######################################################################## ## Rx Power Down ######################################################################## -pd_vref_diff 1[7] 0 -pd_vref 1[6] 0 -pd_rx_digital 1[5] 0 -pd_rx_channel_b 1[4] 0 -pd_rx_channel_a 1[3] 0 -pd_buffer_b 1[2] 0 -pd_buffer_a 1[1] 0 -pd_all_rx 1[0] 0 +vref_diff_pd 1[7] 0 +vref_pd 1[6] 0 +rx_digital_pd 1[5] 0 +rx_channel_b_pd 1[4] 0 +rx_channel_a_pd 1[3] 0 +buffer_b_pd 1[2] 0 +buffer_a_pd 1[1] 0 +all_rx_pd 1[0] 0 ######################################################################## ## Rx A and B ######################################################################## diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index fa4028cc5..2fe3c9294 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -37,6 +37,7 @@ public: void enable_rx_dboard_clock(bool enb); void enable_tx_dboard_clock(bool enb); + void enable_codec_clock(bool enb); private: usrp_e_iface::sptr _iface; @@ -79,10 +80,22 @@ clock_ctrl_impl::clock_ctrl_impl(usrp_e_iface::sptr iface){ _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; + //setup fpga master clock _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; _ad9522_regs.divider0_low_cycles = 2; //3 low _ad9522_regs.divider0_high_cycles = 1; //2 high + //setup codec clock + _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; + _ad9522_regs.divider1_low_cycles = 2; //3 low + _ad9522_regs.divider1_high_cycles = 1; //2 high + + //setup test clock (same divider as codec clock) + _ad9522_regs.out4_format = ad9522_regs_t::OUT4_FORMAT_CMOS; + _ad9522_regs.out4_cmos_configuration = (true)? + ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : + ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; + //setup a list of register ranges to write typedef std::pair range_t; static const std::vector ranges = boost::assign::list_of @@ -106,6 +119,8 @@ clock_ctrl_impl::clock_ctrl_impl(usrp_e_iface::sptr iface){ // reg, 24, true /*no*/ //); //std::cout << "result " << std::hex << result << std::endl; + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); } clock_ctrl_impl::~clock_ctrl_impl(void){ @@ -114,16 +129,34 @@ clock_ctrl_impl::~clock_ctrl_impl(void){ } void clock_ctrl_impl::enable_rx_dboard_clock(bool enb){ - + _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_CMOS; + _ad9522_regs.out9_cmos_configuration = (enb)? + ad9522_regs_t::OUT9_CMOS_CONFIGURATION_B_ON : + ad9522_regs_t::OUT9_CMOS_CONFIGURATION_OFF; + this->send_reg(0x0F9); + + _ad9522_regs.divider3_low_cycles = 2; //3 low + _ad9522_regs.divider3_high_cycles = 1; //2 high + this->send_reg(0x199); + this->latch_regs(); } void clock_ctrl_impl::enable_tx_dboard_clock(bool enb){ - + _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_CMOS; + _ad9522_regs.out6_cmos_configuration = (enb)? + ad9522_regs_t::OUT6_CMOS_CONFIGURATION_B_ON : + ad9522_regs_t::OUT6_CMOS_CONFIGURATION_OFF; + this->send_reg(0x0F6); + + _ad9522_regs.divider2_low_cycles = 2; //3 low + _ad9522_regs.divider2_high_cycles = 1; //2 high + this->send_reg(0x196); + this->latch_regs(); } void clock_ctrl_impl::send_reg(boost::uint16_t addr){ boost::uint32_t reg = _ad9522_regs.get_write_reg(addr); - std::cout << "clock control write reg: " << std::hex << reg << std::endl; + //std::cout << "clock control write reg: " << std::hex << reg << std::endl; _iface->transact_spi( UE_SPI_SS_AD9522, spi_config_t::EDGE_RISE, diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp new file mode 100644 index 000000000..daa6ed3e3 --- /dev/null +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -0,0 +1,122 @@ +// +// 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 . +// + +#include "codec_ctrl.hpp" +#include "ad9862_regs.hpp" +#include +#include "usrp_e_regs.hpp" //spi slave constants +#include +//#include +//#include +#include + + //test out codec ls dac/adc + //ad9862_regs_t ad9862_regs; + //ad9862_regs.select_a = ad9862_regs_t::SELECT_A_AUX_ADC1; + //ad9862_regs.aux_dac_a = 0xff/2; + //_iface->transact_spi( + // UE_SPI_SS_AD9862, + // spi_config_t::EDGE_RISE, + // ad9862_regs.get_write_reg(34), 16, false /*no rb*/ + //); + //_iface->transact_spi( + // UE_SPI_SS_AD9862, + // spi_config_t::EDGE_RISE, + // ad9862_regs.get_write_reg(36), 16, false /*no rb*/ + //); + //boost::uint32_t val = _iface->transact_spi( + // UE_SPI_SS_AD9862, + // spi_config_t::EDGE_RISE, + // ad9862_regs.get_read_reg(29), 16, true + //); + //std::cout << "value: " << std::hex << val << std::endl; + +using namespace uhd; + +/*********************************************************************** + * Codec Control Implementation + **********************************************************************/ +class codec_ctrl_impl : public codec_ctrl{ +public: + //structors + codec_ctrl_impl(usrp_e_iface::sptr iface); + ~codec_ctrl_impl(void); + + //aux adc and dac control + float read_aux_adc(aux_adc_t which); + void read_aux_adc(aux_dac_t which, float volts); + +private: + usrp_e_iface::sptr _iface; + ad9862_regs_t _ad9862_regs; + void send_reg(boost::uint8_t addr); +}; + +/*********************************************************************** + * Codec Control Methods + **********************************************************************/ +codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ + _iface = iface; + + //soft reset + _ad9862_regs.soft_reset = 1; + this->send_reg(0); + + //initialize the codec register settings + _ad9862_regs.sdio_bidir = ad9862_regs_t::SDIO_BIDIR_SDIO_SDO; + _ad9862_regs.lsb_first = ad9862_regs_t::LSB_FIRST_MSB; + _ad9862_regs.soft_reset = 0; + + //write the register settings to the codec + for (uint8_t addr = 0; addr <= 50; addr++){ + this->send_reg(addr); + } +} + +codec_ctrl_impl::~codec_ctrl_impl(void){ + _ad9862_regs.all_rx_pd = 1; + this->send_reg(1); + _ad9862_regs.tx_digital_pd = 1; + _ad9862_regs.tx_analog_pd = ad9862_regs_t::TX_ANALOG_PD_BOTH; + this->send_reg(8); +} + +float codec_ctrl_impl::read_aux_adc(aux_adc_t which){ + return 0; + +} + +void codec_ctrl_impl::read_aux_adc(aux_dac_t which, float volts){ + +} + +void codec_ctrl_impl::send_reg(boost::uint8_t addr){ + boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); + //std::cout << "codec control write reg: " << std::hex << reg << std::endl; + _iface->transact_spi( + UE_SPI_SS_AD9862, + spi_config_t::EDGE_RISE, + reg, 24, false /*no rb*/ + ); +} + +/*********************************************************************** + * Codec Control Make + **********************************************************************/ +codec_ctrl::sptr codec_ctrl::make(usrp_e_iface::sptr iface){ + return sptr(new codec_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/usrp_e/codec_ctrl.hpp b/host/lib/usrp/usrp_e/codec_ctrl.hpp new file mode 100644 index 000000000..0fe70c4a2 --- /dev/null +++ b/host/lib/usrp/usrp_e/codec_ctrl.hpp @@ -0,0 +1,73 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E_CODEC_CTRL_HPP +#define INCLUDED_USRP_E_CODEC_CTRL_HPP + +#include "usrp_e_iface.hpp" +#include +#include + +/*! + * The usrp-e codec control: + * - Init/power down codec. + * - Read aux adc, write aux dac. + */ +class codec_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new clock control object. + * \param iface the usrp_e iface object + * \return the clock control object + */ + static sptr make(usrp_e_iface::sptr iface); + + //! aux adc identifier constants + enum aux_adc_t{ + AUX_ADC_A2 = 0xA2, + AUX_ADC_A1 = 0xA1, + AUX_ADC_B2 = 0xB2, + AUX_ADC_B1 = 0xB1 + }; + + /*! + * Read the aux adc. + * \param which which of the 4 adcs + * \return a value in volts + */ + virtual float read_aux_adc(aux_adc_t which) = 0; + + //! aux dac identifier constants + enum aux_dac_t{ + AUX_DAC_A = 0xA, + AUX_DAC_B = 0xB, + AUX_DAC_C = 0xC, + AUX_DAC_D = 0xD + }; + + /*! + * Write the aux dac. + * \param which which of the 4 dacs + * \param volts the level in in volts + */ + virtual void read_aux_adc(aux_dac_t which, float volts) = 0; + +}; + +#endif /* INCLUDED_USRP_E_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp index 41737a716..1dbe383fa 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.cpp @@ -20,6 +20,7 @@ #include //ioctl #include //ioctl structures and constants #include +#include //mutex #include using namespace uhd; @@ -42,6 +43,8 @@ public: * IOCTL: provides the communication base for all other calls ******************************************************************/ void ioctl(int request, void *mem){ + boost::mutex::scoped_lock lock(_ctrl_mutex); + if (::ioctl(_node_fd, request, mem) < 0){ throw std::runtime_error(str( boost::format("ioctl failed with request %d") % request @@ -167,7 +170,9 @@ public: return data.data; } -private: int _node_fd; +private: + int _node_fd; + boost::mutex _ctrl_mutex; }; /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 52bbcdd32..b6fed6a74 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -23,7 +23,6 @@ #include #include #include //open -#include "clock_ctrl.hpp" using namespace uhd; using namespace uhd::usrp; @@ -84,9 +83,12 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ )); } - _iface = usrp_e_iface::make(_node_fd); + sleep(1); //FIXME sleep here until the kernel driver stops hanging - clock_ctrl::sptr my_clk_ctrl = clock_ctrl::make(_iface); + //setup various interfaces into hardware + _iface = usrp_e_iface::make(_node_fd); + _clock_ctrl = clock_ctrl::make(_iface); + _codec_ctrl = codec_ctrl::make(_iface); //initialize the mboard mboard_init(); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 23e36ed05..6746e012a 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -16,6 +16,8 @@ // #include "usrp_e_iface.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" #include #include #include @@ -91,6 +93,12 @@ private: uhd::clock_config_t _clock_config; + //ad9522 clock control + clock_ctrl::sptr _clock_ctrl; + + //ad9862 codec control + codec_ctrl::sptr _codec_ctrl; + //device functions and settings void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); -- cgit v1.2.3 From 06bcfc6b872d8efcb94b312b963f18678a862b93 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 May 2010 22:00:21 +0000 Subject: moved usrp_e specific build stuff into its own cmake file --- host/lib/CMakeLists.txt | 37 +-------------------------- host/lib/usrp/usrp_e/CMakeLists.txt | 51 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 36 deletions(-) create mode 100644 host/lib/usrp/usrp_e/CMakeLists.txt (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index f64f1dbac..6cf896db8 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -72,42 +72,7 @@ INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/transport/CMakeLists.txt) INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/CMakeLists.txt) INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/dboard/CMakeLists.txt) INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/usrp2/CMakeLists.txt) - -######################################################################## -# 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/clock_ctrl.cpp - usrp/usrp_e/codec_ctrl.cpp - usrp/usrp_e/dboard_impl.cpp - usrp/usrp_e/dboard_iface.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 - usrp/usrp_e/usrp_e_iface.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) +INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/usrp_e/CMakeLists.txt) ######################################################################## # Setup defines for module loading diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt new file mode 100644 index 000000000..2eff3147d --- /dev/null +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -0,0 +1,51 @@ +# +# 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 . +# + +#This file will be included by cmake, use absolute paths! + +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.") + LIBUHD_APPEND_SOURCES( + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/clock_ctrl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_ctrl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_iface.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dsp_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/fpga-downloader.cc + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/mboard_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.cpp + ) +ELSE(HAVE_USRP_E_REQUIRED_HEADERS) + MESSAGE(STATUS " Skipping usrp-e support.") + LIBUHD_APPEND_SOURCES( + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_none.cpp + ) +ENDIF(HAVE_USRP_E_REQUIRED_HEADERS) -- cgit v1.2.3 From 272b08ce9a66b3ba1b9dc91922afff410145231f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 7 May 2010 01:02:20 +0000 Subject: work on codec control, writing aux dacs, read aux adc --- host/lib/ic_reg_maps/gen_ad9862_regs.py | 2 +- host/lib/usrp/usrp_e/CMakeLists.txt | 28 +++--- host/lib/usrp/usrp_e/clock_ctrl.cpp | 1 - host/lib/usrp/usrp_e/codec_ctrl.cpp | 145 +++++++++++++++++++++++++------- host/lib/usrp/usrp_e/codec_ctrl.hpp | 10 ++- 5 files changed, 141 insertions(+), 45 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/ic_reg_maps/gen_ad9862_regs.py b/host/lib/ic_reg_maps/gen_ad9862_regs.py index 2094f5e4b..4444c6240 100755 --- a/host/lib/ic_reg_maps/gen_ad9862_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9862_regs.py @@ -233,7 +233,7 @@ boost::uint16_t get_write_reg(boost::uint8_t addr){ } boost::uint16_t get_read_reg(boost::uint8_t addr){ - return (boost::uint16_t(addr) << 8) | (1 << 7); + return (boost::uint16_t(addr) << 8) | (1 << 15); } """ diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index 2eff3147d..c25b2cba4 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -17,18 +17,26 @@ #This file will be included by cmake, use absolute paths! +######################################################################## +# Helpful macro to check for required headers +######################################################################## +INCLUDE(CheckIncludeFileCXX) +SET(HAVE_USRP_E_REQUIRED_HEADERS TRUE) +MACRO(USRP_E_REQUIRE_HEADER header variable) + CHECK_INCLUDE_FILE_CXX(${header} ${variable}) + IF(NOT ${variable}) + SET(HAVE_USRP_E_REQUIRED_HEADERS FALSE) + ENDIF(NOT ${variable}) +ENDMACRO(USRP_E_REQUIRE_HEADER) + +######################################################################## +# Conditionally configure the USRP-E support +######################################################################## 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 -) +USRP_E_REQUIRE_HEADER(linux/ioctl.h HAVE_LINUX_IOCTL_H) +USRP_E_REQUIRE_HEADER(linux/spi/spidev.h HAVE_LINUX_SPI_SPIDEV_H) +USRP_E_REQUIRE_HEADER(linux/usrp_e.h HAVE_LINUX_USRP_E_H) IF(HAVE_USRP_E_REQUIRED_HEADERS) MESSAGE(STATUS " Building usrp-e support.") diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 2fe3c9294..9c2ddf670 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -37,7 +37,6 @@ public: void enable_rx_dboard_clock(bool enb); void enable_tx_dboard_clock(bool enb); - void enable_codec_clock(bool enb); private: usrp_e_iface::sptr _iface; diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index daa6ed3e3..a430f2c6f 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -17,34 +17,16 @@ #include "codec_ctrl.hpp" #include "ad9862_regs.hpp" +#include +#include +#include #include +#include +#include #include "usrp_e_regs.hpp" //spi slave constants #include -//#include -//#include #include - //test out codec ls dac/adc - //ad9862_regs_t ad9862_regs; - //ad9862_regs.select_a = ad9862_regs_t::SELECT_A_AUX_ADC1; - //ad9862_regs.aux_dac_a = 0xff/2; - //_iface->transact_spi( - // UE_SPI_SS_AD9862, - // spi_config_t::EDGE_RISE, - // ad9862_regs.get_write_reg(34), 16, false /*no rb*/ - //); - //_iface->transact_spi( - // UE_SPI_SS_AD9862, - // spi_config_t::EDGE_RISE, - // ad9862_regs.get_write_reg(36), 16, false /*no rb*/ - //); - //boost::uint32_t val = _iface->transact_spi( - // UE_SPI_SS_AD9862, - // spi_config_t::EDGE_RISE, - // ad9862_regs.get_read_reg(29), 16, true - //); - //std::cout << "value: " << std::hex << val << std::endl; - using namespace uhd; /*********************************************************************** @@ -58,16 +40,18 @@ public: //aux adc and dac control float read_aux_adc(aux_adc_t which); - void read_aux_adc(aux_dac_t which, float volts); + void write_aux_dac(aux_dac_t which, float volts); private: usrp_e_iface::sptr _iface; ad9862_regs_t _ad9862_regs; + aux_adc_t _last_aux_adc_a, _last_aux_adc_b; void send_reg(boost::uint8_t addr); + void recv_reg(boost::uint8_t addr); }; /*********************************************************************** - * Codec Control Methods + * Codec Control Structors **********************************************************************/ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ _iface = iface; @@ -88,6 +72,13 @@ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ } codec_ctrl_impl::~codec_ctrl_impl(void){ + //set aux dacs to zero + this->write_aux_dac(AUX_DAC_A, 0); + this->write_aux_dac(AUX_DAC_B, 0); + this->write_aux_dac(AUX_DAC_C, 0); + this->write_aux_dac(AUX_DAC_D, 0); + + //power down _ad9862_regs.all_rx_pd = 1; this->send_reg(1); _ad9862_regs.tx_digital_pd = 1; @@ -95,23 +86,119 @@ codec_ctrl_impl::~codec_ctrl_impl(void){ this->send_reg(8); } +/*********************************************************************** + * Codec Control AUX ADC Methods + **********************************************************************/ +static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){ + return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; +} + float codec_ctrl_impl::read_aux_adc(aux_adc_t which){ - return 0; + //check to see if the switch needs to be set + bool write_switch = false; + switch(which){ + + case AUX_ADC_A1: + case AUX_ADC_A2: + if (which != _last_aux_adc_a){ + _ad9862_regs.select_a = (which == AUX_ADC_A1)? + ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2; + _last_aux_adc_a = which; + write_switch = true; + } + break; + + case AUX_ADC_B1: + case AUX_ADC_B2: + if (which != _last_aux_adc_b){ + _ad9862_regs.select_b = (which == AUX_ADC_B1)? + ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2; + _last_aux_adc_b = which; + write_switch = true; + } + break; + + } + //write the switch if it changed + if(write_switch) this->send_reg(34); + + //map aux adcs to register values to read + static const uhd::dict aux_dac_to_addr = boost::assign::map_list_of + (AUX_ADC_A2, 26) (AUX_ADC_A1, 28) + (AUX_ADC_B2, 30) (AUX_ADC_B1, 32) + ; + + //read the value + this->recv_reg(aux_dac_to_addr[which]+0); + this->recv_reg(aux_dac_to_addr[which]+1); + + //return the value scaled to volts + switch(which){ + case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0); + case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0); + case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0); + case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0); + } + UHD_ASSERT_THROW(false); } -void codec_ctrl_impl::read_aux_adc(aux_dac_t which, float volts){ - +/*********************************************************************** + * Codec Control AUX DAC Methods + **********************************************************************/ +void codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ + //special case for aux dac d (aka sigma delta word) + if (which == AUX_DAC_D){ + boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff); + _ad9862_regs.sig_delt_11_4 = boost::uint8_t(dac_word >> 4); + _ad9862_regs.sig_delt_3_0 = boost::uint8_t(dac_word & 0xf); + this->send_reg(42); + this->send_reg(43); + return; + } + + //calculate the dac word for aux dac a, b, c + boost::uint8_t dac_word = std::clip(boost::math::iround(volts*0xff/3.3), 0, 0xff); + + //setup a lookup table for the aux dac params (reg ref, reg addr) + typedef boost::tuple dac_params_t; + uhd::dict aux_dac_to_params = boost::assign::map_list_of + (AUX_DAC_A, dac_params_t(&_ad9862_regs.aux_dac_a, 36)) + (AUX_DAC_B, dac_params_t(&_ad9862_regs.aux_dac_b, 37)) + (AUX_DAC_C, dac_params_t(&_ad9862_regs.aux_dac_c, 38)) + ; + + //set the aux dac register + UHD_ASSERT_THROW(aux_dac_to_params.has_key(which)); + boost::uint8_t *reg_ref, reg_addr; + boost::tie(reg_ref, reg_addr) = aux_dac_to_params[which]; + *reg_ref = dac_word; + this->send_reg(reg_addr); } +/*********************************************************************** + * Codec Control SPI Methods + **********************************************************************/ void codec_ctrl_impl::send_reg(boost::uint8_t addr){ boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); //std::cout << "codec control write reg: " << std::hex << reg << std::endl; _iface->transact_spi( UE_SPI_SS_AD9862, spi_config_t::EDGE_RISE, - reg, 24, false /*no rb*/ + reg, 16, false /*no rb*/ + ); +} + +void codec_ctrl_impl::recv_reg(boost::uint8_t addr){ + boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); + //std::cout << "codec control read reg: " << std::hex << reg << std::endl; + boost::uint32_t ret = _iface->transact_spi( + UE_SPI_SS_AD9862, + spi_config_t::EDGE_RISE, + reg, 16, true /*rb*/ ); + //std::cout << "codec control read ret: " << std::hex << ret << std::endl; + _ad9862_regs.set_reg(addr, boost::uint16_t(ret)); } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/codec_ctrl.hpp b/host/lib/usrp/usrp_e/codec_ctrl.hpp index 0fe70c4a2..efdcd7142 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.hpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.hpp @@ -47,7 +47,9 @@ public: }; /*! - * Read the aux adc. + * Read an auxiliary adc: + * The internals remember which aux adc was read last. + * Therefore, the aux adc switch is only changed as needed. * \param which which of the 4 adcs * \return a value in volts */ @@ -58,15 +60,15 @@ public: AUX_DAC_A = 0xA, AUX_DAC_B = 0xB, AUX_DAC_C = 0xC, - AUX_DAC_D = 0xD + AUX_DAC_D = 0xD //really the sigma delta output }; /*! - * Write the aux dac. + * Write an auxiliary dac. * \param which which of the 4 dacs * \param volts the level in in volts */ - virtual void read_aux_adc(aux_dac_t which, float volts) = 0; + virtual void write_aux_dac(aux_dac_t which, float volts) = 0; }; -- cgit v1.2.3 From 6ef09d18def4afdd6413188ab63ee38dbae4e9d8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 7 May 2010 21:51:06 +0000 Subject: filled in dboard interface with codec and clock control --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 4 ++ host/lib/usrp/usrp_e/clock_ctrl.hpp | 18 +++++++ host/lib/usrp/usrp_e/dboard_iface.cpp | 88 ++++++++++++++++++++++++----------- host/lib/usrp/usrp_e/dboard_impl.cpp | 6 ++- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 2 - host/lib/usrp/usrp_e/usrp_e_impl.hpp | 8 +++- 6 files changed, 95 insertions(+), 31 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 9c2ddf670..5f7269412 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -38,6 +38,10 @@ public: void enable_rx_dboard_clock(bool enb); void enable_tx_dboard_clock(bool enb); + double get_fpga_clock_rate(void){return 64e6;} + double get_rx_dboard_clock_rate(void){return get_fpga_clock_rate();} + double get_tx_dboard_clock_rate(void){return get_fpga_clock_rate();} + private: usrp_e_iface::sptr _iface; ad9522_regs_t _ad9522_regs; diff --git a/host/lib/usrp/usrp_e/clock_ctrl.hpp b/host/lib/usrp/usrp_e/clock_ctrl.hpp index d0b896a8f..994b83564 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.hpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.hpp @@ -38,6 +38,24 @@ public: */ static sptr make(usrp_e_iface::sptr iface); + /*! + * Get the rate of the fpga clock line. + * \return the fpga clock rate in Hz + */ + virtual double get_fpga_clock_rate(void) = 0; + + /*! + * Get the rate of the dboard clock clock line. + * \return the dboard clock rate in Hz + */ + virtual double get_rx_dboard_clock_rate(void) = 0; + + /*! + * Get the rate of the dboard clock clock line. + * \return the dboard clock rate in Hz + */ + virtual double get_tx_dboard_clock_rate(void) = 0; + /*! * Enable/disable the rx dboard clock. * \param enb true to enable diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index 2a3976ba1..e70934b8c 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -17,6 +17,8 @@ #include "usrp_e_iface.hpp" #include "usrp_e_regs.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" #include #include #include @@ -25,11 +27,24 @@ using namespace uhd; using namespace uhd::usrp; +using namespace boost::assign; class usrp_e_dboard_iface : public dboard_iface{ public: - usrp_e_dboard_iface(usrp_e_iface::sptr iface); - ~usrp_e_dboard_iface(void); + + usrp_e_dboard_iface( + usrp_e_iface::sptr iface, + clock_ctrl::sptr clock, + codec_ctrl::sptr codec + ){ + _iface = iface; + _clock = clock; + _codec = codec; + } + + ~usrp_e_dboard_iface(void){ + /* NOP */ + } void write_aux_dac(unit_t, int, float); float read_aux_adc(unit_t, int); @@ -60,35 +75,37 @@ public: private: usrp_e_iface::sptr _iface; + clock_ctrl::sptr _clock; + codec_ctrl::sptr _codec; }; /*********************************************************************** * Make Function **********************************************************************/ -dboard_iface::sptr make_usrp_e_dboard_iface(usrp_e_iface::sptr iface){ - return dboard_iface::sptr(new usrp_e_dboard_iface(iface)); -} - -/*********************************************************************** - * Structors - **********************************************************************/ -usrp_e_dboard_iface::usrp_e_dboard_iface(usrp_e_iface::sptr iface){ - _iface = iface; -} - -usrp_e_dboard_iface::~usrp_e_dboard_iface(void){ - /* NOP */ +dboard_iface::sptr make_usrp_e_dboard_iface( + usrp_e_iface::sptr iface, + clock_ctrl::sptr clock, + codec_ctrl::sptr codec +){ + return dboard_iface::sptr(new usrp_e_dboard_iface(iface, clock, codec)); } /*********************************************************************** * Clock Rates **********************************************************************/ -double usrp_e_dboard_iface::get_clock_rate(unit_t){ - throw std::runtime_error("not implemented"); +double usrp_e_dboard_iface::get_clock_rate(unit_t unit){ + switch(unit){ + case UNIT_RX: return _clock->get_rx_dboard_clock_rate(); + case UNIT_TX: return _clock->get_tx_dboard_clock_rate(); + } + UHD_ASSERT_THROW(false); } -void usrp_e_dboard_iface::set_clock_enabled(unit_t, bool){ - throw std::runtime_error("not implemented"); +void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ + switch(unit){ + case UNIT_RX: return _clock->enable_rx_dboard_clock(enb); + case UNIT_TX: return _clock->enable_tx_dboard_clock(enb); + } } /*********************************************************************** @@ -96,7 +113,7 @@ void usrp_e_dboard_iface::set_clock_enabled(unit_t, bool){ **********************************************************************/ void usrp_e_dboard_iface::set_gpio_ddr(unit_t bank, boost::uint16_t value){ //define mapping of gpio bank to register address - static const uhd::dict bank_to_addr = boost::assign::map_list_of + static const uhd::dict bank_to_addr = map_list_of (UNIT_RX, UE_REG_GPIO_RX_DDR) (UNIT_TX, UE_REG_GPIO_TX_DDR) ; @@ -105,7 +122,7 @@ void usrp_e_dboard_iface::set_gpio_ddr(unit_t bank, boost::uint16_t value){ boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t bank){ //define mapping of gpio bank to register address - static const uhd::dict bank_to_addr = boost::assign::map_list_of + static const uhd::dict bank_to_addr = map_list_of (UNIT_RX, UE_REG_GPIO_RX_IO) (UNIT_TX, UE_REG_GPIO_TX_IO) ; @@ -116,14 +133,14 @@ void usrp_e_dboard_iface::set_atr_reg(unit_t bank, atr_reg_t atr, boost::uint16_ //define mapping of bank to atr regs to register address static const uhd::dict< unit_t, uhd::dict - > bank_to_atr_to_addr = boost::assign::map_list_of - (UNIT_RX, boost::assign::map_list_of + > bank_to_atr_to_addr = map_list_of + (UNIT_RX, 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) ) - (UNIT_TX, boost::assign::map_list_of + (UNIT_TX, 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) @@ -181,10 +198,27 @@ byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_byte /*********************************************************************** * Aux DAX/ADC **********************************************************************/ -void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t unit, int which, float value){ - throw std::runtime_error("not implemented"); +void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t, int which, float value){ + //same aux dacs for each unit + static const uhd::dict which_to_aux_dac = map_list_of + (0, codec_ctrl::AUX_DAC_A) (1, codec_ctrl::AUX_DAC_B) + (2, codec_ctrl::AUX_DAC_C) (3, codec_ctrl::AUX_DAC_D) + ; + _codec->write_aux_dac(which_to_aux_dac[which], value); } float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, int which){ - throw std::runtime_error("not implemented"); + static const uhd::dict< + unit_t, uhd::dict + > unit_to_which_to_aux_adc = map_list_of + (UNIT_RX, map_list_of + (0, codec_ctrl::AUX_ADC_A1) + (1, codec_ctrl::AUX_ADC_B1) + ) + (UNIT_TX, map_list_of + (0, codec_ctrl::AUX_ADC_A2) + (1, codec_ctrl::AUX_ADC_B2) + ) + ; + return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]); } diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 00b5d77d7..31f792306 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -17,6 +17,7 @@ #include #include "usrp_e_impl.hpp" +#include using namespace uhd::usrp; @@ -27,9 +28,12 @@ void usrp_e_impl::dboard_init(void){ _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); + std::cout << _rx_db_eeprom.id.to_pp_string() << std::endl; + std::cout << _tx_db_eeprom.id.to_pp_string() << std::endl; + //create a new dboard interface and manager dboard_iface::sptr dboard_iface( - make_usrp_e_dboard_iface(_iface) + make_usrp_e_dboard_iface(_iface, _clock_ctrl, _codec_ctrl) ); _dboard_manager = dboard_manager::make( _rx_db_eeprom.id, _tx_db_eeprom.id, dboard_iface diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index b6fed6a74..5861be102 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -83,8 +83,6 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ )); } - sleep(1); //FIXME sleep here until the kernel driver stops hanging - //setup various interfaces into hardware _iface = usrp_e_iface::make(_node_fd); _clock_ctrl = clock_ctrl::make(_iface); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 6746e012a..bde0f87c3 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -29,9 +29,15 @@ /*! * Make a usrp-e dboard interface. * \param iface the usrp-e interface object + * \param clock the clock control interface + * \param codec the codec control interface * \return a sptr to a new dboard interface */ -uhd::usrp::dboard_iface::sptr make_usrp_e_dboard_iface(usrp_e_iface::sptr iface); +uhd::usrp::dboard_iface::sptr make_usrp_e_dboard_iface( + usrp_e_iface::sptr iface, + clock_ctrl::sptr clock, + codec_ctrl::sptr codec +); /*! * Simple wax obj proxy class: -- cgit v1.2.3 From 29809e9697b052fa1d0cd2109c8bd5f9af178cfa Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 8 May 2010 01:58:10 +0000 Subject: moved open/close into iface, work on codec tx --- host/lib/usrp/usrp_e/codec_ctrl.cpp | 35 ++++++++++++++++++++++++++++++++--- host/lib/usrp/usrp_e/usrp_e_iface.cpp | 17 ++++++++++++----- host/lib/usrp/usrp_e/usrp_e_iface.hpp | 4 ++-- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 13 ++----------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 1 - 5 files changed, 48 insertions(+), 22 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index a430f2c6f..3f3523ddf 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -29,6 +29,8 @@ using namespace uhd; +static const bool codec_debug = true; + /*********************************************************************** * Codec Control Implementation **********************************************************************/ @@ -56,6 +58,9 @@ private: codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ _iface = iface; + //FIXME temp poke !!! + _iface->poke16(UE_REG_MISC_TEST, 0x0f00); + //soft reset _ad9862_regs.soft_reset = 1; this->send_reg(0); @@ -65,6 +70,28 @@ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ _ad9862_regs.lsb_first = ad9862_regs_t::LSB_FIRST_MSB; _ad9862_regs.soft_reset = 0; + //setup rx side of codec + _ad9862_regs.byp_buffer_a = 1; + _ad9862_regs.byp_buffer_b = 1; + _ad9862_regs.buffer_a_pd = 1; + _ad9862_regs.buffer_b_pd = 1; + _ad9862_regs.rx_pga_a = 0x1f; //TODO bring under api control + _ad9862_regs.rx_pga_b = 0x1f; //TODO bring under api control + _ad9862_regs.rx_twos_comp = 1; + _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS; + + //setup tx side of codec + _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH; + _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_SINGLE; //FIXME should be interleaved + _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control + _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; + _ad9862_regs.interp = ad9862_regs_t::INTERP_4; + _ad9862_regs.tx_twos_comp = 1; + _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_BYPASS; + _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; + _ad9862_regs.dac_a_coarse_gain = 0x3; + _ad9862_regs.dac_b_coarse_gain = 0x3; + //write the register settings to the codec for (uint8_t addr = 0; addr <= 50; addr++){ this->send_reg(addr); @@ -72,6 +99,8 @@ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ } codec_ctrl_impl::~codec_ctrl_impl(void){ + return; //FIXME remove this later + //set aux dacs to zero this->write_aux_dac(AUX_DAC_A, 0); this->write_aux_dac(AUX_DAC_B, 0); @@ -181,7 +210,7 @@ void codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ **********************************************************************/ void codec_ctrl_impl::send_reg(boost::uint8_t addr){ boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); - //std::cout << "codec control write reg: " << std::hex << reg << std::endl; + if (codec_debug) std::cout << "codec control write reg: " << std::hex << reg << std::endl; _iface->transact_spi( UE_SPI_SS_AD9862, spi_config_t::EDGE_RISE, @@ -191,13 +220,13 @@ void codec_ctrl_impl::send_reg(boost::uint8_t addr){ void codec_ctrl_impl::recv_reg(boost::uint8_t addr){ boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); - //std::cout << "codec control read reg: " << std::hex << reg << std::endl; + if (codec_debug) std::cout << "codec control read reg: " << std::hex << reg << std::endl; boost::uint32_t ret = _iface->transact_spi( UE_SPI_SS_AD9862, spi_config_t::EDGE_RISE, reg, 16, true /*rb*/ ); - //std::cout << "codec control read ret: " << std::hex << ret << std::endl; + if (codec_debug) std::cout << "codec control read ret: " << std::hex << ret << std::endl; _ad9862_regs.set_reg(addr, boost::uint16_t(ret)); } diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp index 1dbe383fa..98d8ef478 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.cpp @@ -18,6 +18,7 @@ #include "usrp_e_iface.hpp" #include #include //ioctl +#include //open, close #include //ioctl structures and constants #include #include //mutex @@ -31,12 +32,18 @@ public: /******************************************************************* * Structors ******************************************************************/ - usrp_e_iface_impl(int node_fd){ - _node_fd = node_fd; + usrp_e_iface_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 + )); + } } ~usrp_e_iface_impl(void){ - /* NOP */ + //close the device node file descriptor + ::close(_node_fd); } /******************************************************************* @@ -178,6 +185,6 @@ private: /*********************************************************************** * Public Make Function **********************************************************************/ -usrp_e_iface::sptr usrp_e_iface::make(int node_fd){ - return sptr(new usrp_e_iface_impl(node_fd)); +usrp_e_iface::sptr usrp_e_iface::make(const std::string &node){ + return sptr(new usrp_e_iface_impl(node)); } diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.hpp b/host/lib/usrp/usrp_e/usrp_e_iface.hpp index 016d7448f..6363a24b2 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.hpp @@ -44,10 +44,10 @@ public: /*! * Make a new usrp-e interface with the control transport. - * \param node_fd the file descriptor for the kernel module node + * \param node the device node name * \return a new usrp-e interface object */ - static sptr make(int node_fd); + static sptr make(const std::string &node); /*! * Perform an ioctl call on the device node file descriptor. diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 5861be102..4f7361eca 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -22,7 +22,6 @@ #include #include #include -#include //open using namespace uhd; using namespace uhd::usrp; @@ -76,15 +75,8 @@ device::sptr usrp_e::make(const device_addr_t &device_addr){ usrp_e_impl::usrp_e_impl(const std::string &node){ std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; - //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 - )); - } - //setup various interfaces into hardware - _iface = usrp_e_iface::make(_node_fd); + _iface = usrp_e_iface::make(node); _clock_ctrl = clock_ctrl::make(_iface); _codec_ctrl = codec_ctrl::make(_iface); @@ -100,8 +92,7 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ } usrp_e_impl::~usrp_e_impl(void){ - //close the device node file descriptor - ::close(_node_fd); + /* NOP */ } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index bde0f87c3..59f80c70c 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -95,7 +95,6 @@ public: private: static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); usrp_e_iface::sptr _iface; - int _node_fd; uhd::clock_config_t _clock_config; -- cgit v1.2.3 From 3a26c45c69ea61bb1e2cc4dbfb7a605abbd7ca4b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 10 May 2010 19:00:56 +0000 Subject: ad9862 transmit working --- host/lib/ic_reg_maps/gen_ad9862_regs.py | 2 +- host/lib/usrp/usrp_e/codec_ctrl.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/ic_reg_maps/gen_ad9862_regs.py b/host/lib/ic_reg_maps/gen_ad9862_regs.py index 4444c6240..00340224c 100755 --- a/host/lib/ic_reg_maps/gen_ad9862_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9862_regs.py @@ -123,7 +123,7 @@ ftw_23_16 23[0:7] 0 ######################################################################## ## DLL ######################################################################## -input_clk_ctrl 24[6] 0 external, internal +input_clk_ctrl 24[6] 0 internal, external adc_div2 24[5] 0 normal, div2 dll_mult 24[3:4] 0 1, 2, 4 dll_pd 24[2] 0 diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index 3f3523ddf..ce05ac9eb 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -82,7 +82,7 @@ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ //setup tx side of codec _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH; - _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_SINGLE; //FIXME should be interleaved + _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; _ad9862_regs.interp = ad9862_regs_t::INTERP_4; @@ -92,10 +92,19 @@ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ _ad9862_regs.dac_a_coarse_gain = 0x3; _ad9862_regs.dac_b_coarse_gain = 0x3; + //setup the dll + _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL; + _ad9862_regs.dll_mult = ad9862_regs_t::DLL_MULT_2; + _ad9862_regs.dll_mode = ad9862_regs_t::DLL_MODE_FAST; + //write the register settings to the codec - for (uint8_t addr = 0; addr <= 50; addr++){ + for (uint8_t addr = 0; addr <= 25; addr++){ this->send_reg(addr); } + + //aux adc clock + _ad9862_regs.clk_4 = ad9862_regs_t::CLK_4_1_4; + this->send_reg(34); } codec_ctrl_impl::~codec_ctrl_impl(void){ -- cgit v1.2.3 From 66deed6015f2a2bc67f17f6630ca62a41b596090 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 1 Jun 2010 18:50:15 -0700 Subject: added sr registers to u1e --- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 78 +++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index 51a47f061..67c174208 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -17,6 +17,7 @@ // Slave pointers #define UE_REG_SLAVE(n) ((n)<<7) +#define UE_REG_SR_ADDR(n) ((UE_REG_SLAVE(5)) + (4*(n))) ///////////////////////////////////////////////////// // Slave 0 -- Misc Regs @@ -102,8 +103,8 @@ #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_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 @@ -111,5 +112,78 @@ #define UE_REG_ATR_FULL_RXSIDE UE_REG_ATR_BASE + 12 #define UE_REG_ATR_FULL_TXSIDE UE_REG_ATR_BASE + 14 +///////////////////////////////////////////////// +// DSP RX Regs +//////////////////////////////////////////////// +#define UE_REG_DSP_RX_FREQ UE_REG_SR_ADDR(0) +#define UE_REG_DSP_RX_SCALE_IQ UE_REG_SR_ADDR(1) // {scale_i,scale_q} +#define UE_REG_DSP_RX_DECIM_RATE UE_REG_SR_ADDR(2) // hb and decim rate +#define UE_REG_DSP_RX_DCOFFSET_I UE_REG_SR_ADDR(3) // Bit 31 high sets fixed offset mode, using lower 14 bits, // otherwise it is automatic +#define UE_REG_DSP_RX_DCOFFSET_Q UE_REG_SR_ADDR(4) // Bit 31 high sets fixed offset mode, using lower 14 bits +#define UE_REG_DSP_RX_MUX UE_REG_SR_ADDR(5) + +/////////////////////////////////////////////////// +// VITA RX CTRL regs +/////////////////////////////////////////////////// +// The following 3 are logically a single command register. +// They are clocked into the underlying fifo when time_ticks is written. +#define UE_REG_CTRL_RX_STREAM_CMD UE_REG_SR_ADDR(8) // {now, chain, num_samples(30) +#define UE_REG_CTRL_RX_TIME_SECS UE_REG_SR_ADDR(9) +#define UE_REG_CTRL_RX_TIME_TICKS UE_REG_SR_ADDR(10) +#define UE_REG_CTRL_RX_CLEAR_OVERRUN UE_REG_SR_ADDR(11) // write anything to clear overrun +#define UE_REG_CTRL_RX_VRT_HEADER UE_REG_SR_ADDR(12) // word 0 of packet. FPGA fills in packet counter +#define UE_REG_CTRL_RX_VRT_STREAM_ID UE_REG_SR_ADDR(13) // word 1 of packet. +#define UE_REG_CTRL_RX_VRT_TRAILER UE_REG_SR_ADDR(14) +#define UE_REG_CTRL_RX_NSAMPS_PER_PKT UE_REG_SR_ADDR(15) +#define UE_REG_CTRL_RX_NCHANNELS UE_REG_SR_ADDR(16) // 1 in basic case, up to 4 for vector sources + +///////////////////////////////////////////////// +// DSP TX Regs +//////////////////////////////////////////////// +#define UE_REG_DSP_TX_FREQ UE_REG_SR_ADDR(17) +#define UE_REG_DSP_TX_SCALE_IQ UE_REG_SR_ADDR(18) // {scale_i,scale_q} +#define UE_REG_DSP_TX_INTERP_RATE UE_REG_SR_ADDR(19) +#define UE_REG_DSP_TX_UNUSED UE_REG_SR_ADDR(20) +#define UE_REG_DSP_TX_MUX UE_REG_SR_ADDR(21) + +///////////////////////////////////////////////// +// VITA TX CTRL regs +//////////////////////////////////////////////// +#define UE_REG_CTRL_TX_NCHANNELS UE_REG_SR_ADDR(24) +#define UE_REG_CTRL_TX_CLEAR_UNDERRUN UE_REG_SR_ADDR(25) + +///////////////////////////////////////////////// +// VITA49 64 bit time (write only) +//////////////////////////////////////////////// + /*! + * \brief Time 64 flags + * + *
+   *
+   *    3                   2                   1
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-----------------------------------------------------------+-+-+
+   * |                                                           |S|P|
+   * +-----------------------------------------------------------+-+-+
+   *
+   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
+   * S - Source (0=sma, 1=mimo, 0=default)
+   *
+   * 
+ */ +#define UE_REG_TIME64_SECS UE_REG_SR_ADDR(28) // value to set absolute secs to on next PPS +#define UE_REG_TIME64_TICKS UE_REG_SR_ADDR(29) // value to set absolute ticks to on next PPS +#define UE_REG_TIME64_FLAGS UE_REG_SR_ADDR(30) // flags - see chart above +#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0) + +//pps flags (see above) +#define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0) +#define UE_FLAG_TIME64_PPS_POSEDGE (1 << 0) +#define UE_FLAG_TIME64_PPS_SMA (0 << 1) +#define UE_FLAG_TIME64_PPS_MIMO (1 << 1) + +#define UE_FLAG_TIME64_LATCH_NOW 1 +#define UE_FLAG_TIME64_LATCH_NEXT_PPS 0 + #endif -- cgit v1.2.3 From f1529463174883f6c830acbfd52cd52ed4755971 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 3 Jun 2010 17:09:06 +0000 Subject: added headers to cmakelists for completeness --- host/lib/usrp/usrp_e/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index c25b2cba4..6035d4ff2 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -42,14 +42,19 @@ IF(HAVE_USRP_E_REQUIRED_HEADERS) MESSAGE(STATUS " Building usrp-e support.") LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/clock_ctrl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/clock_ctrl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_ctrl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_ctrl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dsp_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/fpga-downloader.cc ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/mboard_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_regs.hpp ) ELSE(HAVE_USRP_E_REQUIRED_HEADERS) MESSAGE(STATUS " Skipping usrp-e support.") -- cgit v1.2.3 From 551426b72672379faa56302eb3d3e19d12c41aec Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 3 Jun 2010 19:30:00 +0000 Subject: work on io impl for usrp-e using read/write --- host/lib/usrp/usrp_e/CMakeLists.txt | 1 + host/lib/usrp/usrp_e/io_impl.cpp | 137 ++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp_e/usrp_e_iface.cpp | 4 + host/lib/usrp/usrp_e/usrp_e_iface.hpp | 6 ++ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 30 +------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 35 ++++----- 6 files changed, 166 insertions(+), 47 deletions(-) create mode 100644 host/lib/usrp/usrp_e/io_impl.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index 6035d4ff2..568fbd132 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -49,6 +49,7 @@ IF(HAVE_USRP_E_REQUIRED_HEADERS) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dsp_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/fpga-downloader.cc + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/io_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/mboard_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.hpp diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp new file mode 100644 index 000000000..5bb40723e --- /dev/null +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -0,0 +1,137 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include "../../transport/vrt_packet_handler.hpp" +#include +#include //read, write +#include //transfer frame struct +#include //offsetof + +using namespace uhd; + +/*********************************************************************** + * Data Transport (phony zero-copy with read/write) + **********************************************************************/ +class data_transport: + public transport::phony_zero_copy_recv_if, + public transport::phony_zero_copy_send_if +{ +public: + data_transport(int fd): + transport::phony_zero_copy_recv_if(2048), //FIXME magic # + transport::phony_zero_copy_send_if(2048), //FIXME magic # + _fd(fd) + { + /* NOP */ + } + + size_t get_num_recv_frames(void) const{ + return 10; //FIXME no idea! + } + + size_t get_num_send_frames(void) const{ + return 10; //FIXME no idea! + } + +private: + int _fd; + size_t send(const boost::asio::const_buffer &buff){ + return write( + _fd, + boost::asio::buffer_cast(buff), + boost::asio::buffer_size(buff) + ); + } + size_t recv(const boost::asio::mutable_buffer &buff){ + return read( + _fd, + boost::asio::buffer_cast(buff), + boost::asio::buffer_size(buff) + ); + } +}; + +/*********************************************************************** + * IO Implementation Details + **********************************************************************/ +struct usrp_e_impl::io_impl{ + vrt_packet_handler::recv_state recv_state; + vrt_packet_handler::send_state send_state; + data_transport transport; + io_impl(int fd): transport(fd){} +}; + +void usrp_e_impl::io_init(void){ + _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface->get_file_descriptor())); +} + +/*********************************************************************** + * Data Send + **********************************************************************/ +size_t usrp_e_impl::send( + const boost::asio::const_buffer &buff, + const uhd::tx_metadata_t &metadata, + const io_type_t & io_type, + send_mode_t send_mode +){ + otw_type_t send_otw_type; + send_otw_type.width = 16; + send_otw_type.shift = 0; + send_otw_type.byteorder = otw_type_t::BO_NATIVE; + + return vrt_packet_handler::send( + _io_impl->send_state, + buff, + metadata, + send_mode, + io_type, + send_otw_type, //TODO + 64e6, //TODO + boost::bind(&data_transport::get_send_buff, &_io_impl->transport), + _max_num_samples, //TODO + offsetof(usrp_transfer_frame, buf) + //TODO probably need callback to fill in frame size + ); +} + +/*********************************************************************** + * Data Recv + **********************************************************************/ +size_t usrp_e_impl::recv( + const boost::asio::mutable_buffer &buff, + uhd::rx_metadata_t &metadata, + const io_type_t &io_type, + recv_mode_t recv_mode +){ + otw_type_t recv_otw_type; + recv_otw_type.width = 16; + recv_otw_type.shift = 0; + recv_otw_type.byteorder = otw_type_t::BO_NATIVE; + + return vrt_packet_handler::recv( + _io_impl->recv_state, + buff, + metadata, + recv_mode, + io_type, + recv_otw_type, //TODO + 64e6, //TODO + boost::bind(&data_transport::get_recv_buff, &_io_impl->transport), + offsetof(usrp_transfer_frame, buf) + ); +} diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp index 98d8ef478..21e91452f 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.cpp @@ -29,6 +29,10 @@ using namespace uhd; class usrp_e_iface_impl : public usrp_e_iface{ public: + int get_file_descriptor(void){ + return _node_fd; + } + /******************************************************************* * Structors ******************************************************************/ diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.hpp b/host/lib/usrp/usrp_e/usrp_e_iface.hpp index 6363a24b2..59aac43d9 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.hpp @@ -49,6 +49,12 @@ public: */ static sptr make(const std::string &node); + /*! + * Get the underlying file descriptor. + * \return the file descriptor + */ + virtual int get_file_descriptor(void) = 0; + /*! * Perform an ioctl call on the device node file descriptor. * This will throw when the internal ioctl call fails. diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 4a398e21c..f9af36887 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -89,6 +89,9 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ //initialize the dsps rx_ddc_init(); tx_duc_init(); + + //init the io send/recv + io_init(); } usrp_e_impl::~usrp_e_impl(void){ @@ -127,30 +130,3 @@ void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ void usrp_e_impl::set(const wax::obj &, const wax::obj &){ UHD_THROW_PROP_SET_ERROR(); } - -/*********************************************************************** - * Device IO (TODO) - **********************************************************************/ -size_t usrp_e_impl::send( - const boost::asio::const_buffer &, - const uhd::tx_metadata_t &, - const io_type_t &, - send_mode_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 &, - recv_mode_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 index a2cdbc31e..12d4c9d9e 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -18,6 +18,7 @@ #include "usrp_e_iface.hpp" #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" +#include #include #include #include @@ -55,26 +56,11 @@ public: 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); - } + 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);} }; /*! @@ -95,10 +81,19 @@ public: size_t get_max_recv_samps_per_packet(void) const{return _max_num_samples;} private: - static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); + //interface to ioctls and file descriptor usrp_e_iface::sptr _iface; + //FIXME fetch from ioctl? + static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); + + //handle io stuff + UHD_PIMPL_DECL(io_impl) _io_impl; + void io_init(void); + + //configuration shadows uhd::clock_config_t _clock_config; + //TODO otw type recv/send //ad9522 clock control clock_ctrl::sptr _clock_ctrl; -- cgit v1.2.3 From fcdbea4f089db2405820ad598979e639cf131ff5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 4 Jun 2010 01:58:12 +0000 Subject: io impl tweaks, renamed clock control and codec control implementation to avoid collision with usrp2 (those need to be renamed as well) --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 18 +++++++++--------- host/lib/usrp/usrp_e/codec_ctrl.cpp | 20 ++++++++++---------- host/lib/usrp/usrp_e/dsp_impl.cpp | 24 ++++++++++++++++++++++++ host/lib/usrp/usrp_e/io_impl.cpp | 16 ++++++++++++---- 4 files changed, 55 insertions(+), 23 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 5f7269412..7947930a0 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -29,11 +29,11 @@ using namespace uhd; /*********************************************************************** * Clock Control Implementation **********************************************************************/ -class clock_ctrl_impl : public clock_ctrl{ +class usrp_e_clock_ctrl_impl : public clock_ctrl{ public: //structors - clock_ctrl_impl(usrp_e_iface::sptr iface); - ~clock_ctrl_impl(void); + usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface); + ~usrp_e_clock_ctrl_impl(void); void enable_rx_dboard_clock(bool enb); void enable_tx_dboard_clock(bool enb); @@ -56,7 +56,7 @@ private: /*********************************************************************** * Clock Control Methods **********************************************************************/ -clock_ctrl_impl::clock_ctrl_impl(usrp_e_iface::sptr iface){ +usrp_e_clock_ctrl_impl::usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ _iface = iface; //init the clock gen registers @@ -126,12 +126,12 @@ clock_ctrl_impl::clock_ctrl_impl(usrp_e_iface::sptr iface){ this->enable_tx_dboard_clock(false); } -clock_ctrl_impl::~clock_ctrl_impl(void){ +usrp_e_clock_ctrl_impl::~usrp_e_clock_ctrl_impl(void){ this->enable_rx_dboard_clock(false); this->enable_tx_dboard_clock(false); } -void clock_ctrl_impl::enable_rx_dboard_clock(bool enb){ +void usrp_e_clock_ctrl_impl::enable_rx_dboard_clock(bool enb){ _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_CMOS; _ad9522_regs.out9_cmos_configuration = (enb)? ad9522_regs_t::OUT9_CMOS_CONFIGURATION_B_ON : @@ -144,7 +144,7 @@ void clock_ctrl_impl::enable_rx_dboard_clock(bool enb){ this->latch_regs(); } -void clock_ctrl_impl::enable_tx_dboard_clock(bool enb){ +void usrp_e_clock_ctrl_impl::enable_tx_dboard_clock(bool enb){ _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_CMOS; _ad9522_regs.out6_cmos_configuration = (enb)? ad9522_regs_t::OUT6_CMOS_CONFIGURATION_B_ON : @@ -157,7 +157,7 @@ void clock_ctrl_impl::enable_tx_dboard_clock(bool enb){ this->latch_regs(); } -void clock_ctrl_impl::send_reg(boost::uint16_t addr){ +void usrp_e_clock_ctrl_impl::send_reg(boost::uint16_t addr){ boost::uint32_t reg = _ad9522_regs.get_write_reg(addr); //std::cout << "clock control write reg: " << std::hex << reg << std::endl; _iface->transact_spi( @@ -171,5 +171,5 @@ void clock_ctrl_impl::send_reg(boost::uint16_t addr){ * Clock Control Make **********************************************************************/ clock_ctrl::sptr clock_ctrl::make(usrp_e_iface::sptr iface){ - return sptr(new clock_ctrl_impl(iface)); + return sptr(new usrp_e_clock_ctrl_impl(iface)); } diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index ce05ac9eb..e86fde346 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -34,11 +34,11 @@ static const bool codec_debug = true; /*********************************************************************** * Codec Control Implementation **********************************************************************/ -class codec_ctrl_impl : public codec_ctrl{ +class usrp_e_codec_ctrl_impl : public codec_ctrl{ public: //structors - codec_ctrl_impl(usrp_e_iface::sptr iface); - ~codec_ctrl_impl(void); + usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface); + ~usrp_e_codec_ctrl_impl(void); //aux adc and dac control float read_aux_adc(aux_adc_t which); @@ -55,7 +55,7 @@ private: /*********************************************************************** * Codec Control Structors **********************************************************************/ -codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ +usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ _iface = iface; //FIXME temp poke !!! @@ -107,7 +107,7 @@ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){ this->send_reg(34); } -codec_ctrl_impl::~codec_ctrl_impl(void){ +usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ return; //FIXME remove this later //set aux dacs to zero @@ -131,7 +131,7 @@ static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){ return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; } -float codec_ctrl_impl::read_aux_adc(aux_adc_t which){ +float usrp_e_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ //check to see if the switch needs to be set bool write_switch = false; switch(which){ @@ -184,7 +184,7 @@ float codec_ctrl_impl::read_aux_adc(aux_adc_t which){ /*********************************************************************** * Codec Control AUX DAC Methods **********************************************************************/ -void codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ +void usrp_e_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ //special case for aux dac d (aka sigma delta word) if (which == AUX_DAC_D){ boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff); @@ -217,7 +217,7 @@ void codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ /*********************************************************************** * Codec Control SPI Methods **********************************************************************/ -void codec_ctrl_impl::send_reg(boost::uint8_t addr){ +void usrp_e_codec_ctrl_impl::send_reg(boost::uint8_t addr){ boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); if (codec_debug) std::cout << "codec control write reg: " << std::hex << reg << std::endl; _iface->transact_spi( @@ -227,7 +227,7 @@ void codec_ctrl_impl::send_reg(boost::uint8_t addr){ ); } -void codec_ctrl_impl::recv_reg(boost::uint8_t addr){ +void usrp_e_codec_ctrl_impl::recv_reg(boost::uint8_t addr){ boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); if (codec_debug) std::cout << "codec control read reg: " << std::hex << reg << std::endl; boost::uint32_t ret = _iface->transact_spi( @@ -243,5 +243,5 @@ void codec_ctrl_impl::recv_reg(boost::uint8_t addr){ * Codec Control Make **********************************************************************/ codec_ctrl::sptr codec_ctrl::make(usrp_e_iface::sptr iface){ - return sptr(new codec_ctrl_impl(iface)); + return sptr(new usrp_e_codec_ctrl_impl(iface)); } diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index 272ac71b3..e61f529ab 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -20,6 +20,30 @@ using namespace uhd::usrp; +/*********************************************************************** + * Helper Functions + **********************************************************************/ +// Check if requested decim/interp rate is: +// multiple of 4, enable two halfband filters +// multiple of 2, enable one halfband filter +// handle remainder in CIC +static boost::uint32_t calculate_cic_word(size_t rate){ + int hb0 = 0, hb1 = 0; + if (not (rate & 0x1)){ + hb0 = 1; + rate /= 2; + } + if (not (rate & 0x1)){ + hb1 = 1; + rate /= 2; + } + return (hb1 << 9) | (hb0 << 8) | (rate & 0xff); +} + +static boost::uint32_t calculate_iq_scale_word(boost::int16_t i, boost::int16_t q){ + return (boost::uint16_t(i) << 16) | (boost::uint16_t(q) << 0); +} + /*********************************************************************** * RX DDC Initialization **********************************************************************/ diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 5bb40723e..f83829cb8 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -24,6 +24,8 @@ using namespace uhd; +static const size_t MAX_BUFF_SIZE = 2048; + /*********************************************************************** * Data Transport (phony zero-copy with read/write) **********************************************************************/ @@ -33,8 +35,8 @@ class data_transport: { public: data_transport(int fd): - transport::phony_zero_copy_recv_if(2048), //FIXME magic # - transport::phony_zero_copy_send_if(2048), //FIXME magic # + transport::phony_zero_copy_recv_if(MAX_BUFF_SIZE), + transport::phony_zero_copy_send_if(MAX_BUFF_SIZE), _fd(fd) { /* NOP */ @@ -51,6 +53,13 @@ public: private: int _fd; size_t send(const boost::asio::const_buffer &buff){ + //Set the frame length in the frame header. + //This is technically bad to write to a const buffer, + //but this will go away when the ring gets implemented, + //and the send buffer commit method will set the length. + const_cast( + boost::asio::buffer_cast(buff) + )->len = boost::asio::buffer_size(buff); return write( _fd, boost::asio::buffer_cast(buff), @@ -103,9 +112,8 @@ size_t usrp_e_impl::send( send_otw_type, //TODO 64e6, //TODO boost::bind(&data_transport::get_send_buff, &_io_impl->transport), - _max_num_samples, //TODO + (MAX_BUFF_SIZE - sizeof(usrp_transfer_frame))/send_otw_type.get_sample_size(), offsetof(usrp_transfer_frame, buf) - //TODO probably need callback to fill in frame size ); } -- cgit v1.2.3 From 685cf432a373ee7556db507f7958f51e6ccf581a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 4 Jun 2010 21:13:27 +0000 Subject: prefixed helper classes with usrp_e to avoid collision --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 4 ++-- host/lib/usrp/usrp_e/clock_ctrl.hpp | 4 ++-- host/lib/usrp/usrp_e/codec_ctrl.cpp | 4 ++-- host/lib/usrp/usrp_e/codec_ctrl.hpp | 4 ++-- host/lib/usrp/usrp_e/dboard_iface.cpp | 28 ++++++++++++++-------------- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 4 ++-- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 8 ++++---- 7 files changed, 28 insertions(+), 28 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 7947930a0..e37b17a54 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -29,7 +29,7 @@ using namespace uhd; /*********************************************************************** * Clock Control Implementation **********************************************************************/ -class usrp_e_clock_ctrl_impl : public clock_ctrl{ +class usrp_e_clock_ctrl_impl : public usrp_e_clock_ctrl{ public: //structors usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface); @@ -170,6 +170,6 @@ void usrp_e_clock_ctrl_impl::send_reg(boost::uint16_t addr){ /*********************************************************************** * Clock Control Make **********************************************************************/ -clock_ctrl::sptr clock_ctrl::make(usrp_e_iface::sptr iface){ +usrp_e_clock_ctrl::sptr usrp_e_clock_ctrl::make(usrp_e_iface::sptr iface){ return sptr(new usrp_e_clock_ctrl_impl(iface)); } diff --git a/host/lib/usrp/usrp_e/clock_ctrl.hpp b/host/lib/usrp/usrp_e/clock_ctrl.hpp index 994b83564..692b9eb0e 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.hpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.hpp @@ -27,9 +27,9 @@ * - Setup system clocks. * - Disable/enable clock lines. */ -class clock_ctrl : boost::noncopyable{ +class usrp_e_clock_ctrl : boost::noncopyable{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; /*! * Make a new clock control object. diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index e86fde346..b19606020 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -34,7 +34,7 @@ static const bool codec_debug = true; /*********************************************************************** * Codec Control Implementation **********************************************************************/ -class usrp_e_codec_ctrl_impl : public codec_ctrl{ +class usrp_e_codec_ctrl_impl : public usrp_e_codec_ctrl{ public: //structors usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface); @@ -242,6 +242,6 @@ void usrp_e_codec_ctrl_impl::recv_reg(boost::uint8_t addr){ /*********************************************************************** * Codec Control Make **********************************************************************/ -codec_ctrl::sptr codec_ctrl::make(usrp_e_iface::sptr iface){ +usrp_e_codec_ctrl::sptr usrp_e_codec_ctrl::make(usrp_e_iface::sptr iface){ return sptr(new usrp_e_codec_ctrl_impl(iface)); } diff --git a/host/lib/usrp/usrp_e/codec_ctrl.hpp b/host/lib/usrp/usrp_e/codec_ctrl.hpp index efdcd7142..b9005a82d 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.hpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.hpp @@ -27,9 +27,9 @@ * - Init/power down codec. * - Read aux adc, write aux dac. */ -class codec_ctrl : boost::noncopyable{ +class usrp_e_codec_ctrl : boost::noncopyable{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; /*! * Make a new clock control object. diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index 23255b58c..594f2a23e 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -34,8 +34,8 @@ public: usrp_e_dboard_iface( usrp_e_iface::sptr iface, - clock_ctrl::sptr clock, - codec_ctrl::sptr codec + usrp_e_clock_ctrl::sptr clock, + usrp_e_codec_ctrl::sptr codec ){ _iface = iface; _clock = clock; @@ -77,8 +77,8 @@ public: private: usrp_e_iface::sptr _iface; - clock_ctrl::sptr _clock; - codec_ctrl::sptr _codec; + usrp_e_clock_ctrl::sptr _clock; + usrp_e_codec_ctrl::sptr _codec; }; /*********************************************************************** @@ -86,8 +86,8 @@ private: **********************************************************************/ dboard_iface::sptr make_usrp_e_dboard_iface( usrp_e_iface::sptr iface, - clock_ctrl::sptr clock, - codec_ctrl::sptr codec + usrp_e_clock_ctrl::sptr clock, + usrp_e_codec_ctrl::sptr codec ){ return dboard_iface::sptr(new usrp_e_dboard_iface(iface, clock, codec)); } @@ -214,24 +214,24 @@ byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_byte **********************************************************************/ void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t, int which, float value){ //same aux dacs for each unit - static const uhd::dict which_to_aux_dac = map_list_of - (0, codec_ctrl::AUX_DAC_A) (1, codec_ctrl::AUX_DAC_B) - (2, codec_ctrl::AUX_DAC_C) (3, codec_ctrl::AUX_DAC_D) + static const uhd::dict which_to_aux_dac = map_list_of + (0, usrp_e_codec_ctrl::AUX_DAC_A) (1, usrp_e_codec_ctrl::AUX_DAC_B) + (2, usrp_e_codec_ctrl::AUX_DAC_C) (3, usrp_e_codec_ctrl::AUX_DAC_D) ; _codec->write_aux_dac(which_to_aux_dac[which], value); } float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, int which){ static const uhd::dict< - unit_t, uhd::dict + unit_t, uhd::dict > unit_to_which_to_aux_adc = map_list_of (UNIT_RX, map_list_of - (0, codec_ctrl::AUX_ADC_A1) - (1, codec_ctrl::AUX_ADC_B1) + (0, usrp_e_codec_ctrl::AUX_ADC_A1) + (1, usrp_e_codec_ctrl::AUX_ADC_B1) ) (UNIT_TX, map_list_of - (0, codec_ctrl::AUX_ADC_A2) - (1, codec_ctrl::AUX_ADC_B2) + (0, usrp_e_codec_ctrl::AUX_ADC_A2) + (1, usrp_e_codec_ctrl::AUX_ADC_B2) ) ; return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index f9af36887..226825510 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -77,8 +77,8 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ //setup various interfaces into hardware _iface = usrp_e_iface::make(node); - _clock_ctrl = clock_ctrl::make(_iface); - _codec_ctrl = codec_ctrl::make(_iface); + _clock_ctrl = usrp_e_clock_ctrl::make(_iface); + _codec_ctrl = usrp_e_codec_ctrl::make(_iface); //initialize the mboard mboard_init(); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 12d4c9d9e..bdb1a675b 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -36,8 +36,8 @@ */ uhd::usrp::dboard_iface::sptr make_usrp_e_dboard_iface( usrp_e_iface::sptr iface, - clock_ctrl::sptr clock, - codec_ctrl::sptr codec + usrp_e_clock_ctrl::sptr clock, + usrp_e_codec_ctrl::sptr codec ); /*! @@ -96,10 +96,10 @@ private: //TODO otw type recv/send //ad9522 clock control - clock_ctrl::sptr _clock_ctrl; + usrp_e_clock_ctrl::sptr _clock_ctrl; //ad9862 codec control - codec_ctrl::sptr _codec_ctrl; + usrp_e_codec_ctrl::sptr _codec_ctrl; //device functions and settings void get(const wax::obj &, wax::obj &); -- cgit v1.2.3 From a5dca07971587e3b20e57924227c020f13bfd700 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 4 Jun 2010 22:44:06 +0000 Subject: implemented dsp and rx control --- host/lib/usrp/usrp_e/dsp_impl.cpp | 137 ++++++++++++++++++++++++++++++++--- host/lib/usrp/usrp_e/io_impl.cpp | 40 +++++++++- host/lib/usrp/usrp_e/mboard_impl.cpp | 12 ++- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 6 ++ 4 files changed, 182 insertions(+), 13 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index e61f529ab..11d22d15f 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -15,14 +15,34 @@ // along with this program. If not, see . // -#include #include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include +#include +#include +#include + +#define rint boost::math::iround +using namespace uhd; using namespace uhd::usrp; /*********************************************************************** * Helper Functions **********************************************************************/ +static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq, double clock_freq){ + UHD_ASSERT_THROW(std::abs(freq) < clock_freq/2.0); + static const double scale_factor = std::pow(2.0, 32); + + //calculate the freq register word + boost::uint32_t freq_word = rint((freq / clock_freq) * scale_factor); + + //update the actual frequency + freq = (double(freq_word) / scale_factor) * clock_freq; + + return freq_word; +} + // Check if requested decim/interp rate is: // multiple of 4, enable two halfband filters // multiple of 2, enable one halfband filter @@ -57,15 +77,62 @@ void usrp_e_impl::rx_ddc_init(void){ /*********************************************************************** * RX DDC Get **********************************************************************/ -void usrp_e_impl::rx_ddc_get(const wax::obj &, wax::obj &){ - UHD_THROW_PROP_GET_ERROR(); +void usrp_e_impl::rx_ddc_get(const wax::obj &key, wax::obj &val){ + switch(key.as()){ + case DSP_PROP_NAME: + val = std::string("usrp-e ddc0"); + return; + + case DSP_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case DSP_PROP_FREQ_SHIFT: + val = _ddc_freq; + return; + + case DSP_PROP_CODEC_RATE: + val = MASTER_CLOCK_RATE; + return; + + case DSP_PROP_HOST_RATE: + val = MASTER_CLOCK_RATE/_ddc_decim; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } } /*********************************************************************** * RX DDC Set **********************************************************************/ -void usrp_e_impl::rx_ddc_set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); +void usrp_e_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + + case DSP_PROP_FREQ_SHIFT:{ + double new_freq = val.as(); + _iface->poke32(UE_REG_DSP_RX_FREQ, + calculate_freq_word_and_update_actual_freq(new_freq, MASTER_CLOCK_RATE) + ); + _ddc_freq = new_freq; //shadow + } + return; + + case DSP_PROP_HOST_RATE:{ + //set the decimation + _ddc_decim = rint(MASTER_CLOCK_RATE/val.as()); + _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, calculate_cic_word(_ddc_decim)); + + //set the scaling + static const boost::int16_t default_rx_scale_iq = 1024; + _iface->poke32(UE_REG_DSP_RX_SCALE_IQ, + calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) + ); + } + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } /*********************************************************************** @@ -81,13 +148,65 @@ void usrp_e_impl::tx_duc_init(void){ /*********************************************************************** * TX DUC Get **********************************************************************/ -void usrp_e_impl::tx_duc_get(const wax::obj &, wax::obj &){ - UHD_THROW_PROP_GET_ERROR(); +void usrp_e_impl::tx_duc_get(const wax::obj &key, wax::obj &val){ + switch(key.as()){ + case DSP_PROP_NAME: + val = std::string("usrp-e duc0"); + return; + + case DSP_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case DSP_PROP_FREQ_SHIFT: + val = _duc_freq; + return; + + case DSP_PROP_CODEC_RATE: + val = MASTER_CLOCK_RATE; + return; + + case DSP_PROP_HOST_RATE: + val = MASTER_CLOCK_RATE/_duc_interp; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } } /*********************************************************************** * TX DUC Set **********************************************************************/ -void usrp_e_impl::tx_duc_set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); +void usrp_e_impl::tx_duc_set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + + case DSP_PROP_FREQ_SHIFT:{ + double new_freq = val.as(); + _iface->poke32(UE_REG_DSP_TX_FREQ, + calculate_freq_word_and_update_actual_freq(new_freq, MASTER_CLOCK_RATE) + ); + _duc_freq = new_freq; //shadow + } + return; + + case DSP_PROP_HOST_RATE:{ + _duc_interp = rint(MASTER_CLOCK_RATE/val.as()); + + // Calculate CIC interpolation (i.e., without halfband interpolators) + size_t tmp_interp = calculate_cic_word(_duc_interp) & 0xff; + + // Calculate closest multiplier constant to reverse gain absent scale multipliers + double interp_cubed = std::pow(double(tmp_interp), 3); + boost::int16_t scale = rint((4096*std::pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed)); + + //set the interpolation + _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, calculate_cic_word(_duc_interp)); + + //set the scaling + _iface->poke32(UE_REG_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale)); + } + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index f83829cb8..5914bc613 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -16,6 +16,7 @@ // #include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" #include "../../transport/vrt_packet_handler.hpp" #include #include //read, write @@ -86,9 +87,44 @@ struct usrp_e_impl::io_impl{ }; void usrp_e_impl::io_init(void){ + //setup rx data path + _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, 1000); //FIXME magic number + _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); + _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 1); //reset + _iface->poke32(UE_REG_CTRL_RX_VRT_HEADER, 0 + | (0x1 << 28) //if data with stream id + | (0x1 << 26) //has trailer + | (0x3 << 22) //integer time other + | (0x1 << 20) //fractional time sample count + ); + _iface->poke32(UE_REG_CTRL_RX_VRT_STREAM_ID, 0); + _iface->poke32(UE_REG_CTRL_RX_VRT_TRAILER, 0); + _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface->get_file_descriptor())); } +static boost::uint32_t make_stream_cmd(bool now, bool chain, boost::uint32_t nsamps){ + return (((now)? 1 : 0) << 31) | (((chain)? 1 : 0) << 30) | nsamps; +} + +void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ + boost::uint32_t cmd = 0; + switch(stream_cmd.stream_mode){ + case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE: + cmd = make_stream_cmd(stream_cmd.stream_now, false, stream_cmd.num_samps); + break; + + case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE: + cmd = make_stream_cmd(stream_cmd.stream_now, true, stream_cmd.num_samps); + break; + + default: throw std::runtime_error("stream mode not implemented"); + } + _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, cmd); + _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, stream_cmd.time_spec.secs); + _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_ticks(MASTER_CLOCK_RATE)); +} + /*********************************************************************** * Data Send **********************************************************************/ @@ -110,7 +146,7 @@ size_t usrp_e_impl::send( send_mode, io_type, send_otw_type, //TODO - 64e6, //TODO + MASTER_CLOCK_RATE, boost::bind(&data_transport::get_send_buff, &_io_impl->transport), (MAX_BUFF_SIZE - sizeof(usrp_transfer_frame))/send_otw_type.get_sample_size(), offsetof(usrp_transfer_frame, buf) @@ -138,7 +174,7 @@ size_t usrp_e_impl::recv( recv_mode, io_type, recv_otw_type, //TODO - 64e6, //TODO + MASTER_CLOCK_RATE, boost::bind(&data_transport::get_recv_buff, &_io_impl->transport), offsetof(usrp_transfer_frame, buf) ); diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 00ce4b782..efbde38ce 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -108,6 +108,14 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * Mboard Set **********************************************************************/ -void usrp_e_impl::mboard_set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); +void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ + //handle the get request conditioned on the key + switch(key.as()){ + + case MBOARD_PROP_STREAM_CMD: + issue_stream_cmd(val.as()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index bdb1a675b..a9fd856fe 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -22,11 +22,14 @@ #include #include #include +#include #include #ifndef INCLUDED_USRP_E_IMPL_HPP #define INCLUDED_USRP_E_IMPL_HPP +static const double MASTER_CLOCK_RATE = 64e6; + /*! * Make a usrp-e dboard interface. * \param iface the usrp-e interface object @@ -90,6 +93,7 @@ private: //handle io stuff UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); + void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); //configuration shadows uhd::clock_config_t _clock_config; @@ -131,12 +135,14 @@ private: void rx_ddc_init(void); void rx_ddc_get(const wax::obj &, wax::obj &); void rx_ddc_set(const wax::obj &, const wax::obj &); + double _ddc_freq; size_t _ddc_decim; 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 &); + double _duc_freq; size_t _duc_interp; wax_obj_proxy::sptr _tx_duc_proxy; }; -- cgit v1.2.3 From a5cdd7a311edcb3afdc9673bd7f6ec84bf8e7b6c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 5 Jun 2010 00:24:16 +0000 Subject: usrp-e more implementation, rx timed samples runs w/o error (no workie though) --- host/lib/usrp/usrp_e/dboard_impl.cpp | 116 +++++++++++++++++++++++++++++++---- host/lib/usrp/usrp_e/io_impl.cpp | 5 ++ host/lib/usrp/usrp_e/mboard_impl.cpp | 23 ++++--- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 3 + 4 files changed, 128 insertions(+), 19 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 31f792306..22c4ac8b7 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -17,8 +17,11 @@ #include #include "usrp_e_impl.hpp" +#include +#include #include +using namespace uhd; using namespace uhd::usrp; /*********************************************************************** @@ -32,11 +35,11 @@ void usrp_e_impl::dboard_init(void){ std::cout << _tx_db_eeprom.id.to_pp_string() << std::endl; //create a new dboard interface and manager - dboard_iface::sptr dboard_iface( - make_usrp_e_dboard_iface(_iface, _clock_ctrl, _codec_ctrl) + _dboard_iface = make_usrp_e_dboard_iface( + _iface, _clock_ctrl, _codec_ctrl ); _dboard_manager = dboard_manager::make( - _rx_db_eeprom.id, _tx_db_eeprom.id, dboard_iface + _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface ); //setup the dboard proxies @@ -48,32 +51,123 @@ void usrp_e_impl::dboard_init(void){ boost::bind(&usrp_e_impl::tx_dboard_get, this, _1, _2), boost::bind(&usrp_e_impl::tx_dboard_set, this, _1, _2) ); + + //init the subdevs in use (use the first subdevice) + _rx_subdevs_in_use = prop_names_t(1, _dboard_manager->get_rx_subdev_names().at(0)); + //TODO update_rx_mux_config(); + + _tx_subdevs_in_use = prop_names_t(1, _dboard_manager->get_tx_subdev_names().at(0)); + //TODO update_tx_mux_config(); } /*********************************************************************** * RX Dboard Get **********************************************************************/ -void usrp_e_impl::rx_dboard_get(const wax::obj &, wax::obj &){ - UHD_THROW_PROP_GET_ERROR(); +void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case DBOARD_PROP_NAME: + val = std::string("usrp-e dboard (rx unit)"); + return; + + case DBOARD_PROP_SUBDEV: + val = _dboard_manager->get_rx_subdev(name); + return; + + case DBOARD_PROP_SUBDEV_NAMES: + val = _dboard_manager->get_rx_subdev_names(); + return; + + case DBOARD_PROP_USED_SUBDEVS: + val = _rx_subdevs_in_use; + return; + + case DBOARD_PROP_DBOARD_ID: + val = _rx_db_eeprom.id; + return; + + case DBOARD_PROP_DBOARD_IFACE: + val = _dboard_iface; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } } /*********************************************************************** * RX Dboard Set **********************************************************************/ -void usrp_e_impl::rx_dboard_set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); +void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + case DBOARD_PROP_USED_SUBDEVS: + _rx_subdevs_in_use = val.as(); + //TODO update_rx_mux_config(); //if the val is bad, this will throw + return; + + case DBOARD_PROP_DBOARD_ID: + _rx_db_eeprom.id = val.as(); + _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } /*********************************************************************** * TX Dboard Get **********************************************************************/ -void usrp_e_impl::tx_dboard_get(const wax::obj &, wax::obj &){ - UHD_THROW_PROP_GET_ERROR(); +void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case DBOARD_PROP_NAME: + val = std::string("usrp-e dboard (tx unit)"); + return; + + case DBOARD_PROP_SUBDEV: + val = _dboard_manager->get_tx_subdev(name); + return; + + case DBOARD_PROP_SUBDEV_NAMES: + val = _dboard_manager->get_tx_subdev_names(); + return; + + case DBOARD_PROP_USED_SUBDEVS: + val = _tx_subdevs_in_use; + return; + + case DBOARD_PROP_DBOARD_ID: + val = _tx_db_eeprom.id; + return; + + case DBOARD_PROP_DBOARD_IFACE: + val = _dboard_iface; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } } /*********************************************************************** * TX Dboard Set **********************************************************************/ -void usrp_e_impl::tx_dboard_set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); +void usrp_e_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + case DBOARD_PROP_USED_SUBDEVS: + _tx_subdevs_in_use = val.as(); + //TODO update_tx_mux_config(); //if the val is bad, this will throw + return; + + case DBOARD_PROP_DBOARD_ID: + _tx_db_eeprom.id = val.as(); + _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 5914bc613..9ebc5b560 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -22,6 +22,8 @@ #include //read, write #include //transfer frame struct #include //offsetof +#include +#include using namespace uhd; @@ -68,6 +70,9 @@ private: ); } size_t recv(const boost::asio::mutable_buffer &buff){ + std::cout << boost::format( + "calling read on fd %d, buff size is %d" + ) % _fd % boost::asio::buffer_size(buff) << std::endl; return read( _fd, boost::asio::buffer_cast(buff), diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index efbde38ce..e4a0e81af 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -16,6 +16,7 @@ // #include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" #include #include #include @@ -75,26 +76,22 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = prop_names_t(1, ""); //vector of size 1 with empty string return; - case MBOARD_PROP_STREAM_CMD: - //val = TODO - return; - case MBOARD_PROP_RX_DSP: - UHD_ASSERT_THROW(name == "ddc0"); + UHD_ASSERT_THROW(name == ""); val = _rx_ddc_proxy->get_link(); return; case MBOARD_PROP_RX_DSP_NAMES: - val = prop_names_t(1, "ddc0"); + val = prop_names_t(1, ""); return; case MBOARD_PROP_TX_DSP: - UHD_ASSERT_THROW(name == "duc0"); + UHD_ASSERT_THROW(name == ""); val = _tx_duc_proxy->get_link(); return; case MBOARD_PROP_TX_DSP_NAMES: - val = prop_names_t(1, "duc0"); + val = prop_names_t(1, ""); return; case MBOARD_PROP_CLOCK_CONFIG: @@ -116,6 +113,16 @@ void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ issue_stream_cmd(val.as()); return; + case MBOARD_PROP_TIME_NOW: + case MBOARD_PROP_TIME_NEXT_PPS:{ + time_spec_t time_spec = val.as(); + _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_ticks(MASTER_CLOCK_RATE)); + boost::uint32_t imm_flags = (key.as() == MBOARD_PROP_TIME_NOW)? 1 : 0; + _iface->poke32(UE_REG_TIME64_IMM, imm_flags); + _iface->poke32(UE_REG_TIME64_SECS, time_spec.secs); + } + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index a9fd856fe..657d2d225 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -118,17 +118,20 @@ private: //xx dboard functions and settings void dboard_init(void); uhd::usrp::dboard_manager::sptr _dboard_manager; + uhd::usrp::dboard_iface::sptr _dboard_iface; //rx dboard functions and settings uhd::usrp::dboard_eeprom_t _rx_db_eeprom; void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); + uhd::prop_names_t _rx_subdevs_in_use; wax_obj_proxy::sptr _rx_dboard_proxy; //tx dboard functions and settings uhd::usrp::dboard_eeprom_t _tx_db_eeprom; void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); + uhd::prop_names_t _tx_subdevs_in_use; wax_obj_proxy::sptr _tx_dboard_proxy; //rx ddc functions and settings -- cgit v1.2.3 From 7332fc3198a81d9f747ea2a033c1cca168858944 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 5 Jun 2010 01:35:19 +0000 Subject: recv giving me something, bad vrt headers though... --- host/lib/usrp/usrp_e/io_impl.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 9ebc5b560..7c451a75f 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -73,11 +73,14 @@ private: std::cout << boost::format( "calling read on fd %d, buff size is %d" ) % _fd % boost::asio::buffer_size(buff) << std::endl; - return read( + ssize_t ret = read( _fd, boost::asio::buffer_cast(buff), boost::asio::buffer_size(buff) ); + if (ret < ssize_t(sizeof(usrp_transfer_frame))) return 0; + std::cout << "len " << int(boost::asio::buffer_cast(buff)->len) << std::endl; + return boost::asio::buffer_cast(buff)->len; } }; @@ -93,7 +96,7 @@ struct usrp_e_impl::io_impl{ void usrp_e_impl::io_init(void){ //setup rx data path - _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, 1000); //FIXME magic number + _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, 300); //FIXME magic number _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 1); //reset _iface->poke32(UE_REG_CTRL_RX_VRT_HEADER, 0 @@ -142,7 +145,7 @@ size_t usrp_e_impl::send( otw_type_t send_otw_type; send_otw_type.width = 16; send_otw_type.shift = 0; - send_otw_type.byteorder = otw_type_t::BO_NATIVE; + send_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; return vrt_packet_handler::send( _io_impl->send_state, @@ -170,7 +173,7 @@ size_t usrp_e_impl::recv( otw_type_t recv_otw_type; recv_otw_type.width = 16; recv_otw_type.shift = 0; - recv_otw_type.byteorder = otw_type_t::BO_NATIVE; + recv_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; return vrt_packet_handler::recv( _io_impl->recv_state, -- cgit v1.2.3 From cd84a19214ea03a3615b5ac7997f33fcfc9870ae Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Jun 2010 22:51:02 +0000 Subject: usrp-e: working vrt recv, implemented dsp utils in usrp-e dsp --- host/lib/usrp/usrp_e/codec_ctrl.cpp | 2 +- host/lib/usrp/usrp_e/dsp_impl.cpp | 59 +++++-------------------------------- host/lib/usrp/usrp_e/io_impl.cpp | 27 ++++++++++++----- 3 files changed, 28 insertions(+), 60 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index b19606020..ce3458827 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -29,7 +29,7 @@ using namespace uhd; -static const bool codec_debug = true; +static const bool codec_debug = false; /*********************************************************************** * Codec Control Implementation diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index 11d22d15f..a87a41ca6 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -17,53 +17,15 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" +#include "../dsp_utils.hpp" #include -#include #include -#include #define rint boost::math::iround using namespace uhd; using namespace uhd::usrp; -/*********************************************************************** - * Helper Functions - **********************************************************************/ -static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq, double clock_freq){ - UHD_ASSERT_THROW(std::abs(freq) < clock_freq/2.0); - static const double scale_factor = std::pow(2.0, 32); - - //calculate the freq register word - boost::uint32_t freq_word = rint((freq / clock_freq) * scale_factor); - - //update the actual frequency - freq = (double(freq_word) / scale_factor) * clock_freq; - - return freq_word; -} - -// Check if requested decim/interp rate is: -// multiple of 4, enable two halfband filters -// multiple of 2, enable one halfband filter -// handle remainder in CIC -static boost::uint32_t calculate_cic_word(size_t rate){ - int hb0 = 0, hb1 = 0; - if (not (rate & 0x1)){ - hb0 = 1; - rate /= 2; - } - if (not (rate & 0x1)){ - hb1 = 1; - rate /= 2; - } - return (hb1 << 9) | (hb0 << 8) | (rate & 0xff); -} - -static boost::uint32_t calculate_iq_scale_word(boost::int16_t i, boost::int16_t q){ - return (boost::uint16_t(i) << 16) | (boost::uint16_t(q) << 0); -} - /*********************************************************************** * RX DDC Initialization **********************************************************************/ @@ -112,7 +74,7 @@ void usrp_e_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); _iface->poke32(UE_REG_DSP_RX_FREQ, - calculate_freq_word_and_update_actual_freq(new_freq, MASTER_CLOCK_RATE) + dsp_type1::calc_cordic_word_and_update(new_freq, MASTER_CLOCK_RATE) ); _ddc_freq = new_freq; //shadow } @@ -121,12 +83,12 @@ void usrp_e_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val){ case DSP_PROP_HOST_RATE:{ //set the decimation _ddc_decim = rint(MASTER_CLOCK_RATE/val.as()); - _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, calculate_cic_word(_ddc_decim)); + _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); //set the scaling static const boost::int16_t default_rx_scale_iq = 1024; _iface->poke32(UE_REG_DSP_RX_SCALE_IQ, - calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) + dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) ); } return; @@ -183,7 +145,7 @@ void usrp_e_impl::tx_duc_set(const wax::obj &key, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); _iface->poke32(UE_REG_DSP_TX_FREQ, - calculate_freq_word_and_update_actual_freq(new_freq, MASTER_CLOCK_RATE) + dsp_type1::calc_cordic_word_and_update(new_freq, MASTER_CLOCK_RATE) ); _duc_freq = new_freq; //shadow } @@ -192,18 +154,11 @@ void usrp_e_impl::tx_duc_set(const wax::obj &key, const wax::obj &val){ case DSP_PROP_HOST_RATE:{ _duc_interp = rint(MASTER_CLOCK_RATE/val.as()); - // Calculate CIC interpolation (i.e., without halfband interpolators) - size_t tmp_interp = calculate_cic_word(_duc_interp) & 0xff; - - // Calculate closest multiplier constant to reverse gain absent scale multipliers - double interp_cubed = std::pow(double(tmp_interp), 3); - boost::int16_t scale = rint((4096*std::pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed)); - //set the interpolation - _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, calculate_cic_word(_duc_interp)); + _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp)); //set the scaling - _iface->poke32(UE_REG_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale)); + _iface->poke32(UE_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_duc_interp)); } return; diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 7c451a75f..d26f113f5 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -29,6 +29,8 @@ using namespace uhd; static const size_t MAX_BUFF_SIZE = 2048; +static const size_t vrt_header_offset_words32 = offsetof(usrp_transfer_frame, buf)/sizeof(boost::uint32_t); + /*********************************************************************** * Data Transport (phony zero-copy with read/write) **********************************************************************/ @@ -70,17 +72,26 @@ private: ); } size_t recv(const boost::asio::mutable_buffer &buff){ - std::cout << boost::format( - "calling read on fd %d, buff size is %d" - ) % _fd % boost::asio::buffer_size(buff) << std::endl; + //std::cout << boost::format( + // "calling read on fd %d, buff size is %d" + //) % _fd % boost::asio::buffer_size(buff) << std::endl; ssize_t ret = read( _fd, boost::asio::buffer_cast(buff), boost::asio::buffer_size(buff) ); if (ret < ssize_t(sizeof(usrp_transfer_frame))) return 0; - std::cout << "len " << int(boost::asio::buffer_cast(buff)->len) << std::endl; - return boost::asio::buffer_cast(buff)->len; + //overwrite the vrt header length with the transfer frame length + size_t frame_size = boost::asio::buffer_cast(buff)->len; + boost::uint32_t *vrt_header = boost::asio::buffer_cast(buff) + vrt_header_offset_words32; + vrt_header[0] = (vrt_header[0] & ~0xffff) | ((frame_size/sizeof(boost::uint32_t)) & 0xffff); + + //std::cout << "len " << int(boost::asio::buffer_cast(buff)->len) << std::endl; + //for (size_t i = 0; i < 7; i++){ + // std::cout << boost::format(" 0x%08x") % boost::asio::buffer_cast(buff)[i] << std::endl; + //} + + return frame_size; } }; @@ -155,9 +166,10 @@ size_t usrp_e_impl::send( io_type, send_otw_type, //TODO MASTER_CLOCK_RATE, + uhd::transport::vrt::pack_le, boost::bind(&data_transport::get_send_buff, &_io_impl->transport), (MAX_BUFF_SIZE - sizeof(usrp_transfer_frame))/send_otw_type.get_sample_size(), - offsetof(usrp_transfer_frame, buf) + vrt_header_offset_words32 ); } @@ -183,7 +195,8 @@ size_t usrp_e_impl::recv( io_type, recv_otw_type, //TODO MASTER_CLOCK_RATE, + uhd::transport::vrt::unpack_le, boost::bind(&data_transport::get_recv_buff, &_io_impl->transport), - offsetof(usrp_transfer_frame, buf) + vrt_header_offset_words32 ); } -- cgit v1.2.3 From c8e2670b63ec4e7dbec1549dbc452dfeacecf07d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 9 Jun 2010 01:05:14 +0000 Subject: usrp-e: switched otw type to little endian (works now) --- host/lib/usrp/usrp_e/io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index d26f113f5..a94275b78 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -156,7 +156,7 @@ size_t usrp_e_impl::send( otw_type_t send_otw_type; send_otw_type.width = 16; send_otw_type.shift = 0; - send_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; + send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; return vrt_packet_handler::send( _io_impl->send_state, @@ -185,7 +185,7 @@ size_t usrp_e_impl::recv( otw_type_t recv_otw_type; recv_otw_type.width = 16; recv_otw_type.shift = 0; - recv_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; + recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; return vrt_packet_handler::recv( _io_impl->recv_state, -- cgit v1.2.3 From 71783634c4394e739bbc13a9bb3df7d6ab75c147 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 10 Jun 2010 18:25:42 +0000 Subject: installed mux setting and initing the duc and ddc --- host/lib/usrp/usrp_e/dboard_impl.cpp | 40 ++++++++++++++++++++++-------------- host/lib/usrp/usrp_e/dsp_impl.cpp | 8 ++++++++ host/lib/usrp/usrp_e/usrp_e_regs.hpp | 3 ++- 3 files changed, 35 insertions(+), 16 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 22c4ac8b7..a384c71a0 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -15,10 +15,13 @@ // along with this program. If not, see . // -#include #include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include "../dsp_utils.hpp" #include #include +#include +#include #include using namespace uhd; @@ -31,9 +34,6 @@ void usrp_e_impl::dboard_init(void){ _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); - std::cout << _rx_db_eeprom.id.to_pp_string() << std::endl; - std::cout << _tx_db_eeprom.id.to_pp_string() << std::endl; - //create a new dboard interface and manager _dboard_iface = make_usrp_e_dboard_iface( _iface, _clock_ctrl, _codec_ctrl @@ -53,11 +53,8 @@ void usrp_e_impl::dboard_init(void){ ); //init the subdevs in use (use the first subdevice) - _rx_subdevs_in_use = prop_names_t(1, _dboard_manager->get_rx_subdev_names().at(0)); - //TODO update_rx_mux_config(); - - _tx_subdevs_in_use = prop_names_t(1, _dboard_manager->get_tx_subdev_names().at(0)); - //TODO update_tx_mux_config(); + rx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_rx_subdev_names().at(0))); + tx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_tx_subdev_names().at(0))); } /*********************************************************************** @@ -102,9 +99,16 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ **********************************************************************/ void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as()){ - case DBOARD_PROP_USED_SUBDEVS: - _rx_subdevs_in_use = val.as(); - //TODO update_rx_mux_config(); //if the val is bad, this will throw + case DBOARD_PROP_USED_SUBDEVS:{ + _rx_subdevs_in_use = val.as(); + UHD_ASSERT_THROW(_rx_subdevs_in_use.size() == 1); + wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0)); + std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as() << std::endl; + _iface->poke32(UE_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( + rx_subdev[SUBDEV_PROP_QUADRATURE].as(), + rx_subdev[SUBDEV_PROP_IQ_SWAPPED].as() + )); + } return; case DBOARD_PROP_DBOARD_ID: @@ -158,9 +162,15 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ **********************************************************************/ void usrp_e_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as()){ - case DBOARD_PROP_USED_SUBDEVS: - _tx_subdevs_in_use = val.as(); - //TODO update_tx_mux_config(); //if the val is bad, this will throw + case DBOARD_PROP_USED_SUBDEVS:{ + _tx_subdevs_in_use = val.as(); + UHD_ASSERT_THROW(_tx_subdevs_in_use.size() == 1); + wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); + std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as() << std::endl; + _iface->poke32(UE_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( + tx_subdev[SUBDEV_PROP_IQ_SWAPPED].as() + )); + } return; case DBOARD_PROP_DBOARD_ID: diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index a87a41ca6..58a58706d 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -34,6 +34,10 @@ void usrp_e_impl::rx_ddc_init(void){ boost::bind(&usrp_e_impl::rx_ddc_get, this, _1, _2), boost::bind(&usrp_e_impl::rx_ddc_set, this, _1, _2) ); + + //initial config and update + rx_ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); + rx_ddc_set(DSP_PROP_HOST_RATE, double(64e6/10)); } /*********************************************************************** @@ -105,6 +109,10 @@ void usrp_e_impl::tx_duc_init(void){ boost::bind(&usrp_e_impl::tx_duc_get, this, _1, _2), boost::bind(&usrp_e_impl::tx_duc_set, this, _1, _2) ); + + //initial config and update + tx_duc_set(DSP_PROP_FREQ_SHIFT, double(0)); + tx_duc_set(DSP_PROP_HOST_RATE, double(64e6/10)); } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index 67c174208..41cbfa1e2 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -174,7 +174,8 @@ #define UE_REG_TIME64_SECS UE_REG_SR_ADDR(28) // value to set absolute secs to on next PPS #define UE_REG_TIME64_TICKS UE_REG_SR_ADDR(29) // value to set absolute ticks to on next PPS #define UE_REG_TIME64_FLAGS UE_REG_SR_ADDR(30) // flags - see chart above -#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0) +#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0) +#define UE_REG_TIME64_TPS UE_REG_SR_ADDR(31) // clock ticks per second (counter rollover) //pps flags (see above) #define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0) -- cgit v1.2.3 From ec451d811c335af672d7a8ffbcfd3d0a1a645b2b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 14 Jun 2010 22:32:54 +0000 Subject: file option for rx timed samples, misc fixes --- host/examples/rx_timed_samples.cpp | 21 ++++++++++++++++----- host/lib/usrp/usrp_e/codec_ctrl.cpp | 11 +++-------- host/lib/usrp/usrp_e/io_impl.cpp | 4 ++-- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 4 ++-- 4 files changed, 23 insertions(+), 17 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 64da260d5..eb7ef7251 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -20,13 +20,14 @@ #include #include #include +#include #include namespace po = boost::program_options; int UHD_SAFE_MAIN(int argc, char *argv[]){ //variables to be set by po - std::string args; + std::string args, file_path; int seconds_in_future; size_t total_num_samps; double rx_rate, freq; @@ -40,6 +41,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("file", po::value(&file_path)->default_value(""), "write samps to output file") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -76,14 +78,20 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); sdev->issue_stream_cmd(stream_cmd); + std::ofstream outfile; + if(file_path != "") outfile.open (file_path.c_str(), std::ios::out | std::ios::binary); + + //setup recv buffer, io type, and metadata for recv + uhd::rx_metadata_t md; + uhd::io_type_t io_type(uhd::io_type_t::COMPLEX_INT16); + std::vector > recv_mem(dev->get_max_recv_samps_per_packet()); + boost::asio::mutable_buffer buff(boost::asio::buffer(recv_mem)); + //loop until total number of samples reached size_t num_acc_samps = 0; //number of accumulated samples while(num_acc_samps < total_num_samps){ - uhd::rx_metadata_t md; - std::vector > buff(dev->get_max_recv_samps_per_packet()); size_t num_rx_samps = dev->recv( - boost::asio::buffer(buff), - md, uhd::io_type_t::COMPLEX_FLOAT32, + buff, md, io_type, uhd::device::RECV_MODE_ONE_PACKET ); if (num_rx_samps == 0 and num_acc_samps > 0){ @@ -95,11 +103,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Got packet: %u samples, %u secs, %u nsecs") % num_rx_samps % md.time_spec.secs % md.time_spec.nsecs << std::endl; + if(file_path != "") outfile.write(boost::asio::buffer_cast(buff), num_rx_samps*io_type.size); + num_acc_samps += num_rx_samps; } //finished std::cout << std::endl << "Done!" << std::endl << std::endl; + if(file_path != "") outfile.close(); return 0; } diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index ce3458827..ac61bc6b4 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -58,9 +58,6 @@ private: usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ _iface = iface; - //FIXME temp poke !!! - _iface->poke16(UE_REG_MISC_TEST, 0x0f00); - //soft reset _ad9862_regs.soft_reset = 1; this->send_reg(0); @@ -75,8 +72,8 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ _ad9862_regs.byp_buffer_b = 1; _ad9862_regs.buffer_a_pd = 1; _ad9862_regs.buffer_b_pd = 1; - _ad9862_regs.rx_pga_a = 0x1f; //TODO bring under api control - _ad9862_regs.rx_pga_b = 0x1f; //TODO bring under api control + _ad9862_regs.rx_pga_a = 0;//0x1f; //TODO bring under api control + _ad9862_regs.rx_pga_b = 0;//0x1f; //TODO bring under api control _ad9862_regs.rx_twos_comp = 1; _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS; @@ -85,7 +82,7 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; - _ad9862_regs.interp = ad9862_regs_t::INTERP_4; + _ad9862_regs.interp = ad9862_regs_t::INTERP_2; _ad9862_regs.tx_twos_comp = 1; _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_BYPASS; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; @@ -108,8 +105,6 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ } usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ - return; //FIXME remove this later - //set aux dacs to zero this->write_aux_dac(AUX_DAC_A, 0); this->write_aux_dac(AUX_DAC_B, 0); diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index a94275b78..e1c1fe80b 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -107,7 +107,7 @@ struct usrp_e_impl::io_impl{ void usrp_e_impl::io_init(void){ //setup rx data path - _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, 300); //FIXME magic number + _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 1); //reset _iface->poke32(UE_REG_CTRL_RX_VRT_HEADER, 0 @@ -168,7 +168,7 @@ size_t usrp_e_impl::send( MASTER_CLOCK_RATE, uhd::transport::vrt::pack_le, boost::bind(&data_transport::get_send_buff, &_io_impl->transport), - (MAX_BUFF_SIZE - sizeof(usrp_transfer_frame))/send_otw_type.get_sample_size(), + get_max_send_samps_per_packet(), vrt_header_offset_words32 ); } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 657d2d225..487e295cb 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -80,8 +80,8 @@ public: //the io interface size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t); size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t); - size_t get_max_send_samps_per_packet(void) const{return _max_num_samples;} - size_t get_max_recv_samps_per_packet(void) const{return _max_num_samples;} + size_t get_max_send_samps_per_packet(void) const{return 300;} + size_t get_max_recv_samps_per_packet(void) const{return 300;} private: //interface to ioctls and file descriptor -- cgit v1.2.3 From b4b80f1f6e59fa02d508af860f1a572c9224b975 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 15 Jun 2010 01:23:00 +0000 Subject: usrp-e: added poll(...) call before read(...) call --- host/lib/usrp/usrp_e/io_impl.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index e1c1fe80b..829e923b5 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -22,6 +22,7 @@ #include //read, write #include //transfer frame struct #include //offsetof +#include #include #include @@ -75,12 +76,22 @@ private: //std::cout << boost::format( // "calling read on fd %d, buff size is %d" //) % _fd % boost::asio::buffer_size(buff) << std::endl; + + //setup and call poll on the file descriptor + //return 0 and do not read when poll times out + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLIN; + if (poll(&pfd, 1, 100 /*ms*/) <= 0) return 0; //timeout + + //perform the blocking read(...) ssize_t ret = read( _fd, boost::asio::buffer_cast(buff), boost::asio::buffer_size(buff) ); if (ret < ssize_t(sizeof(usrp_transfer_frame))) return 0; + //overwrite the vrt header length with the transfer frame length size_t frame_size = boost::asio::buffer_cast(buff)->len; boost::uint32_t *vrt_header = boost::asio::buffer_cast(buff) + vrt_header_offset_words32; -- cgit v1.2.3 From e18a963fb5c35ba9ccf03986e8c82adfe44f0b89 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 16 Jun 2010 17:35:20 +0000 Subject: usrp-e: added type device address argument to usrp-e --- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 226825510..a534c74b2 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -44,6 +44,9 @@ static std::string abs_path(const std::string &file_path){ device_addrs_t usrp_e::find(const device_addr_t &hint){ device_addrs_t usrp_e_addrs; + //return an empty list of addresses when type is set to non-usrp-e + if (hint.has_key("type") and hint["type"] != "usrp-e") return usrp_e_addrs; + //device node not provided, assume its 0 if (not hint.has_key("node")){ device_addr_t new_addr = hint; @@ -54,7 +57,7 @@ device_addrs_t usrp_e::find(const device_addr_t &hint){ //use the given device node name if (fs::exists(hint["node"])){ device_addr_t new_addr; - new_addr["name"] = "USRP-E"; + new_addr["type"] = "usrp-e"; new_addr["node"] = abs_path(hint["node"]); usrp_e_addrs.push_back(new_addr); } -- cgit v1.2.3 From 2f9b6d5530df140a5a03120adc98a5ad32a69cc4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 17 Jun 2010 22:33:32 +0000 Subject: usrp-e: added verbose for bad poll and read values --- host/lib/usrp/usrp_e/io_impl.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 829e923b5..c168d6304 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -28,9 +28,13 @@ using namespace uhd; +/*********************************************************************** + * Constants + **********************************************************************/ static const size_t MAX_BUFF_SIZE = 2048; - static const size_t vrt_header_offset_words32 = offsetof(usrp_transfer_frame, buf)/sizeof(boost::uint32_t); +static const bool usrp_e_io_impl_verbose = true; +static const size_t recv_timeout_ms = 100; /*********************************************************************** * Data Transport (phony zero-copy with read/write) @@ -82,15 +86,28 @@ private: pollfd pfd; pfd.fd = _fd; pfd.events = POLLIN; - if (poll(&pfd, 1, 100 /*ms*/) <= 0) return 0; //timeout + ssize_t poll_ret = poll(&pfd, 1, recv_timeout_ms); + if (poll_ret <= 0){ + if (usrp_e_io_impl_verbose) std::cerr << boost::format( + "usrp-e io impl recv(): poll() returned non-positive value: %d\n" + " -> return 0 for timeout" + ) % poll_ret << std::endl; + return 0; //timeout + } //perform the blocking read(...) - ssize_t ret = read( + ssize_t read_ret = read( _fd, boost::asio::buffer_cast(buff), boost::asio::buffer_size(buff) ); - if (ret < ssize_t(sizeof(usrp_transfer_frame))) return 0; + if (read_ret < ssize_t(sizeof(usrp_transfer_frame))){ + if (usrp_e_io_impl_verbose) std::cerr << boost::format( + "usrp-e io impl recv(): read() returned small value: %d\n" + " -> return 0 for error" + ) % read_ret << std::endl; + return 0; + } //overwrite the vrt header length with the transfer frame length size_t frame_size = boost::asio::buffer_cast(buff)->len; -- cgit v1.2.3 From df6cc603fd5e9dc34665385ac84b94eadf074074 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 21 Jun 2010 19:39:15 +0000 Subject: usrp-e: added clock rate control to dboard iface and clock control impl --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 290 ++++++++++++++++++++-------------- host/lib/usrp/usrp_e/clock_ctrl.hpp | 27 +++- host/lib/usrp/usrp_e/dboard_iface.cpp | 53 +++++-- 3 files changed, 226 insertions(+), 144 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index e37b17a54..36799ef63 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -17,6 +17,7 @@ #include "clock_ctrl.hpp" #include "ad9522_regs.hpp" +#include #include #include "usrp_e_regs.hpp" //spi slave constants #include @@ -26,21 +27,171 @@ using namespace uhd; +template static void set_clock_divider( + size_t divider, div_type &low, div_type &high +){ + high = divider/2; + low = divider-high; +} + +/*********************************************************************** + * Constants + **********************************************************************/ +static const double master_clock_rate = 320e6; +static const size_t fpga_clock_divider = 5; //64 MHz +static const size_t codec_clock_divider = 5; //64 MHz + /*********************************************************************** * Clock Control Implementation **********************************************************************/ class usrp_e_clock_ctrl_impl : public usrp_e_clock_ctrl{ public: - //structors - usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface); - ~usrp_e_clock_ctrl_impl(void); + usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ + _iface = iface; + + //init the clock gen registers + //Note: out0 should already be clocking the FPGA or this isnt going to work + _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; + _ad9522_regs.status_pin_control = 0x1; //n divider + _ad9522_regs.ld_pin_control = 0x32; //show ref2 + _ad9522_regs.refmon_pin_control = 0x12; //show ref2 + + _ad9522_regs.enable_ref2 = 1; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; + + _ad9522_regs.r_counter_lsb = 1; + _ad9522_regs.r_counter_msb = 0; + _ad9522_regs.a_counter = 0; + _ad9522_regs.b_counter_lsb = 20; + _ad9522_regs.b_counter_msb = 0; + _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; + + _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; + _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_3_0MA; + + _ad9522_regs.vco_calibration_now = 1; //calibrate it! + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; + _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; + + //setup fpga master clock + _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; + set_clock_divider(fpga_clock_divider, + _ad9522_regs.divider0_low_cycles, + _ad9522_regs.divider0_high_cycles + ); + + //setup codec clock + _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; + set_clock_divider(codec_clock_divider, + _ad9522_regs.divider1_low_cycles, + _ad9522_regs.divider1_high_cycles + ); + + //setup test clock (same divider as codec clock) + _ad9522_regs.out4_format = ad9522_regs_t::OUT4_FORMAT_CMOS; + _ad9522_regs.out4_cmos_configuration = (true)? + ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : + ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; + + //setup a list of register ranges to write + typedef std::pair range_t; + static const std::vector ranges = boost::assign::list_of + (range_t(0x000, 0x000)) (range_t(0x010, 0x01F)) + (range_t(0x0F0, 0x0FD)) (range_t(0x190, 0x19B)) + (range_t(0x1E0, 0x1E1)) (range_t(0x230, 0x230)) + ; + + //write initial register values and latch/update + BOOST_FOREACH(const range_t &range, ranges){ + for(boost::uint16_t addr = range.first; addr <= range.second; addr++){ + this->send_reg(addr); + } + } + this->latch_regs(); + //test read: + //boost::uint32_t reg = _ad9522_regs.get_read_reg(0x01b); + //boost::uint32_t result = _iface->transact_spi( + // UE_SPI_SS_AD9522, + // spi_config_t::EDGE_RISE, + // reg, 24, true /*no*/ + //); + //std::cout << "result " << std::hex << result << std::endl; + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + } + + ~usrp_e_clock_ctrl_impl(void){ + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + } - void enable_rx_dboard_clock(bool enb); - void enable_tx_dboard_clock(bool enb); + double get_fpga_clock_rate(void){ + return master_clock_rate/fpga_clock_divider; + } - double get_fpga_clock_rate(void){return 64e6;} - double get_rx_dboard_clock_rate(void){return get_fpga_clock_rate();} - double get_tx_dboard_clock_rate(void){return get_fpga_clock_rate();} + /*********************************************************************** + * RX Dboard Clock Control (output 9, divider 3) + **********************************************************************/ + void enable_rx_dboard_clock(bool enb){ + _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_CMOS; + _ad9522_regs.out9_cmos_configuration = (enb)? + ad9522_regs_t::OUT9_CMOS_CONFIGURATION_B_ON : + ad9522_regs_t::OUT9_CMOS_CONFIGURATION_OFF; + this->send_reg(0x0F9); + this->latch_regs(); + } + + std::vector get_rx_dboard_clock_rates(void){ + std::vector rates; + for(size_t div = 1; div <= 16+16; div++) rates.push_back(master_clock_rate/div); + return rates; + } + + void set_rx_dboard_clock_rate(double rate){ + assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); + size_t divider = size_t(rate/master_clock_rate); + //bypass when the divider ratio is one + _ad9522_regs.divider3_bypass = (divider == 1)? 1 : 0; + this->send_reg(0x19a); + //set the divider registers + set_clock_divider(divider, + _ad9522_regs.divider3_low_cycles, + _ad9522_regs.divider3_high_cycles + ); + this->send_reg(0x199); + this->latch_regs(); + } + + /*********************************************************************** + * TX Dboard Clock Control (output 6, divider 2) + **********************************************************************/ + void enable_tx_dboard_clock(bool enb){ + _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_CMOS; + _ad9522_regs.out6_cmos_configuration = (enb)? + ad9522_regs_t::OUT6_CMOS_CONFIGURATION_B_ON : + ad9522_regs_t::OUT6_CMOS_CONFIGURATION_OFF; + this->send_reg(0x0F6); + this->latch_regs(); + } + + std::vector get_tx_dboard_clock_rates(void){ + return get_rx_dboard_clock_rates(); //same master clock, same dividers... + } + + void set_tx_dboard_clock_rate(double rate){ + assert_has(get_tx_dboard_clock_rates(), rate, "tx dboard clock rate"); + size_t divider = size_t(rate/master_clock_rate); + //bypass when the divider ratio is one + _ad9522_regs.divider2_bypass = (divider == 1)? 1 : 0; + this->send_reg(0x197); + //set the divider registers + set_clock_divider(divider, + _ad9522_regs.divider2_low_cycles, + _ad9522_regs.divider2_high_cycles + ); + this->send_reg(0x196); + this->latch_regs(); + } private: usrp_e_iface::sptr _iface; @@ -50,122 +201,17 @@ private: _ad9522_regs.io_update = 1; this->send_reg(0x232); } - void send_reg(boost::uint16_t addr); -}; -/*********************************************************************** - * Clock Control Methods - **********************************************************************/ -usrp_e_clock_ctrl_impl::usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ - _iface = iface; - - //init the clock gen registers - //Note: out0 should already be clocking the FPGA or this isnt going to work - _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; - _ad9522_regs.status_pin_control = 0x1; //n divider - _ad9522_regs.ld_pin_control = 0x32; //show ref2 - _ad9522_regs.refmon_pin_control = 0x12; //show ref2 - - _ad9522_regs.enable_ref2 = 1; - _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; - - _ad9522_regs.r_counter_lsb = 1; - _ad9522_regs.r_counter_msb = 0; - _ad9522_regs.a_counter = 0; - _ad9522_regs.b_counter_lsb = 20; - _ad9522_regs.b_counter_msb = 0; - _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; - - _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; - _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_3_0MA; - - _ad9522_regs.vco_calibration_now = 1; //calibrate it! - _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; - _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; - - //setup fpga master clock - _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; - _ad9522_regs.divider0_low_cycles = 2; //3 low - _ad9522_regs.divider0_high_cycles = 1; //2 high - - //setup codec clock - _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; - _ad9522_regs.divider1_low_cycles = 2; //3 low - _ad9522_regs.divider1_high_cycles = 1; //2 high - - //setup test clock (same divider as codec clock) - _ad9522_regs.out4_format = ad9522_regs_t::OUT4_FORMAT_CMOS; - _ad9522_regs.out4_cmos_configuration = (true)? - ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : - ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; - - //setup a list of register ranges to write - typedef std::pair range_t; - static const std::vector ranges = boost::assign::list_of - (range_t(0x000, 0x000)) (range_t(0x010, 0x01F)) - (range_t(0x0F0, 0x0FD)) (range_t(0x190, 0x19B)) - (range_t(0x1E0, 0x1E1)) (range_t(0x230, 0x230)) - ; - - //write initial register values and latch/update - BOOST_FOREACH(const range_t &range, ranges){ - for(boost::uint16_t addr = range.first; addr <= range.second; addr++){ - this->send_reg(addr); - } + void send_reg(boost::uint16_t addr){ + boost::uint32_t reg = _ad9522_regs.get_write_reg(addr); + //std::cout << "clock control write reg: " << std::hex << reg << std::endl; + _iface->transact_spi( + UE_SPI_SS_AD9522, + spi_config_t::EDGE_RISE, + reg, 24, false /*no rb*/ + ); } - this->latch_regs(); - //test read: - //boost::uint32_t reg = _ad9522_regs.get_read_reg(0x01b); - //boost::uint32_t result = _iface->transact_spi( - // UE_SPI_SS_AD9522, - // spi_config_t::EDGE_RISE, - // reg, 24, true /*no*/ - //); - //std::cout << "result " << std::hex << result << std::endl; - this->enable_rx_dboard_clock(false); - this->enable_tx_dboard_clock(false); -} - -usrp_e_clock_ctrl_impl::~usrp_e_clock_ctrl_impl(void){ - this->enable_rx_dboard_clock(false); - this->enable_tx_dboard_clock(false); -} - -void usrp_e_clock_ctrl_impl::enable_rx_dboard_clock(bool enb){ - _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_CMOS; - _ad9522_regs.out9_cmos_configuration = (enb)? - ad9522_regs_t::OUT9_CMOS_CONFIGURATION_B_ON : - ad9522_regs_t::OUT9_CMOS_CONFIGURATION_OFF; - this->send_reg(0x0F9); - - _ad9522_regs.divider3_low_cycles = 2; //3 low - _ad9522_regs.divider3_high_cycles = 1; //2 high - this->send_reg(0x199); - this->latch_regs(); -} - -void usrp_e_clock_ctrl_impl::enable_tx_dboard_clock(bool enb){ - _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_CMOS; - _ad9522_regs.out6_cmos_configuration = (enb)? - ad9522_regs_t::OUT6_CMOS_CONFIGURATION_B_ON : - ad9522_regs_t::OUT6_CMOS_CONFIGURATION_OFF; - this->send_reg(0x0F6); - - _ad9522_regs.divider2_low_cycles = 2; //3 low - _ad9522_regs.divider2_high_cycles = 1; //2 high - this->send_reg(0x196); - this->latch_regs(); -} - -void usrp_e_clock_ctrl_impl::send_reg(boost::uint16_t addr){ - boost::uint32_t reg = _ad9522_regs.get_write_reg(addr); - //std::cout << "clock control write reg: " << std::hex << reg << std::endl; - _iface->transact_spi( - UE_SPI_SS_AD9522, - spi_config_t::EDGE_RISE, - reg, 24, false /*no rb*/ - ); -} +}; /*********************************************************************** * Clock Control Make diff --git a/host/lib/usrp/usrp_e/clock_ctrl.hpp b/host/lib/usrp/usrp_e/clock_ctrl.hpp index 692b9eb0e..3b5103ed1 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.hpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.hpp @@ -21,6 +21,7 @@ #include "usrp_e_iface.hpp" #include #include +#include /*! * The usrp-e clock control: @@ -45,16 +46,30 @@ public: virtual double get_fpga_clock_rate(void) = 0; /*! - * Get the rate of the dboard clock clock line. - * \return the dboard clock rate in Hz + * Get the possible rates of the rx dboard clock. + * \return a vector of clock rates in Hz */ - virtual double get_rx_dboard_clock_rate(void) = 0; + virtual std::vector get_rx_dboard_clock_rates(void) = 0; /*! - * Get the rate of the dboard clock clock line. - * \return the dboard clock rate in Hz + * Get the possible rates of the tx dboard clock. + * \return a vector of clock rates in Hz */ - virtual double get_tx_dboard_clock_rate(void) = 0; + virtual std::vector get_tx_dboard_clock_rates(void) = 0; + + /*! + * Set the rx dboard clock rate to a possible rate. + * \param rate the new clock rate in Hz + * \throw exception when rate cannot be achieved + */ + virtual void set_rx_dboard_clock_rate(double rate) = 0; + + /*! + * Set the tx dboard clock rate to a possible rate. + * \param rate the new clock rate in Hz + * \throw exception when rate cannot be achieved + */ + virtual void set_tx_dboard_clock_rate(double rate) = 0; /*! * Enable/disable the rx dboard clock. diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index 594f2a23e..ce00cd40d 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -40,14 +40,18 @@ public: _iface = iface; _clock = clock; _codec = codec; + + //init the clock rate shadows + this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); + this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); } ~usrp_e_dboard_iface(void){ /* NOP */ } - void write_aux_dac(unit_t, int, float); - float read_aux_adc(unit_t, int); + void write_aux_dac(unit_t, aux_dac_t, float); + float read_aux_adc(unit_t, aux_adc_t); void set_pin_ctrl(unit_t, boost::uint16_t); void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); @@ -72,6 +76,8 @@ public: size_t num_bits ); + void set_clock_rate(unit_t, double); + std::vector get_clock_rates(unit_t); double get_clock_rate(unit_t); void set_clock_enabled(unit_t, bool); @@ -79,6 +85,7 @@ private: usrp_e_iface::sptr _iface; usrp_e_clock_ctrl::sptr _clock; usrp_e_codec_ctrl::sptr _codec; + uhd::dict _clock_rates; }; /*********************************************************************** @@ -95,12 +102,24 @@ dboard_iface::sptr make_usrp_e_dboard_iface( /*********************************************************************** * Clock Rates **********************************************************************/ -double usrp_e_dboard_iface::get_clock_rate(unit_t unit){ +void usrp_e_dboard_iface::set_clock_rate(unit_t unit, double rate){ + _clock_rates[unit] = rate; switch(unit){ - case UNIT_RX: return _clock->get_rx_dboard_clock_rate(); - case UNIT_TX: return _clock->get_tx_dboard_clock_rate(); + case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate); + case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate); } - UHD_ASSERT_THROW(false); +} + +std::vector usrp_e_dboard_iface::get_clock_rates(unit_t unit){ + switch(unit){ + case UNIT_RX: return _clock->get_rx_dboard_clock_rates(); + case UNIT_TX: return _clock->get_tx_dboard_clock_rates(); + default: UHD_THROW_INVALID_CODE_PATH(); + } +} + +double usrp_e_dboard_iface::get_clock_rate(unit_t unit){ + return _clock_rates[unit]; } void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ @@ -212,26 +231,28 @@ byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_byte /*********************************************************************** * Aux DAX/ADC **********************************************************************/ -void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t, int which, float value){ +void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which, float value){ //same aux dacs for each unit - static const uhd::dict which_to_aux_dac = map_list_of - (0, usrp_e_codec_ctrl::AUX_DAC_A) (1, usrp_e_codec_ctrl::AUX_DAC_B) - (2, usrp_e_codec_ctrl::AUX_DAC_C) (3, usrp_e_codec_ctrl::AUX_DAC_D) + static const uhd::dict which_to_aux_dac = map_list_of + (AUX_DAC_A, usrp_e_codec_ctrl::AUX_DAC_A) + (AUX_DAC_B, usrp_e_codec_ctrl::AUX_DAC_B) + (AUX_DAC_C, usrp_e_codec_ctrl::AUX_DAC_C) + (AUX_DAC_D, usrp_e_codec_ctrl::AUX_DAC_D) ; _codec->write_aux_dac(which_to_aux_dac[which], value); } -float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, int which){ +float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, aux_adc_t which){ static const uhd::dict< - unit_t, uhd::dict + unit_t, uhd::dict > unit_to_which_to_aux_adc = map_list_of (UNIT_RX, map_list_of - (0, usrp_e_codec_ctrl::AUX_ADC_A1) - (1, usrp_e_codec_ctrl::AUX_ADC_B1) + (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A1) + (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B1) ) (UNIT_TX, map_list_of - (0, usrp_e_codec_ctrl::AUX_ADC_A2) - (1, usrp_e_codec_ctrl::AUX_ADC_B2) + (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A2) + (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B2) ) ; return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]); -- cgit v1.2.3 From e6aed138b08100fe81355771fc62d4ff2f7556d0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 23 Jun 2010 00:16:59 +0000 Subject: usrp-e: clock divider calculation fix --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 36799ef63..bf38db8a6 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -30,8 +30,8 @@ using namespace uhd; template static void set_clock_divider( size_t divider, div_type &low, div_type &high ){ - high = divider/2; - low = divider-high; + high = divider/2 - 1; + low = divider - high - 2; } /*********************************************************************** -- cgit v1.2.3 From 2ff1a854669a0fe5c8029f0c013e38faade6b826 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 23 Jun 2010 01:43:25 +0000 Subject: usrp-e: clock control constants to easily change dividers and counters, tweaks to ic reg maps common --- host/lib/ic_reg_maps/common.py | 4 +-- host/lib/ic_reg_maps/gen_ad9522_regs.py | 2 ++ host/lib/usrp/usrp_e/clock_ctrl.cpp | 50 ++++++++++++++++++++------------- 3 files changed, 34 insertions(+), 22 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/ic_reg_maps/common.py b/host/lib/ic_reg_maps/common.py index 173186eb1..47325a7e3 100644 --- a/host/lib/ic_reg_maps/common.py +++ b/host/lib/ic_reg_maps/common.py @@ -59,7 +59,7 @@ public: delete _state; } -$body + $body void save_state(void){ if (_state == NULL) _state = new $(name)_t(); @@ -181,7 +181,7 @@ def generate(name, regs_tmpl, body_tmpl='', file=__file__): else: regs.append(reg(entry)) #evaluate the body template with the list of registers - body = parse_tmpl(body_tmpl, regs=regs).replace('\n', '\n ').strip() + body = '\n '.join(parse_tmpl(body_tmpl, regs=regs).splitlines()) #evaluate the code template with the parsed registers and arguments code = parse_tmpl(COMMON_TMPL, diff --git a/host/lib/ic_reg_maps/gen_ad9522_regs.py b/host/lib/ic_reg_maps/gen_ad9522_regs.py index 9da51205b..ed6b5f48d 100755 --- a/host/lib/ic_reg_maps/gen_ad9522_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9522_regs.py @@ -32,9 +32,11 @@ cp_mode 0x010[3:2] 3 high_imp, force pll_power_down 0x010[1:0] 1 normal=0, async=1, sync=3 r_counter_lsb 0x011[7:0] 1 r_counter_msb 0x012[5:0] 0 +~r_counter r_counter_lsb, r_counter_msb a_counter 0x013[5:0] 0 b_counter_lsb 0x014[7:0] 3 b_counter_msb 0x015[4:0] 0 +~b_counter b_counter_lsb, b_counter_msb set_cp_pin_to_vcp_2 0x016[7] 0 normal, vcp_2 reset_r_counter 0x016[6] 0 reset_a_and_b_counters 0x016[5] 0 diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index bf38db8a6..0b18763a4 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -27,19 +27,31 @@ using namespace uhd; -template static void set_clock_divider( - size_t divider, div_type &low, div_type &high +template static void set_clock_divider( + size_t divider, div_type &low, div_type &high, bypass_type &bypass ){ high = divider/2 - 1; low = divider - high - 2; + bypass = (divider == 1)? 1 : 0; } /*********************************************************************** * Constants **********************************************************************/ -static const double master_clock_rate = 320e6; -static const size_t fpga_clock_divider = 5; //64 MHz -static const size_t codec_clock_divider = 5; //64 MHz +static const double ref_clock_rate = 10e6; + +static const size_t r_counter = 1; +static const size_t a_counter = 0; +static const size_t b_counter = 20; +static const size_t prescaler = 8; //set below with enum +static const size_t vco_divider = 5; //set below with enum + +static const size_t n_counter = prescaler * b_counter + a_counter; +static const size_t vco_clock_rate = ref_clock_rate/r_counter * n_counter; +static const double master_clock_rate = vco_clock_rate/vco_divider; + +static const size_t fpga_clock_divider = size_t(master_clock_rate/64e6); +static const size_t codec_clock_divider = size_t(master_clock_rate/64e6); /*********************************************************************** * Clock Control Implementation @@ -59,11 +71,9 @@ public: _ad9522_regs.enable_ref2 = 1; _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; - _ad9522_regs.r_counter_lsb = 1; - _ad9522_regs.r_counter_msb = 0; - _ad9522_regs.a_counter = 0; - _ad9522_regs.b_counter_lsb = 20; - _ad9522_regs.b_counter_msb = 0; + _ad9522_regs.set_r_counter(r_counter); + _ad9522_regs.a_counter = a_counter; + _ad9522_regs.set_b_counter(b_counter); _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; @@ -77,14 +87,16 @@ public: _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; set_clock_divider(fpga_clock_divider, _ad9522_regs.divider0_low_cycles, - _ad9522_regs.divider0_high_cycles + _ad9522_regs.divider0_high_cycles, + _ad9522_regs.divider0_bypass ); //setup codec clock _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; set_clock_divider(codec_clock_divider, _ad9522_regs.divider1_low_cycles, - _ad9522_regs.divider1_high_cycles + _ad9522_regs.divider1_high_cycles, + _ad9522_regs.divider1_bypass ); //setup test clock (same divider as codec clock) @@ -150,15 +162,14 @@ public: void set_rx_dboard_clock_rate(double rate){ assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); size_t divider = size_t(rate/master_clock_rate); - //bypass when the divider ratio is one - _ad9522_regs.divider3_bypass = (divider == 1)? 1 : 0; - this->send_reg(0x19a); //set the divider registers set_clock_divider(divider, _ad9522_regs.divider3_low_cycles, - _ad9522_regs.divider3_high_cycles + _ad9522_regs.divider3_high_cycles, + _ad9522_regs.divider3_bypass ); this->send_reg(0x199); + this->send_reg(0x19a); this->latch_regs(); } @@ -181,15 +192,14 @@ public: void set_tx_dboard_clock_rate(double rate){ assert_has(get_tx_dboard_clock_rates(), rate, "tx dboard clock rate"); size_t divider = size_t(rate/master_clock_rate); - //bypass when the divider ratio is one - _ad9522_regs.divider2_bypass = (divider == 1)? 1 : 0; - this->send_reg(0x197); //set the divider registers set_clock_divider(divider, _ad9522_regs.divider2_low_cycles, - _ad9522_regs.divider2_high_cycles + _ad9522_regs.divider2_high_cycles, + _ad9522_regs.divider2_bypass ); this->send_reg(0x196); + this->send_reg(0x197); this->latch_regs(); } -- cgit v1.2.3 From 89a22c7dd531b1754f2401037a4a5c971139bd97 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Jul 2010 01:58:30 +0000 Subject: usrp-e: tweaks to clock control logic --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 0b18763a4..df649cee6 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -43,11 +43,11 @@ static const double ref_clock_rate = 10e6; static const size_t r_counter = 1; static const size_t a_counter = 0; static const size_t b_counter = 20; -static const size_t prescaler = 8; //set below with enum -static const size_t vco_divider = 5; //set below with enum +static const size_t prescaler = 8; //set below with enum, set to 8 when input is under 2400 MHz +static const size_t vco_divider = 1; //set below with enum static const size_t n_counter = prescaler * b_counter + a_counter; -static const size_t vco_clock_rate = ref_clock_rate/r_counter * n_counter; +static const size_t vco_clock_rate = ref_clock_rate/r_counter * n_counter; //between 1400 and 1800 MHz static const double master_clock_rate = vco_clock_rate/vco_divider; static const size_t fpga_clock_divider = size_t(master_clock_rate/64e6); @@ -60,15 +60,18 @@ class usrp_e_clock_ctrl_impl : public usrp_e_clock_ctrl{ public: usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ _iface = iface; + std::cout << "master_clock_rate: " << (master_clock_rate/1e6) << " MHz" << std::endl; //init the clock gen registers //Note: out0 should already be clocking the FPGA or this isnt going to work _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; + _ad9522_regs.enb_stat_eeprom_at_stat_pin = 0; //use status pin _ad9522_regs.status_pin_control = 0x1; //n divider - _ad9522_regs.ld_pin_control = 0x32; //show ref2 + _ad9522_regs.ld_pin_control = 0x00; //dld _ad9522_regs.refmon_pin_control = 0x12; //show ref2 _ad9522_regs.enable_ref2 = 1; + _ad9522_regs.enable_ref1 = 0; _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; _ad9522_regs.set_r_counter(r_counter); @@ -80,7 +83,7 @@ public: _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_3_0MA; _ad9522_regs.vco_calibration_now = 1; //calibrate it! - _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV1; _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; //setup fpga master clock -- cgit v1.2.3 From 998fee6ef064f1d53a61dd0eec79276d1e85291e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Jul 2010 02:19:20 +0000 Subject: usrp-e: removed top level header for usrp-e and fpga burner app, were not going to do it that way... --- host/include/uhd/usrp/CMakeLists.txt | 4 --- host/include/uhd/usrp/usrp_e.hpp | 54 --------------------------------- host/lib/usrp/usrp_e/CMakeLists.txt | 3 -- host/lib/usrp/usrp_e/fpga-downloader.cc | 3 +- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 16 +++++----- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 7 +++-- host/lib/usrp/usrp_e/usrp_e_none.cpp | 38 ----------------------- host/utils/CMakeLists.txt | 4 --- host/utils/usrp_e_load_fpga.cpp | 47 ---------------------------- 9 files changed, 14 insertions(+), 162 deletions(-) delete mode 100644 host/include/uhd/usrp/usrp_e.hpp delete mode 100644 host/lib/usrp/usrp_e/usrp_e_none.cpp delete mode 100644 host/utils/usrp_e_load_fpga.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index ff2636d8c..58aa8588a 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -31,10 +31,6 @@ INSTALL(FILES dboard_iface.hpp dboard_manager.hpp - ### usrp headers ### - usrp_e.hpp - usrp2.hpp - ### utilities ### tune_helper.hpp simple_usrp.hpp diff --git a/host/include/uhd/usrp/usrp_e.hpp b/host/include/uhd/usrp/usrp_e.hpp deleted file mode 100644 index 557058261..000000000 --- a/host/include/uhd/usrp/usrp_e.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_UHD_USRP_USRP_E_HPP -#define INCLUDED_UHD_USRP_USRP_E_HPP - -#include -#include - -namespace uhd{ namespace usrp{ - -/*! - * The USRP-Embedded device class. - */ -class UHD_API usrp_e : public device{ -public: - /*! - * 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 usrp_e from a device address. - * \param addr the device address - * \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_USRP_E_HPP */ diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index 568fbd132..db6d162d4 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -59,7 +59,4 @@ IF(HAVE_USRP_E_REQUIRED_HEADERS) ) ELSE(HAVE_USRP_E_REQUIRED_HEADERS) MESSAGE(STATUS " Skipping usrp-e support.") - LIBUHD_APPEND_SOURCES( - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_none.cpp - ) ENDIF(HAVE_USRP_E_REQUIRED_HEADERS) diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc index 4429786a9..ff8671e98 100644 --- a/host/lib/usrp/usrp_e/fpga-downloader.cc +++ b/host/lib/usrp/usrp_e/fpga-downloader.cc @@ -246,8 +246,7 @@ int main(int argc, char *argv[]) } */ -#include -void uhd::usrp::usrp_e::load_fpga(const std::string &bin_file){ +void 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); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index a534c74b2..76c77af15 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -27,10 +27,6 @@ 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 **********************************************************************/ @@ -41,7 +37,7 @@ static std::string abs_path(const std::string &file_path){ /*********************************************************************** * Discovery **********************************************************************/ -device_addrs_t usrp_e::find(const device_addr_t &hint){ +static device_addrs_t usrp_e_find(const device_addr_t &hint){ device_addrs_t usrp_e_addrs; //return an empty list of addresses when type is set to non-usrp-e @@ -51,7 +47,7 @@ device_addrs_t usrp_e::find(const device_addr_t &hint){ if (not hint.has_key("node")){ device_addr_t new_addr = hint; new_addr["node"] = "/dev/usrp_e0"; - return usrp_e::find(new_addr); + return usrp_e_find(new_addr); } //use the given device node name @@ -68,8 +64,12 @@ device_addrs_t usrp_e::find(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ -device::sptr usrp_e::make(const device_addr_t &device_addr){ - return sptr(new usrp_e_impl(device_addr["node"])); +static device::sptr usrp_e_make(const device_addr_t &device_addr){ + return device::sptr(new usrp_e_impl(device_addr["node"])); +} + +UHD_STATIC_BLOCK(register_usrp_e_device){ + device::register_device(&usrp_e_find, &usrp_e_make); } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 487e295cb..e6bea1358 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -18,8 +18,8 @@ #include "usrp_e_iface.hpp" #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" +#include #include -#include #include #include #include @@ -28,7 +28,10 @@ #ifndef INCLUDED_USRP_E_IMPL_HPP #define INCLUDED_USRP_E_IMPL_HPP -static const double MASTER_CLOCK_RATE = 64e6; +static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control + +//! load an fpga image from a bin file into the usrp-e fpga +extern void usrp_e_load_fpga(const std::string &bin_file); /*! * Make a usrp-e dboard interface. diff --git a/host/lib/usrp/usrp_e/usrp_e_none.cpp b/host/lib/usrp/usrp_e/usrp_e_none.cpp deleted file mode 100644 index 09a3c6946..000000000 --- a/host/lib/usrp/usrp_e/usrp_e_none.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include - -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/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index cf056e135..8d260c06c 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -19,10 +19,6 @@ 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(uhd_usrp_probe uhd_usrp_probe.cpp) TARGET_LINK_LIBRARIES(uhd_usrp_probe uhd) INSTALL(TARGETS uhd_usrp_probe RUNTIME DESTINATION ${RUNTIME_DIR}) diff --git a/host/utils/usrp_e_load_fpga.cpp b/host/utils/usrp_e_load_fpga.cpp deleted file mode 100644 index 403130b53..000000000 --- a/host/utils/usrp_e_load_fpga.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#include -#include - -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(), "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(); - uhd::usrp::usrp_e::load_fpga(file); - - return 0; -} -- cgit v1.2.3 From 416f720e56ff4542d5ba4b8c9c145f0a09bf341b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Jul 2010 03:40:25 +0000 Subject: uhd: updated code to build with latest api, not tested --- host/lib/usrp/usrp_e/io_impl.cpp | 112 ++++++++++++++++++++++------------- host/lib/usrp/usrp_e/mboard_impl.cpp | 4 +- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 4 +- 3 files changed, 74 insertions(+), 46 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index c168d6304..a77a73b38 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -24,6 +24,7 @@ #include //offsetof #include #include +#include #include using namespace uhd; @@ -127,10 +128,11 @@ private: * IO Implementation Details **********************************************************************/ struct usrp_e_impl::io_impl{ - vrt_packet_handler::recv_state recv_state; - vrt_packet_handler::send_state send_state; + //state management for the vrt packet handler code + vrt_packet_handler::recv_state packet_handler_recv_state; + vrt_packet_handler::send_state packet_handler_send_state; data_transport transport; - io_impl(int fd): transport(fd){} + io_impl(int fd): packet_handler_recv_state(1), transport(fd){} }; void usrp_e_impl::io_init(void){ @@ -150,35 +152,56 @@ void usrp_e_impl::io_init(void){ _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface->get_file_descriptor())); } -static boost::uint32_t make_stream_cmd(bool now, bool chain, boost::uint32_t nsamps){ - return (((now)? 1 : 0) << 31) | (((chain)? 1 : 0) << 30) | nsamps; +static boost::uint32_t make_stream_cmd(bool now, bool chain, bool reload, boost::uint32_t nsamps){ + return (((now)? 1 : 0) << 31) | (((chain)? 1 : 0) << 30) | (((reload)? 1 : 0) << 29) | nsamps; } void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ - boost::uint32_t cmd = 0; - switch(stream_cmd.stream_mode){ - case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE: - cmd = make_stream_cmd(stream_cmd.stream_now, false, stream_cmd.num_samps); - break; + UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff); - case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE: - cmd = make_stream_cmd(stream_cmd.stream_now, true, stream_cmd.num_samps); - break; + //setup the mode to instruction flags + typedef boost::tuple inst_t; + static const uhd::dict mode_to_inst = boost::assign::map_list_of + //reload, chain, samps + (stream_cmd_t::STREAM_MODE_START_CONTINUOUS, inst_t(true, true, false)) + (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS, inst_t(false, false, false)) + (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true)) + (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true, true)) + ; + + //setup the instruction flag values + bool inst_reload, inst_chain, inst_samps; + boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode]; + + //issue the stream command + _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, make_stream_cmd( + (inst_samps)? stream_cmd.num_samps : ((inst_chain)? get_max_recv_samps_per_packet() : 1), + (stream_cmd.stream_now)? 1 : 0, + (inst_chain)? 1 : 0, + (inst_reload)? 1 : 0 + )); + _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); + _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(MASTER_CLOCK_RATE)); - default: throw std::runtime_error("stream mode not implemented"); - } - _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, cmd); - _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, stream_cmd.time_spec.secs); - _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_ticks(MASTER_CLOCK_RATE)); } /*********************************************************************** * Data Send **********************************************************************/ +bool get_send_buffs( + data_transport *trans, + vrt_packet_handler::managed_send_buffs_t &buffs +){ + UHD_ASSERT_THROW(buffs.size() == 1); + buffs[0] = trans->get_send_buff(); + return buffs[0].get() != NULL; +} + size_t usrp_e_impl::send( - const boost::asio::const_buffer &buff, - const uhd::tx_metadata_t &metadata, - const io_type_t & io_type, + const std::vector &buffs, + size_t num_samps, + const tx_metadata_t &metadata, + const io_type_t &io_type, send_mode_t send_mode ){ otw_type_t send_otw_type; @@ -187,15 +210,13 @@ size_t usrp_e_impl::send( send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; return vrt_packet_handler::send( - _io_impl->send_state, - buff, - metadata, - send_mode, - io_type, - send_otw_type, //TODO - MASTER_CLOCK_RATE, - uhd::transport::vrt::pack_le, - boost::bind(&data_transport::get_send_buff, &_io_impl->transport), + _io_impl->packet_handler_send_state, //last state of the send handler + buffs, num_samps, //buffer to fill + metadata, send_mode, //samples metadata + io_type, send_otw_type, //input and output types to convert + MASTER_CLOCK_RATE, //master clock tick rate + uhd::transport::vrt::if_hdr_pack_le, + boost::bind(&get_send_buffs, &_io_impl->transport, _1), get_max_send_samps_per_packet(), vrt_header_offset_words32 ); @@ -204,9 +225,19 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ +bool get_recv_buffs( + data_transport *trans, + vrt_packet_handler::managed_recv_buffs_t &buffs +){ + UHD_ASSERT_THROW(buffs.size() == 1); + buffs[0] = trans->get_recv_buff(); + return buffs[0].get() != NULL; +} + size_t usrp_e_impl::recv( - const boost::asio::mutable_buffer &buff, - uhd::rx_metadata_t &metadata, + const std::vector &buffs, + size_t num_samps, + rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode ){ @@ -216,15 +247,12 @@ size_t usrp_e_impl::recv( recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; return vrt_packet_handler::recv( - _io_impl->recv_state, - buff, - metadata, - recv_mode, - io_type, - recv_otw_type, //TODO - MASTER_CLOCK_RATE, - uhd::transport::vrt::unpack_le, - boost::bind(&data_transport::get_recv_buff, &_io_impl->transport), - vrt_header_offset_words32 + _io_impl->packet_handler_recv_state, //last state of the recv handler + buffs, num_samps, //buffer to fill + metadata, recv_mode, //samples metadata + io_type, recv_otw_type, //input and output types to convert + MASTER_CLOCK_RATE, //master clock tick rate + uhd::transport::vrt::if_hdr_unpack_le, + boost::bind(get_recv_buffs, &_io_impl->transport, _1) ); } diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index e4a0e81af..e27c1964a 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -116,10 +116,10 @@ void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_TIME_NOW: case MBOARD_PROP_TIME_NEXT_PPS:{ time_spec_t time_spec = val.as(); - _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_ticks(MASTER_CLOCK_RATE)); + _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(MASTER_CLOCK_RATE)); boost::uint32_t imm_flags = (key.as() == MBOARD_PROP_TIME_NOW)? 1 : 0; _iface->poke32(UE_REG_TIME64_IMM, imm_flags); - _iface->poke32(UE_REG_TIME64_SECS, time_spec.secs); + _iface->poke32(UE_REG_TIME64_SECS, time_spec.get_full_secs()); } return; diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index e6bea1358..c0e302bd8 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -81,8 +81,8 @@ public: ~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 &, send_mode_t); - size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t); + size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t); + size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t); size_t get_max_send_samps_per_packet(void) const{return 300;} size_t get_max_recv_samps_per_packet(void) const{return 300;} -- cgit v1.2.3 From 7c2e17b549fefb5a667cf77dd7d86ed55f7ebe13 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Jul 2010 18:44:16 +0000 Subject: usrp-e: replaced stream cmd logic with common dsp type1 logic --- host/lib/usrp/usrp_e/io_impl.cpp | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index a77a73b38..9ebd55eac 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -17,6 +17,7 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" +#include "../dsp_utils.hpp" #include "../../transport/vrt_packet_handler.hpp" #include #include //read, write @@ -24,10 +25,10 @@ #include //offsetof #include #include -#include #include using namespace uhd; +using namespace uhd::usrp; /*********************************************************************** * Constants @@ -152,33 +153,9 @@ void usrp_e_impl::io_init(void){ _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface->get_file_descriptor())); } -static boost::uint32_t make_stream_cmd(bool now, bool chain, bool reload, boost::uint32_t nsamps){ - return (((now)? 1 : 0) << 31) | (((chain)? 1 : 0) << 30) | (((reload)? 1 : 0) << 29) | nsamps; -} - void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ - UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff); - - //setup the mode to instruction flags - typedef boost::tuple inst_t; - static const uhd::dict mode_to_inst = boost::assign::map_list_of - //reload, chain, samps - (stream_cmd_t::STREAM_MODE_START_CONTINUOUS, inst_t(true, true, false)) - (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS, inst_t(false, false, false)) - (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true)) - (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true, true)) - ; - - //setup the instruction flag values - bool inst_reload, inst_chain, inst_samps; - boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode]; - - //issue the stream command - _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, make_stream_cmd( - (inst_samps)? stream_cmd.num_samps : ((inst_chain)? get_max_recv_samps_per_packet() : 1), - (stream_cmd.stream_now)? 1 : 0, - (inst_chain)? 1 : 0, - (inst_reload)? 1 : 0 + _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, dsp_type1::calc_stream_cmd_word( + stream_cmd, get_max_recv_samps_per_packet() )); _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(MASTER_CLOCK_RATE)); -- cgit v1.2.3 From b285d23f5eba9b65f9baf799fee3f1389c132632 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Jul 2010 22:55:14 +0000 Subject: usrp-e: fixed send and recv logic in io impl to deal with frame length correctly --- host/lib/usrp/usrp_e/io_impl.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 9ebd55eac..8bcff1352 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -22,7 +22,6 @@ #include #include //read, write #include //transfer frame struct -#include //offsetof #include #include #include @@ -34,7 +33,7 @@ using namespace uhd::usrp; * Constants **********************************************************************/ static const size_t MAX_BUFF_SIZE = 2048; -static const size_t vrt_header_offset_words32 = offsetof(usrp_transfer_frame, buf)/sizeof(boost::uint32_t); +static const size_t vrt_header_offset_words32 = sizeof(usrp_transfer_frame)/sizeof(boost::uint32_t); static const bool usrp_e_io_impl_verbose = true; static const size_t recv_timeout_ms = 100; @@ -71,7 +70,7 @@ private: //and the send buffer commit method will set the length. const_cast( boost::asio::buffer_cast(buff) - )->len = boost::asio::buffer_size(buff); + )->len = boost::asio::buffer_size(buff) - sizeof(usrp_transfer_frame); return write( _fd, boost::asio::buffer_cast(buff), @@ -112,16 +111,16 @@ private: } //overwrite the vrt header length with the transfer frame length - size_t frame_size = boost::asio::buffer_cast(buff)->len; - boost::uint32_t *vrt_header = boost::asio::buffer_cast(buff) + vrt_header_offset_words32; - vrt_header[0] = (vrt_header[0] & ~0xffff) | ((frame_size/sizeof(boost::uint32_t)) & 0xffff); + usrp_transfer_frame *frame = boost::asio::buffer_cast(buff); + boost::uint32_t *vrt_header = reinterpret_cast(frame->buf); + vrt_header[0] = (vrt_header[0] & ~0xffff) | ((frame->len/sizeof(boost::uint32_t)) & 0xffff); - //std::cout << "len " << int(boost::asio::buffer_cast(buff)->len) << std::endl; + //std::cout << "len " << int(frame->len) << std::endl; //for (size_t i = 0; i < 7; i++){ // std::cout << boost::format(" 0x%08x") % boost::asio::buffer_cast(buff)[i] << std::endl; //} - return frame_size; + return read_ret; } }; @@ -230,6 +229,7 @@ size_t usrp_e_impl::recv( io_type, recv_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, - boost::bind(get_recv_buffs, &_io_impl->transport, _1) + boost::bind(get_recv_buffs, &_io_impl->transport, _1), + vrt_header_offset_words32 ); } -- cgit v1.2.3 From ead865c28690deb1566ce6a20f54cfb43484ad01 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 10 Jul 2010 06:13:47 +0000 Subject: usrp-e: added io_impl handle overrun --- host/lib/usrp/usrp_e/io_impl.cpp | 26 ++++++++++++++++++-------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 1 + 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 8bcff1352..d1a00bf25 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -63,7 +63,7 @@ public: private: int _fd; - size_t send(const boost::asio::const_buffer &buff){ + ssize_t send(const boost::asio::const_buffer &buff){ //Set the frame length in the frame header. //This is technically bad to write to a const buffer, //but this will go away when the ring gets implemented, @@ -77,7 +77,7 @@ private: boost::asio::buffer_size(buff) ); } - size_t recv(const boost::asio::mutable_buffer &buff){ + ssize_t recv(const boost::asio::mutable_buffer &buff){ //std::cout << boost::format( // "calling read on fd %d, buff size is %d" //) % _fd % boost::asio::buffer_size(buff) << std::endl; @@ -105,9 +105,9 @@ private: if (read_ret < ssize_t(sizeof(usrp_transfer_frame))){ if (usrp_e_io_impl_verbose) std::cerr << boost::format( "usrp-e io impl recv(): read() returned small value: %d\n" - " -> return 0 for error" + " -> return -1 for error" ) % read_ret << std::endl; - return 0; + return -1; } //overwrite the vrt header length with the transfer frame length @@ -116,7 +116,7 @@ private: vrt_header[0] = (vrt_header[0] & ~0xffff) | ((frame->len/sizeof(boost::uint32_t)) & 0xffff); //std::cout << "len " << int(frame->len) << std::endl; - //for (size_t i = 0; i < 7; i++){ + //for (size_t i = 0; i < 9; i++){ // std::cout << boost::format(" 0x%08x") % boost::asio::buffer_cast(buff)[i] << std::endl; //} @@ -132,6 +132,7 @@ struct usrp_e_impl::io_impl{ vrt_packet_handler::recv_state packet_handler_recv_state; vrt_packet_handler::send_state packet_handler_send_state; data_transport transport; + bool continuous_streaming; io_impl(int fd): packet_handler_recv_state(1), transport(fd){} }; @@ -153,12 +154,20 @@ void usrp_e_impl::io_init(void){ } void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ + _io_impl->continuous_streaming = (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS); _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, dsp_type1::calc_stream_cmd_word( stream_cmd, get_max_recv_samps_per_packet() )); _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(MASTER_CLOCK_RATE)); +} +void usrp_e_impl::handle_overrun(size_t){ + std::cerr << "O"; //the famous OOOOOOOOOOO + _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 0); + if (_io_impl->continuous_streaming){ + this->issue_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + } } /*********************************************************************** @@ -170,7 +179,7 @@ bool get_send_buffs( ){ UHD_ASSERT_THROW(buffs.size() == 1); buffs[0] = trans->get_send_buff(); - return buffs[0].get() != NULL; + return buffs[0].get(); } size_t usrp_e_impl::send( @@ -207,7 +216,7 @@ bool get_recv_buffs( ){ UHD_ASSERT_THROW(buffs.size() == 1); buffs[0] = trans->get_recv_buff(); - return buffs[0].get() != NULL; + return buffs[0].get(); } size_t usrp_e_impl::recv( @@ -229,7 +238,8 @@ size_t usrp_e_impl::recv( io_type, recv_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, - boost::bind(get_recv_buffs, &_io_impl->transport, _1), + boost::bind(&get_recv_buffs, &_io_impl->transport, _1), + boost::bind(&usrp_e_impl::handle_overrun, this, _1), vrt_header_offset_words32 ); } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index c0e302bd8..4a63a6d21 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -97,6 +97,7 @@ private: UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); + void handle_overrun(size_t); //configuration shadows uhd::clock_config_t _clock_config; -- cgit v1.2.3 From 624eb248cd5ee2343cb0f4f24f60916ea51b60fd Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 14 Jul 2010 22:17:35 +0000 Subject: Use largest possible packets for transfers. --- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 4a63a6d21..efbf9f68f 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -83,8 +83,8 @@ public: //the io interface size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t); - size_t get_max_send_samps_per_packet(void) const{return 300;} - size_t get_max_recv_samps_per_packet(void) const{return 300;} + size_t get_max_send_samps_per_packet(void) const{return 503;} + size_t get_max_recv_samps_per_packet(void) const{return 503;} private: //interface to ioctls and file descriptor -- cgit v1.2.3 From a47e75c84099081a7f7b2a13e11c3615bed22a5c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 16 Jul 2010 07:22:11 +0000 Subject: usrp-e: removed vrt header rewrite in io impl, its not in vrt packet parser stuff --- host/lib/usrp/usrp_e/io_impl.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index d1a00bf25..ecde9ca27 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -110,11 +110,7 @@ private: return -1; } - //overwrite the vrt header length with the transfer frame length - usrp_transfer_frame *frame = boost::asio::buffer_cast(buff); - boost::uint32_t *vrt_header = reinterpret_cast(frame->buf); - vrt_header[0] = (vrt_header[0] & ~0xffff) | ((frame->len/sizeof(boost::uint32_t)) & 0xffff); - + //usrp_transfer_frame *frame = boost::asio::buffer_cast(buff); //std::cout << "len " << int(frame->len) << std::endl; //for (size_t i = 0; i < 9; i++){ // std::cout << boost::format(" 0x%08x") % boost::asio::buffer_cast(buff)[i] << std::endl; -- cgit v1.2.3 From 1301d665d621358ec6eccb41a020a4689cb0b566 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 3 Aug 2010 17:57:39 -0700 Subject: usrp-e: fixed clock div calculation bug --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index df649cee6..8a5bd1c6b 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -164,7 +164,7 @@ public: void set_rx_dboard_clock_rate(double rate){ assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); - size_t divider = size_t(rate/master_clock_rate); + size_t divider = size_t(master_clock_rate/rate); //set the divider registers set_clock_divider(divider, _ad9522_regs.divider3_low_cycles, @@ -194,7 +194,7 @@ public: void set_tx_dboard_clock_rate(double rate){ assert_has(get_tx_dboard_clock_rates(), rate, "tx dboard clock rate"); - size_t divider = size_t(rate/master_clock_rate); + size_t divider = size_t(master_clock_rate/rate); //set the divider registers set_clock_divider(divider, _ad9522_regs.divider2_low_cycles, -- cgit v1.2.3 From 9e87ebda07dda14e5b0ab4c64b6adc9800358baa Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 11 Aug 2010 00:16:34 -0700 Subject: usrp-e: fixed warnings and errors, missing subdev spec stuff --- host/include/uhd/utils/pimpl.hpp | 3 +-- host/lib/usrp/usrp_e/dboard_iface.cpp | 2 ++ host/lib/usrp/usrp_e/dboard_impl.cpp | 37 +---------------------------------- host/lib/usrp/usrp_e/io_impl.cpp | 18 +++++++++++++++-- host/lib/usrp/usrp_e/usrp_e_iface.cpp | 22 ++++++++++----------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 5 ++--- 6 files changed, 33 insertions(+), 54 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/utils/pimpl.hpp b/host/include/uhd/utils/pimpl.hpp index 18454f0c4..09bf0c0a2 100644 --- a/host/include/uhd/utils/pimpl.hpp +++ b/host/include/uhd/utils/pimpl.hpp @@ -20,7 +20,6 @@ #include #include -#include /*! \file pimpl.hpp * "Pimpl idiom" (pointer to implementation idiom). @@ -51,6 +50,6 @@ * \param _args the constructor args for the pimpl */ #define UHD_PIMPL_MAKE(_name, _args) \ - boost::make_shared<_name> _args + boost::shared_ptr<_name>(new _name _args) #endif /* INCLUDED_UHD_UTILS_PIMPL_HPP */ diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index ce00cd40d..d5ec10d84 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -50,6 +50,8 @@ public: /* NOP */ } + std::string get_mboard_name(void){return "usrp-e";} + void write_aux_dac(unit_t, aux_dac_t, float); float read_aux_adc(unit_t, aux_adc_t); diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index a384c71a0..4d3f70dfe 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -51,10 +51,6 @@ void usrp_e_impl::dboard_init(void){ boost::bind(&usrp_e_impl::tx_dboard_get, this, _1, _2), boost::bind(&usrp_e_impl::tx_dboard_set, this, _1, _2) ); - - //init the subdevs in use (use the first subdevice) - rx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_rx_subdev_names().at(0))); - tx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_tx_subdev_names().at(0))); } /*********************************************************************** @@ -78,10 +74,6 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_rx_subdev_names(); return; - case DBOARD_PROP_USED_SUBDEVS: - val = _rx_subdevs_in_use; - return; - case DBOARD_PROP_DBOARD_ID: val = _rx_db_eeprom.id; return; @@ -99,18 +91,6 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ **********************************************************************/ void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as()){ - case DBOARD_PROP_USED_SUBDEVS:{ - _rx_subdevs_in_use = val.as(); - UHD_ASSERT_THROW(_rx_subdevs_in_use.size() == 1); - wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0)); - std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as() << std::endl; - _iface->poke32(UE_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( - rx_subdev[SUBDEV_PROP_QUADRATURE].as(), - rx_subdev[SUBDEV_PROP_IQ_SWAPPED].as() - )); - } - return; - case DBOARD_PROP_DBOARD_ID: _rx_db_eeprom.id = val.as(); _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes()); @@ -141,10 +121,6 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_tx_subdev_names(); return; - case DBOARD_PROP_USED_SUBDEVS: - val = _tx_subdevs_in_use; - return; - case DBOARD_PROP_DBOARD_ID: val = _tx_db_eeprom.id; return; @@ -161,18 +137,7 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ * TX Dboard Set **********************************************************************/ void usrp_e_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ - switch(key.as()){ - case DBOARD_PROP_USED_SUBDEVS:{ - _tx_subdevs_in_use = val.as(); - UHD_ASSERT_THROW(_tx_subdevs_in_use.size() == 1); - wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); - std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as() << std::endl; - _iface->poke32(UE_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( - tx_subdev[SUBDEV_PROP_IQ_SWAPPED].as() - )); - } - return; - + switch(key.as()){ case DBOARD_PROP_DBOARD_ID: _tx_db_eeprom.id = val.as(); _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes()); diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index ecde9ca27..0742c4514 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -24,6 +24,7 @@ #include //transfer frame struct #include #include +#include #include using namespace uhd; @@ -35,7 +36,6 @@ using namespace uhd::usrp; static const size_t MAX_BUFF_SIZE = 2048; static const size_t vrt_header_offset_words32 = sizeof(usrp_transfer_frame)/sizeof(boost::uint32_t); static const bool usrp_e_io_impl_verbose = true; -static const size_t recv_timeout_ms = 100; /*********************************************************************** * Data Transport (phony zero-copy with read/write) @@ -61,6 +61,8 @@ public: return 10; //FIXME no idea! } + size_t recv_timeout_ms; + private: int _fd; ssize_t send(const boost::asio::const_buffer &buff){ @@ -220,13 +222,17 @@ size_t usrp_e_impl::recv( size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode + recv_mode_t recv_mode, + size_t timeout_ms ){ otw_type_t recv_otw_type; recv_otw_type.width = 16; recv_otw_type.shift = 0; recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + //hand-off the timeout to the transport + _io_impl->transport.recv_timeout_ms = timeout_ms; + return vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler buffs, num_samps, //buffer to fill @@ -239,3 +245,11 @@ size_t usrp_e_impl::recv( vrt_header_offset_words32 ); } + +/*********************************************************************** + * Dummy Async Recv + **********************************************************************/ +bool usrp_e_impl::recv_async_msg(async_metadata_t &, size_t timeout_ms){ + boost::this_thread::sleep(boost::posix_time::milliseconds(timeout_ms)); + return false; +} diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp index 21e91452f..f00e92946 100644 --- a/host/lib/usrp/usrp_e/usrp_e_iface.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_iface.cpp @@ -123,13 +123,13 @@ public: boost::uint8_t mem[sizeof(usrp_e_i2c) + max_i2c_data_bytes]; //load the data struct - usrp_e_i2c &data = reinterpret_cast(mem); - data.addr = addr; - data.len = bytes.size(); - std::copy(bytes.begin(), bytes.end(), data.data); + usrp_e_i2c *data = reinterpret_cast(mem); + data->addr = addr; + data->len = bytes.size(); + std::copy(bytes.begin(), bytes.end(), data->data); //call the spi ioctl - this->ioctl(USRP_E_I2C_WRITE, &data); + this->ioctl(USRP_E_I2C_WRITE, data); } byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ @@ -138,17 +138,17 @@ public: boost::uint8_t mem[sizeof(usrp_e_i2c) + max_i2c_data_bytes]; //load the data struct - usrp_e_i2c &data = reinterpret_cast(mem); - data.addr = addr; - data.len = num_bytes; + usrp_e_i2c *data = reinterpret_cast(mem); + data->addr = addr; + data->len = num_bytes; //call the spi ioctl - this->ioctl(USRP_E_I2C_READ, &data); + this->ioctl(USRP_E_I2C_READ, data); //unload the data - byte_vector_t bytes(data.len); + byte_vector_t bytes(data->len); UHD_ASSERT_THROW(bytes.size() == num_bytes); - std::copy(data.data, data.data+bytes.size(), bytes.begin()); + std::copy(data->data, data->data+bytes.size(), bytes.begin()); return bytes; } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index efbf9f68f..4bbe100c1 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -82,7 +82,8 @@ public: //the io interface size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t); - size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t); + size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, size_t); + bool recv_async_msg(uhd::async_metadata_t &, size_t); size_t get_max_send_samps_per_packet(void) const{return 503;} size_t get_max_recv_samps_per_packet(void) const{return 503;} @@ -128,14 +129,12 @@ private: uhd::usrp::dboard_eeprom_t _rx_db_eeprom; void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); - uhd::prop_names_t _rx_subdevs_in_use; wax_obj_proxy::sptr _rx_dboard_proxy; //tx dboard functions and settings uhd::usrp::dboard_eeprom_t _tx_db_eeprom; void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); - uhd::prop_names_t _tx_subdevs_in_use; wax_obj_proxy::sptr _tx_dboard_proxy; //rx ddc functions and settings -- cgit v1.2.3 From 3f25b6fee4a7788ffea0224cb79bb6334b621992 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 11 Aug 2010 12:32:57 -0700 Subject: usrp-e: filled in properties and logic for subdev spec --- host/lib/usrp/usrp_e/dboard_impl.cpp | 1 - host/lib/usrp/usrp_e/mboard_impl.cpp | 36 ++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp_e/usrp_e_impl.hpp | 2 ++ 3 files changed, 38 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 4d3f70dfe..809b6f06b 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -17,7 +17,6 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" -#include "../dsp_utils.hpp" #include #include #include diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index e27c1964a..822f1571d 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -17,6 +17,8 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" +#include "../dsp_utils.hpp" +#include "../misc_utils.hpp" #include #include #include @@ -38,6 +40,10 @@ void usrp_e_impl::mboard_init(void){ _clock_config.pps_source = clock_config_t::PPS_SMA; //TODO poke the clock config regs + + //set default subdev specs + this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t()); + this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t()); } /*********************************************************************** @@ -98,6 +104,14 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = _clock_config; return; + case MBOARD_PROP_RX_SUBDEV_SPEC: + val = _rx_subdev_spec; + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + val = _tx_subdev_spec; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -123,6 +137,28 @@ void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ } return; + case MBOARD_PROP_RX_SUBDEV_SPEC: + _rx_subdev_spec = val.as(); + verify_rx_subdev_spec(_rx_subdev_spec, this->get_link()); + //sanity check + UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); + //set the mux + _iface->poke32(UE_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( + _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as() + )); + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + _tx_subdev_spec = val.as(); + verify_tx_subdev_spec(_tx_subdev_spec, this->get_link()); + //sanity check + UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); + //set the mux + _iface->poke32(UE_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( + _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as() + )); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 4bbe100c1..e3249e9de 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -20,6 +20,7 @@ #include "codec_ctrl.hpp" #include #include +#include #include #include #include @@ -119,6 +120,7 @@ private: void mboard_get(const wax::obj &, wax::obj &); void mboard_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _mboard_proxy; + uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; //xx dboard functions and settings void dboard_init(void); -- cgit v1.2.3 From 8e5040a9ec0639bc7b110ba96e256c48e5a62df7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 11 Aug 2010 15:33:12 -0700 Subject: usrp-e: removed transfer frameness --- host/lib/usrp/usrp_e/io_impl.cpp | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 0742c4514..bbc3f5215 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -21,7 +21,6 @@ #include "../../transport/vrt_packet_handler.hpp" #include #include //read, write -#include //transfer frame struct #include #include #include @@ -34,7 +33,6 @@ using namespace uhd::usrp; * Constants **********************************************************************/ static const size_t MAX_BUFF_SIZE = 2048; -static const size_t vrt_header_offset_words32 = sizeof(usrp_transfer_frame)/sizeof(boost::uint32_t); static const bool usrp_e_io_impl_verbose = true; /*********************************************************************** @@ -66,15 +64,7 @@ public: private: int _fd; ssize_t send(const boost::asio::const_buffer &buff){ - //Set the frame length in the frame header. - //This is technically bad to write to a const buffer, - //but this will go away when the ring gets implemented, - //and the send buffer commit method will set the length. - const_cast( - boost::asio::buffer_cast(buff) - )->len = boost::asio::buffer_size(buff) - sizeof(usrp_transfer_frame); - return write( - _fd, + return write(_fd, boost::asio::buffer_cast(buff), boost::asio::buffer_size(buff) ); @@ -99,12 +89,11 @@ private: } //perform the blocking read(...) - ssize_t read_ret = read( - _fd, + ssize_t read_ret = read(_fd, boost::asio::buffer_cast(buff), boost::asio::buffer_size(buff) ); - if (read_ret < ssize_t(sizeof(usrp_transfer_frame))){ + if (read_ret < 0){ if (usrp_e_io_impl_verbose) std::cerr << boost::format( "usrp-e io impl recv(): read() returned small value: %d\n" " -> return -1 for error" @@ -112,8 +101,7 @@ private: return -1; } - //usrp_transfer_frame *frame = boost::asio::buffer_cast(buff); - //std::cout << "len " << int(frame->len) << std::endl; + //std::cout << "len " << int(read_ret) << std::endl; //for (size_t i = 0; i < 9; i++){ // std::cout << boost::format(" 0x%08x") % boost::asio::buffer_cast(buff)[i] << std::endl; //} @@ -200,8 +188,7 @@ size_t usrp_e_impl::send( MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, boost::bind(&get_send_buffs, &_io_impl->transport, _1), - get_max_send_samps_per_packet(), - vrt_header_offset_words32 + get_max_send_samps_per_packet() ); } @@ -241,8 +228,7 @@ size_t usrp_e_impl::recv( MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, boost::bind(&get_recv_buffs, &_io_impl->transport, _1), - boost::bind(&usrp_e_impl::handle_overrun, this, _1), - vrt_header_offset_words32 + boost::bind(&usrp_e_impl::handle_overrun, this, _1) ); } -- cgit v1.2.3 From 68a65581db6455bfd4652576eeb6795e3c1ca68b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 12 Aug 2010 18:17:37 +0000 Subject: usrp-e: fix typo in verify subdev spec --- host/lib/usrp/usrp_e/mboard_impl.cpp | 4 ++-- host/utils/uhd_find_devices.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 822f1571d..4914bd3b7 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -139,7 +139,7 @@ void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_RX_SUBDEV_SPEC: _rx_subdev_spec = val.as(); - verify_rx_subdev_spec(_rx_subdev_spec, this->get_link()); + verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link()); //sanity check UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); //set the mux @@ -150,7 +150,7 @@ void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_TX_SUBDEV_SPEC: _tx_subdev_spec = val.as(); - verify_tx_subdev_spec(_tx_subdev_spec, this->get_link()); + verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link()); //sanity check UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); //set the mux diff --git a/host/utils/uhd_find_devices.cpp b/host/utils/uhd_find_devices.cpp index 8281c92bc..b778eeb68 100644 --- a/host/utils/uhd_find_devices.cpp +++ b/host/utils/uhd_find_devices.cpp @@ -53,7 +53,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << "-- UHD Device " << i << std::endl; std::cout << "--------------------------------------------------" << std::endl; std::cout << device_addrs[i].to_pp_string() << std::endl << std::endl; - uhd::device::make(device_addrs[i]); //test make + //uhd::device::make(device_addrs[i]); //test make } return 0; -- cgit v1.2.3 From 8c676eeb973593caecb7270a6106e8592f73a352 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 12 Aug 2010 21:28:26 +0000 Subject: usrp-e: added codec impl, probe works --- host/lib/usrp/usrp_e/CMakeLists.txt | 1 + host/lib/usrp/usrp_e/codec_impl.cpp | 96 ++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp_e/dboard_impl.cpp | 8 +++ host/lib/usrp/usrp_e/mboard_impl.cpp | 5 +- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 8 +++ host/lib/usrp/usrp_e/usrp_e_impl.hpp | 8 +++ 6 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 host/lib/usrp/usrp_e/codec_impl.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index 1d64d29d2..f0c125f26 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -32,6 +32,7 @@ IF(HAVE_LINUX_USRP_E_H) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/clock_ctrl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_ctrl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_ctrl.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dsp_impl.cpp diff --git a/host/lib/usrp/usrp_e/codec_impl.cpp b/host/lib/usrp/usrp_e/codec_impl.cpp new file mode 100644 index 000000000..51f7b02b8 --- /dev/null +++ b/host/lib/usrp/usrp_e/codec_impl.cpp @@ -0,0 +1,96 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Helper Methods + **********************************************************************/ +void usrp_e_impl::codec_init(void){ + //make proxies + _rx_codec_proxy = wax_obj_proxy::make( + boost::bind(&usrp_e_impl::rx_codec_get, this, _1, _2), + boost::bind(&usrp_e_impl::rx_codec_set, this, _1, _2) + ); + _tx_codec_proxy = wax_obj_proxy::make( + boost::bind(&usrp_e_impl::tx_codec_get, this, _1, _2), + boost::bind(&usrp_e_impl::tx_codec_set, this, _1, _2) + ); +} + +/*********************************************************************** + * RX Codec Properties + **********************************************************************/ +void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case CODEC_PROP_NAME: + val = std::string("usrp-e adc - ad9522"); + return; + + case CODEC_PROP_OTHERS: + val = prop_names_t(); + return; + + case CODEC_PROP_GAIN_NAMES: + val = prop_names_t(); //no gain elements to be controlled + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void usrp_e_impl::rx_codec_set(const wax::obj &, const wax::obj &){ + UHD_THROW_PROP_SET_ERROR(); +} + +/*********************************************************************** + * TX Codec Properties + **********************************************************************/ +void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case CODEC_PROP_NAME: + val = std::string("usrp-e dac - ad9522"); + return; + + case CODEC_PROP_OTHERS: + val = prop_names_t(); + return; + + case CODEC_PROP_GAIN_NAMES: + val = prop_names_t(); //no gain elements to be controlled + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void usrp_e_impl::tx_codec_set(const wax::obj &, const wax::obj &){ + UHD_THROW_PROP_SET_ERROR(); +} diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 809b6f06b..8aaf16c51 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -81,6 +81,10 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_iface; return; + case DBOARD_PROP_CODEC: + val = _rx_codec_proxy->get_link(); + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -128,6 +132,10 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_iface; return; + case DBOARD_PROP_CODEC: + val = _tx_codec_proxy->get_link(); + return; + default: UHD_THROW_PROP_GET_ERROR(); } } diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 4914bd3b7..88e16a6f5 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -40,10 +41,6 @@ void usrp_e_impl::mboard_init(void){ _clock_config.pps_source = clock_config_t::PPS_SMA; //TODO poke the clock config regs - - //set default subdev specs - this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t()); - this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t()); } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 76c77af15..0566cfd59 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -17,6 +17,7 @@ #include "usrp_e_impl.hpp" #include +#include #include #include #include @@ -93,8 +94,15 @@ usrp_e_impl::usrp_e_impl(const std::string &node){ rx_ddc_init(); tx_duc_init(); + //init the codec properties + codec_init(); + //init the io send/recv io_init(); + + //set default subdev specs + this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t()); + this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t()); } usrp_e_impl::~usrp_e_impl(void){ diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index e3249e9de..2457e27cc 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -152,6 +152,14 @@ private: void tx_duc_set(const wax::obj &, const wax::obj &); double _duc_freq; size_t _duc_interp; wax_obj_proxy::sptr _tx_duc_proxy; + + //codec functions and settings + void codec_init(void); + void rx_codec_get(const wax::obj &, wax::obj &); + void rx_codec_set(const wax::obj &, const wax::obj &); + void tx_codec_get(const wax::obj &, wax::obj &); + void tx_codec_set(const wax::obj &, const wax::obj &); + wax_obj_proxy::sptr _rx_codec_proxy, _tx_codec_proxy; }; #endif /* INCLUDED_USRP_E_IMPL_HPP */ -- cgit v1.2.3 From ac85d2b38c26fd6d31ba0a997d033b159d51769d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 13 Aug 2010 01:09:45 +0000 Subject: usrp-e: codec gain control from properties interface --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 1 - host/lib/usrp/usrp_e/codec_ctrl.cpp | 48 ++++++++++++++++++++++++++ host/lib/usrp/usrp_e/codec_ctrl.hpp | 19 ++++++++-- host/lib/usrp/usrp_e/codec_impl.cpp | 69 +++++++++++++++++++++++++++++++++---- 4 files changed, 128 insertions(+), 9 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 8a5bd1c6b..b53e880a2 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -60,7 +60,6 @@ class usrp_e_clock_ctrl_impl : public usrp_e_clock_ctrl{ public: usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ _iface = iface; - std::cout << "master_clock_rate: " << (master_clock_rate/1e6) << " MHz" << std::endl; //init the clock gen registers //Note: out0 should already be clocking the FPGA or this isnt going to work diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index ac61bc6b4..5322f94bd 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -31,6 +31,9 @@ using namespace uhd; static const bool codec_debug = false; +const gain_range_t usrp_e_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); +const gain_range_t usrp_e_codec_ctrl::rx_pga_gain_range(0, 20, 1); + /*********************************************************************** * Codec Control Implementation **********************************************************************/ @@ -44,6 +47,12 @@ public: float read_aux_adc(aux_adc_t which); void write_aux_dac(aux_dac_t which, float volts); + //pga gain control + void set_tx_pga_gain(float); + float get_tx_pga_gain(void); + void set_rx_pga_gain(float, char); + float get_rx_pga_gain(char); + private: usrp_e_iface::sptr _iface; ad9862_regs_t _ad9862_regs; @@ -119,6 +128,45 @@ usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ this->send_reg(8); } +/*********************************************************************** + * Codec Control Gain Control Methods + **********************************************************************/ +void usrp_e_codec_ctrl_impl::set_tx_pga_gain(float gain){ + int gain_word = int(63*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); + _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 63); + this->send_reg(16); +} + +float usrp_e_codec_ctrl_impl::get_tx_pga_gain(void){ + return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/63) + tx_pga_gain_range.min; +} + +void usrp_e_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){ + int gain_word = int(0x14*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min)); + gain_word = std::clip(gain_word, 0, 0x14); + switch(which){ + case 'A': + _ad9862_regs.rx_pga_a = gain_word; + this->send_reg(2); + return; + case 'B': + _ad9862_regs.rx_pga_b = gain_word; + this->send_reg(3); + return; + default: UHD_THROW_INVALID_CODE_PATH(); + } +} + +float usrp_e_codec_ctrl_impl::get_rx_pga_gain(char which){ + int gain_word; + switch(which){ + case 'A': gain_word = _ad9862_regs.rx_pga_a; break; + case 'B': gain_word = _ad9862_regs.rx_pga_b; break; + default: UHD_THROW_INVALID_CODE_PATH(); + } + return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/0x14) + rx_pga_gain_range.min; +} + /*********************************************************************** * Codec Control AUX ADC Methods **********************************************************************/ diff --git a/host/lib/usrp/usrp_e/codec_ctrl.hpp b/host/lib/usrp/usrp_e/codec_ctrl.hpp index b9005a82d..87b6ff951 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.hpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.hpp @@ -19,6 +19,7 @@ #define INCLUDED_USRP_E_CODEC_CTRL_HPP #include "usrp_e_iface.hpp" +#include #include #include @@ -31,10 +32,13 @@ class usrp_e_codec_ctrl : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + static const uhd::gain_range_t tx_pga_gain_range; + static const uhd::gain_range_t rx_pga_gain_range; + /*! - * Make a new clock control object. + * Make a new codec control object. * \param iface the usrp_e iface object - * \return the clock control object + * \return the codec control object */ static sptr make(usrp_e_iface::sptr iface); @@ -70,6 +74,17 @@ public: */ virtual void write_aux_dac(aux_dac_t which, float volts) = 0; + //! Set the TX PGA gain + virtual void set_tx_pga_gain(float gain) = 0; + + //! Get the TX PGA gain + virtual float get_tx_pga_gain(void) = 0; + + //! Set the RX PGA gain ('A' or 'B') + virtual void set_rx_pga_gain(float gain, char which) = 0; + + //! Get the RX PGA gain ('A' or 'B') + virtual float get_rx_pga_gain(char which) = 0; }; #endif /* INCLUDED_USRP_E_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e/codec_impl.cpp b/host/lib/usrp/usrp_e/codec_impl.cpp index 51f7b02b8..84f8bd37f 100644 --- a/host/lib/usrp/usrp_e/codec_impl.cpp +++ b/host/lib/usrp/usrp_e/codec_impl.cpp @@ -16,6 +16,7 @@ // #include "usrp_e_impl.hpp" +#include #include #include @@ -40,6 +41,8 @@ void usrp_e_impl::codec_init(void){ /*********************************************************************** * RX Codec Properties **********************************************************************/ +static const std::string ad9862_pga_gain_name = "ad9862 pga"; + void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ wax::obj key; std::string name; boost::tie(key, name) = extract_named_prop(key_); @@ -55,15 +58,46 @@ void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(); //no gain elements to be controlled + val = prop_names_t(1, ad9862_pga_gain_name); + return; + + case CODEC_PROP_GAIN_RANGE: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + val = usrp_e_codec_ctrl::rx_pga_gain_range; + return; + + case CODEC_PROP_GAIN_I: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + val = _codec_ctrl->get_rx_pga_gain('A'); + return; + + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + val = _codec_ctrl->get_rx_pga_gain('B'); return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp_e_impl::rx_codec_set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); +void usrp_e_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the set request conditioned on the key + switch(key.as()){ + case CODEC_PROP_GAIN_I: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + _codec_ctrl->set_rx_pga_gain(val.as(), 'A'); + return; + + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + _codec_ctrl->set_rx_pga_gain(val.as(), 'B'); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } /*********************************************************************** @@ -84,13 +118,36 @@ void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(); //no gain elements to be controlled + val = prop_names_t(1, ad9862_pga_gain_name); + return; + + case CODEC_PROP_GAIN_RANGE: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + val = usrp_e_codec_ctrl::tx_pga_gain_range; + return; + + case CODEC_PROP_GAIN_I: //only one gain for I and Q + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + val = _codec_ctrl->get_tx_pga_gain(); return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp_e_impl::tx_codec_set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); +void usrp_e_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the set request conditioned on the key + switch(key.as()){ + case CODEC_PROP_GAIN_I: //only one gain for I and Q + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + _codec_ctrl->set_tx_pga_gain(val.as()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } -- cgit v1.2.3 From a340b9fb5ffe0e43a746ce8ce051b08444a1a713 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 13 Aug 2010 19:30:32 +0000 Subject: usrp-e: clock settings, ref doubler, disable test clock, lower cp current --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index b53e880a2..22578a933 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -38,11 +38,13 @@ template static void set_clock_divider /*********************************************************************** * Constants **********************************************************************/ -static const double ref_clock_rate = 10e6; +static const bool enable_test_clock = false; +static const double ref_clock_doubler = 2; //enabled below +static const double ref_clock_rate = 10e6 * ref_clock_doubler; static const size_t r_counter = 1; static const size_t a_counter = 0; -static const size_t b_counter = 20; +static const size_t b_counter = 20 / ref_clock_doubler; static const size_t prescaler = 8; //set below with enum, set to 8 when input is under 2400 MHz static const size_t vco_divider = 1; //set below with enum @@ -64,6 +66,7 @@ public: //init the clock gen registers //Note: out0 should already be clocking the FPGA or this isnt going to work _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; + _ad9522_regs.enable_clock_doubler = 1; //enable ref clock doubler _ad9522_regs.enb_stat_eeprom_at_stat_pin = 0; //use status pin _ad9522_regs.status_pin_control = 0x1; //n divider _ad9522_regs.ld_pin_control = 0x00; //dld @@ -79,7 +82,7 @@ public: _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; - _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_3_0MA; + _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; _ad9522_regs.vco_calibration_now = 1; //calibrate it! _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV1; @@ -103,7 +106,7 @@ public: //setup test clock (same divider as codec clock) _ad9522_regs.out4_format = ad9522_regs_t::OUT4_FORMAT_CMOS; - _ad9522_regs.out4_cmos_configuration = (true)? + _ad9522_regs.out4_cmos_configuration = (enable_test_clock)? ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; -- cgit v1.2.3 From 1b47702245f0c1f4dda3e0eff487bbe664d48855 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 17 Aug 2010 17:16:31 +0000 Subject: usrp-e: misc code tweaks --- host/examples/tx_timed_samples.cpp | 2 +- host/lib/usrp/usrp_e/clock_ctrl.cpp | 2 +- host/lib/usrp/usrp_e/codec_ctrl.cpp | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index ceae58a22..aa22d3465 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -77,7 +77,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ sdev->set_time_now(uhd::time_spec_t(0.0)); //allocate data to send - std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); + std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); uhd::tx_metadata_t md; //send the data in multiple packets diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 22578a933..62807aec2 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -39,7 +39,7 @@ template static void set_clock_divider * Constants **********************************************************************/ static const bool enable_test_clock = false; -static const double ref_clock_doubler = 2; //enabled below +static const size_t ref_clock_doubler = 2; //enabled below static const double ref_clock_rate = 10e6 * ref_clock_doubler; static const size_t r_counter = 1; diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index 5322f94bd..2bdbc0f1c 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -97,6 +97,7 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; _ad9862_regs.dac_a_coarse_gain = 0x3; _ad9862_regs.dac_b_coarse_gain = 0x3; + _ad9862_regs.edges = ad9862_regs_t::EDGES_BOTH; //setup the dll _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL; -- cgit v1.2.3 From 1e28ae518de1268efa370eb8b4b206b7d5a49b03 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 17 Aug 2010 19:23:56 +0000 Subject: usrp-e: building off of next branch --- host/config/Version.cmake | 2 +- host/lib/usrp/usrp_e/clock_ctrl.cpp | 3 ++- host/lib/usrp/usrp_e/codec_impl.cpp | 28 ++++++++++++---------------- host/lib/usrp/usrp_e/dboard_iface.cpp | 7 ++++++- host/lib/usrp/usrp_e/dboard_impl.cpp | 10 ++++------ host/lib/usrp/usrp_e/dsp_impl.cpp | 3 ++- host/lib/usrp/usrp_e/io_impl.cpp | 2 +- host/lib/usrp/usrp_e/mboard_impl.cpp | 16 +++++++--------- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 5 ++--- 9 files changed, 37 insertions(+), 39 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/config/Version.cmake b/host/config/Version.cmake index a592a4565..9e4b6b306 100644 --- a/host/config/Version.cmake +++ b/host/config/Version.cmake @@ -42,7 +42,7 @@ ELSE(${GIT} STREQUAL "GIT-NOTFOUND") #extract the timestamp from the git log entry EXECUTE_PROCESS( WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMAND ${PYTHON_EXECUTABLE} -c "import re; print re.match('^.*Date:\\s*(\\d*).*$', '''${_git_log}''', re.MULTILINE | re.DOTALL).groups()[0]" + COMMAND ${PYTHON_EXECUTABLE} -c "import re; print re.match('^.*Date:\\s*(\\d*).*$', ''' ${_git_log} ''', re.MULTILINE | re.DOTALL).groups()[0]" OUTPUT_VARIABLE _git_timestamp OUTPUT_STRIP_TRAILING_WHITESPACE ) diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 62807aec2..10f263e1d 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -160,7 +160,8 @@ public: std::vector get_rx_dboard_clock_rates(void){ std::vector rates; - for(size_t div = 1; div <= 16+16; div++) rates.push_back(master_clock_rate/div); + for(size_t div = 2/*vco div == 1*/; div <= 16+16; div++) + rates.push_back(master_clock_rate/div); return rates; } diff --git a/host/lib/usrp/usrp_e/codec_impl.cpp b/host/lib/usrp/usrp_e/codec_impl.cpp index 84f8bd37f..696fb37ec 100644 --- a/host/lib/usrp/usrp_e/codec_impl.cpp +++ b/host/lib/usrp/usrp_e/codec_impl.cpp @@ -44,8 +44,7 @@ void usrp_e_impl::codec_init(void){ static const std::string ad9862_pga_gain_name = "ad9862 pga"; void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ @@ -62,17 +61,17 @@ void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); val = usrp_e_codec_ctrl::rx_pga_gain_range; return; case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); val = _codec_ctrl->get_rx_pga_gain('A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); val = _codec_ctrl->get_rx_pga_gain('B'); return; @@ -81,18 +80,17 @@ void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ } void usrp_e_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); + named_prop_t key = named_prop_t::extract(key_); //handle the set request conditioned on the key switch(key.as()){ case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); _codec_ctrl->set_rx_pga_gain(val.as(), 'A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); _codec_ctrl->set_rx_pga_gain(val.as(), 'B'); return; @@ -104,8 +102,7 @@ void usrp_e_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ * TX Codec Properties **********************************************************************/ void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ @@ -122,13 +119,13 @@ void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); val = usrp_e_codec_ctrl::tx_pga_gain_range; return; case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); val = _codec_ctrl->get_tx_pga_gain(); return; @@ -137,14 +134,13 @@ void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ } void usrp_e_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); + named_prop_t key = named_prop_t::extract(key_); //handle the set request conditioned on the key switch(key.as()){ case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); _codec_ctrl->set_tx_pga_gain(val.as()); return; diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index d5ec10d84..a9831ebc4 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -50,7 +50,12 @@ public: /* NOP */ } - std::string get_mboard_name(void){return "usrp-e";} + special_props_t get_special_props(void){ + special_props_t props; + props.soft_clock_divider = false; + props.mangle_i2c_addrs = false; + return props; + } void write_aux_dac(unit_t, aux_dac_t, float); float read_aux_adc(unit_t, aux_adc_t); diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 8aaf16c51..79ff54c9d 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -56,8 +56,7 @@ void usrp_e_impl::dboard_init(void){ * RX Dboard Get **********************************************************************/ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ @@ -66,7 +65,7 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ return; case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_rx_subdev(name); + val = _dboard_manager->get_rx_subdev(key.name); return; case DBOARD_PROP_SUBDEV_NAMES: @@ -107,8 +106,7 @@ void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ * TX Dboard Get **********************************************************************/ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ @@ -117,7 +115,7 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ return; case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_tx_subdev(name); + val = _dboard_manager->get_tx_subdev(key.name); return; case DBOARD_PROP_SUBDEV_NAMES: diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index 58a58706d..c133eafae 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -17,8 +17,9 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" -#include "../dsp_utils.hpp" +#include #include +#include #include #define rint boost::math::iround diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index bbc3f5215..eaa45d60c 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -17,7 +17,7 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" -#include "../dsp_utils.hpp" +#include #include "../../transport/vrt_packet_handler.hpp" #include #include //read, write diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 88e16a6f5..3d4cef069 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -17,8 +17,8 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" -#include "../dsp_utils.hpp" -#include "../misc_utils.hpp" +#include +#include #include #include #include @@ -47,9 +47,7 @@ void usrp_e_impl::mboard_init(void){ * 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_); - + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ @@ -62,7 +60,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DBOARD: - UHD_ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(key.name == ""); val = _rx_dboard_proxy->get_link(); return; @@ -71,7 +69,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DBOARD: - UHD_ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(key.name == ""); val = _tx_dboard_proxy->get_link(); return; @@ -80,7 +78,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DSP: - UHD_ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(key.name == ""); val = _rx_ddc_proxy->get_link(); return; @@ -89,7 +87,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DSP: - UHD_ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(key.name == ""); val = _tx_duc_proxy->get_link(); return; diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 0566cfd59..5c0e1dbb0 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -113,8 +113,7 @@ usrp_e_impl::~usrp_e_impl(void){ * 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_); + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ @@ -123,7 +122,7 @@ void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MBOARD: - UHD_ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(key.name == ""); val = _mboard_proxy->get_link(); return; -- cgit v1.2.3 From e48dfb211609e26230c2e7c165ad3aa5d5b0ecfc Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Tue, 17 Aug 2010 23:39:36 +0000 Subject: Fix to create 90 phase shift on TX. --- host/lib/usrp/usrp_e/codec_ctrl.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index 2bdbc0f1c..45063894e 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -89,6 +89,7 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ //setup tx side of codec _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH; _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; + _ad9862_regs.tx_retime = ad9862_regs_t::TX_RETIME_CLKOUT2; _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; _ad9862_regs.interp = ad9862_regs_t::INTERP_2; -- cgit v1.2.3 From f7fab232e5b6124b0bda821736ac309ccc0cab94 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 18 Aug 2010 00:41:41 +0000 Subject: Really fix TX IQ phase offset. --- host/lib/usrp/usrp_e/codec_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index 45063894e..837219759 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -29,7 +29,7 @@ using namespace uhd; -static const bool codec_debug = false; +static const bool codec_debug = true; const gain_range_t usrp_e_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); const gain_range_t usrp_e_codec_ctrl::rx_pga_gain_range(0, 20, 1); @@ -98,7 +98,7 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; _ad9862_regs.dac_a_coarse_gain = 0x3; _ad9862_regs.dac_b_coarse_gain = 0x3; - _ad9862_regs.edges = ad9862_regs_t::EDGES_BOTH; + _ad9862_regs.edges = ad9862_regs_t::EDGES_NORMAL; //setup the dll _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL; -- cgit v1.2.3 From c3fc2010bffbb74414c029910347c6aa28c2b8d4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 18 Aug 2010 00:53:58 +0000 Subject: usrp-e: added gain group property --- host/lib/usrp/usrp_e/dboard_iface.cpp | 5 ++++- host/lib/usrp/usrp_e/dboard_impl.cpp | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index a9831ebc4..c9efd0c9e 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -44,6 +44,9 @@ public: //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); + + _iface->poke16(UE_REG_GPIO_RX_DBG, 0); + _iface->poke16(UE_REG_GPIO_TX_DBG, 0); } ~usrp_e_dboard_iface(void){ @@ -165,8 +168,8 @@ boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t unit){ switch(unit){ case UNIT_RX: return _iface->peek16(UE_REG_GPIO_RX_IO); case UNIT_TX: return _iface->peek16(UE_REG_GPIO_TX_IO); + default: UHD_THROW_INVALID_CODE_PATH(); } - UHD_ASSERT_THROW(false); } void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index 79ff54c9d..d4a27cb72 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -84,6 +85,14 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _rx_codec_proxy->get_link(); return; + case DBOARD_PROP_GAIN_GROUP: + val = make_gain_group( + _dboard_manager->get_rx_subdev(key.name), + _rx_codec_proxy->get_link(), + GAIN_GROUP_POLICY_RX + ); + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -134,6 +143,14 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _tx_codec_proxy->get_link(); return; + case DBOARD_PROP_GAIN_GROUP: + val = make_gain_group( + _dboard_manager->get_tx_subdev(key.name), + _tx_codec_proxy->get_link(), + GAIN_GROUP_POLICY_TX + ); + return; + default: UHD_THROW_PROP_GET_ERROR(); } } -- cgit v1.2.3 From 6be4654073523d0666be552eee28445eb5f72297 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 19 Aug 2010 22:23:01 +0000 Subject: Change clock dividers so DBSRX board locks. --- host/lib/usrp/usrp_e/clock_ctrl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 10f263e1d..9d4625305 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -46,7 +46,7 @@ static const size_t r_counter = 1; static const size_t a_counter = 0; static const size_t b_counter = 20 / ref_clock_doubler; static const size_t prescaler = 8; //set below with enum, set to 8 when input is under 2400 MHz -static const size_t vco_divider = 1; //set below with enum +static const size_t vco_divider = 5; //set below with enum static const size_t n_counter = prescaler * b_counter + a_counter; static const size_t vco_clock_rate = ref_clock_rate/r_counter * n_counter; //between 1400 and 1800 MHz @@ -85,7 +85,7 @@ public: _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; _ad9522_regs.vco_calibration_now = 1; //calibrate it! - _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV1; + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; //setup fpga master clock @@ -160,7 +160,7 @@ public: std::vector get_rx_dboard_clock_rates(void){ std::vector rates; - for(size_t div = 2/*vco div == 1*/; div <= 16+16; div++) + for(size_t div = 1; div <= 16+16; div++) rates.push_back(master_clock_rate/div); return rates; } -- cgit v1.2.3 From ee20f8eb4f64d3fd8c34ef9cde5d125bd5a14816 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 18 Aug 2010 23:59:58 +0000 Subject: Change TX PGA gain scaling to match gnuradio scaling --- host/lib/usrp/usrp_e/codec_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index 837219759..17262d358 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -134,8 +134,8 @@ usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ * Codec Control Gain Control Methods **********************************************************************/ void usrp_e_codec_ctrl_impl::set_tx_pga_gain(float gain){ - int gain_word = int(63*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); - _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 63); + int gain_word = int(255*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); + _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 255); this->send_reg(16); } -- cgit v1.2.3 From d3501cda50407143db85f7ea5eb894c71ecd8aac Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 24 Aug 2010 18:11:46 +0000 Subject: usrp-e: added dboard iface set gpio debug call --- host/lib/usrp/usrp_e/dboard_iface.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index c9efd0c9e..1bd177f60 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -67,6 +67,7 @@ public: void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); void set_gpio_ddr(unit_t, boost::uint16_t); void write_gpio(unit_t, boost::uint16_t); + void set_gpio_debug(unit_t, int); boost::uint16_t read_gpio(unit_t); void write_i2c(boost::uint8_t, const byte_vector_t &); @@ -193,6 +194,29 @@ void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_ _iface->poke16(unit_to_atr_to_addr[unit][atr], value); } +void usrp_e_dboard_iface::set_gpio_debug(unit_t unit, int which){ + //set this unit to all outputs + this->set_gpio_ddr(unit, 0xffff); + + //calculate the debug selections + boost::uint32_t dbg_sels = 0x0; + int sel = (which == 0)? GPIO_SEL_DEBUG_0 : GPIO_SEL_DEBUG_1; + for(size_t i = 0; i < 16; i++) dbg_sels |= sel << i; + + //set the debug on and which debug selection + switch(unit){ + case UNIT_RX: + _iface->poke16(UE_REG_GPIO_RX_DBG, 0xffff); + _iface->poke16(UE_REG_GPIO_RX_SEL, dbg_sels); + return; + + case UNIT_TX: + _iface->poke16(UE_REG_GPIO_TX_DBG, 0xffff); + _iface->poke16(UE_REG_GPIO_TX_SEL, dbg_sels); + return; + } +} + /*********************************************************************** * SPI **********************************************************************/ -- cgit v1.2.3 From 65821027b8d41e9c736bc7e29a4fa1f84dc890ba Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 24 Aug 2010 19:26:15 +0000 Subject: usrp-e: fixed codec control gain calculation error, added tx policy registers, set to next packet --- host/lib/usrp/usrp_e/codec_ctrl.cpp | 18 +++++++++++------- host/lib/usrp/usrp_e/io_impl.cpp | 2 +- host/lib/usrp/usrp_e/mboard_impl.cpp | 4 ++++ host/lib/usrp/usrp_e/usrp_e_regs.hpp | 6 ++++++ 4 files changed, 22 insertions(+), 8 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index 17262d358..a728d7e46 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -29,7 +29,7 @@ using namespace uhd; -static const bool codec_debug = true; +static const bool codec_debug = false; const gain_range_t usrp_e_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); const gain_range_t usrp_e_codec_ctrl::rx_pga_gain_range(0, 20, 1); @@ -133,19 +133,23 @@ usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ /*********************************************************************** * Codec Control Gain Control Methods **********************************************************************/ +static const int mtpgw = 255; //maximum tx pga gain word + void usrp_e_codec_ctrl_impl::set_tx_pga_gain(float gain){ - int gain_word = int(255*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); - _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 255); + int gain_word = int(mtpgw*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); + _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw); this->send_reg(16); } float usrp_e_codec_ctrl_impl::get_tx_pga_gain(void){ - return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/63) + tx_pga_gain_range.min; + return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/mtpgw) + tx_pga_gain_range.min; } +static const int mrpgw = 0x14; //maximum rx pga gain word + void usrp_e_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){ - int gain_word = int(0x14*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min)); - gain_word = std::clip(gain_word, 0, 0x14); + int gain_word = int(mrpgw*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min)); + gain_word = std::clip(gain_word, 0, mrpgw); switch(which){ case 'A': _ad9862_regs.rx_pga_a = gain_word; @@ -166,7 +170,7 @@ float usrp_e_codec_ctrl_impl::get_rx_pga_gain(char which){ case 'B': gain_word = _ad9862_regs.rx_pga_b; break; default: UHD_THROW_INVALID_CODE_PATH(); } - return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/0x14) + rx_pga_gain_range.min; + return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/mrpgw) + rx_pga_gain_range.min; } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index eaa45d60c..1bb67d9aa 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -33,7 +33,7 @@ using namespace uhd::usrp; * Constants **********************************************************************/ static const size_t MAX_BUFF_SIZE = 2048; -static const bool usrp_e_io_impl_verbose = true; +static const bool usrp_e_io_impl_verbose = false; /*********************************************************************** * Data Transport (phony zero-copy with read/write) diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 3d4cef069..047db3f7c 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -41,6 +41,10 @@ void usrp_e_impl::mboard_init(void){ _clock_config.pps_source = clock_config_t::PPS_SMA; //TODO poke the clock config regs + + //setup the tx policy + _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, 1); + _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index 41cbfa1e2..a4f42093e 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -151,6 +151,12 @@ //////////////////////////////////////////////// #define UE_REG_CTRL_TX_NCHANNELS UE_REG_SR_ADDR(24) #define UE_REG_CTRL_TX_CLEAR_UNDERRUN UE_REG_SR_ADDR(25) +#define UE_REG_CTRL_TX_REPORT_SID UE_REG_SR_ADDR(26) +#define UE_REG_CTRL_TX_POLICY UE_REG_SR_ADDR(27) + +#define UE_FLAG_CTRL_TX_POLICY_WAIT (0x1 << 0) +#define UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET (0x1 << 1) +#define UE_FLAG_CTRL_TX_POLICY_NEXT_BURST (0x1 << 2) ///////////////////////////////////////////////// // VITA49 64 bit time (write only) -- cgit v1.2.3 From 924914beaac3dd3a2d9fe40c9067ad4f9147a4f6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 25 Aug 2010 21:10:41 +0000 Subject: usrp-e: implemented tx policy and handling of async messages --- host/lib/usrp/usrp_e/io_impl.cpp | 129 +++++++++++++++++++++++++++++++---- host/lib/usrp/usrp_e/mboard_impl.cpp | 4 -- 2 files changed, 114 insertions(+), 19 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 1bb67d9aa..31ea4c6c0 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -18,6 +18,8 @@ #include "usrp_e_impl.hpp" #include "usrp_e_regs.hpp" #include +#include +#include #include "../../transport/vrt_packet_handler.hpp" #include #include //read, write @@ -28,12 +30,15 @@ using namespace uhd; using namespace uhd::usrp; +using namespace uhd::transport; /*********************************************************************** * Constants **********************************************************************/ static const size_t MAX_BUFF_SIZE = 2048; static const bool usrp_e_io_impl_verbose = false; +static const size_t tx_async_report_sid = 1; +static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; /*********************************************************************** * Data Transport (phony zero-copy with read/write) @@ -52,15 +57,15 @@ public: } size_t get_num_recv_frames(void) const{ - return 10; //FIXME no idea! + return 100; //FIXME no idea! + //this will be an important number when packet ring gets implemented } size_t get_num_send_frames(void) const{ - return 10; //FIXME no idea! + return 100; //FIXME no idea! + //this will be an important number when packet ring gets implemented } - size_t recv_timeout_ms; - private: int _fd; ssize_t send(const boost::asio::const_buffer &buff){ @@ -79,7 +84,7 @@ private: pollfd pfd; pfd.fd = _fd; pfd.events = POLLIN; - ssize_t poll_ret = poll(&pfd, 1, recv_timeout_ms); + ssize_t poll_ret = poll(&pfd, 1, 100/*ms*/); if (poll_ret <= 0){ if (usrp_e_io_impl_verbose) std::cerr << boost::format( "usrp-e io impl recv(): poll() returned non-positive value: %d\n" @@ -111,7 +116,11 @@ private: }; /*********************************************************************** - * IO Implementation Details + * io impl details (internal to this file) + * - pirate crew of 1 + * - bounded buffer + * - thread loop + * - vrt packet handler states **********************************************************************/ struct usrp_e_impl::io_impl{ //state management for the vrt packet handler code @@ -119,9 +128,88 @@ struct usrp_e_impl::io_impl{ vrt_packet_handler::send_state packet_handler_send_state; data_transport transport; bool continuous_streaming; - io_impl(int fd): packet_handler_recv_state(1), transport(fd){} + io_impl(int fd): + transport(fd), + recv_pirate_booty(recv_booty_type::make(transport.get_num_recv_frames())), + async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) + { + /* NOP */ + } + + ~io_impl(void){ + recv_pirate_crew_raiding = false; + recv_pirate_crew.interrupt_all(); + recv_pirate_crew.join_all(); + } + + bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, size_t timeout_ms){ + UHD_ASSERT_THROW(buffs.size() == 1); + boost::this_thread::disable_interruption di; //disable because the wait can throw + return recv_pirate_booty->pop_with_timed_wait(buffs.front(), boost::posix_time::milliseconds(timeout_ms)); + } + + //a pirate's life is the life for me! + void recv_pirate_loop(); + typedef bounded_buffer recv_booty_type; + recv_booty_type::sptr recv_pirate_booty; + bounded_buffer::sptr async_msg_fifo; + boost::thread_group recv_pirate_crew; + bool recv_pirate_crew_raiding; }; +/*********************************************************************** + * Receive Pirate Loop + * - while raiding, loot for recv buffers + * - put booty into the alignment buffer + **********************************************************************/ +void usrp_e_impl::io_impl::recv_pirate_loop( + +){ + set_thread_priority_safe(); + recv_pirate_crew_raiding = true; + //size_t next_packet_seq = 0; + + while(recv_pirate_crew_raiding){ + managed_recv_buffer::sptr buff = this->transport.get_recv_buff(); + if (not buff.get()) continue; //ignore timeout/error buffers + + try{ + //extract the vrt header packet info + vrt::if_packet_info_t if_packet_info; + if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); + const boost::uint32_t *vrt_hdr = buff->cast(); + vrt::if_hdr_unpack_le(vrt_hdr, if_packet_info); + + //handle a tx async report message + if (if_packet_info.sid == tx_async_report_sid and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ + + //fill in the async metadata + async_metadata_t metadata; + metadata.channel = 0; + metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; + metadata.time_spec = time_spec_t( + time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), MASTER_CLOCK_RATE + ); + metadata.event_code = vrt_packet_handler::get_context_code(vrt_hdr, if_packet_info); + + //print the famous U, and push the metadata into the message queue + if (metadata.event_code & underflow_flags) std::cerr << "U" << std::flush; + async_msg_fifo->push_with_pop_on_full(metadata); + continue; + } + + }catch(const std::exception &e){ + std::cerr << "Error (usrp-e recv pirate loop): " << e.what() << std::endl; + } + + //usrp-e back-pressures on receive: push with wait + recv_pirate_booty->push_with_wait(buff); + } +} + +/*********************************************************************** + * Helper Functions + **********************************************************************/ void usrp_e_impl::io_init(void){ //setup rx data path _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); @@ -136,7 +224,16 @@ void usrp_e_impl::io_init(void){ _iface->poke32(UE_REG_CTRL_RX_VRT_STREAM_ID, 0); _iface->poke32(UE_REG_CTRL_RX_VRT_TRAILER, 0); + //setup the tx policy + _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, tx_async_report_sid); + _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); + _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface->get_file_descriptor())); + + //spawn a pirate, yarrr! + _io_impl->recv_pirate_crew.create_thread(boost::bind( + &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get() + )); } void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ @@ -217,9 +314,6 @@ size_t usrp_e_impl::recv( recv_otw_type.shift = 0; recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - //hand-off the timeout to the transport - _io_impl->transport.recv_timeout_ms = timeout_ms; - return vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler buffs, num_samps, //buffer to fill @@ -227,15 +321,20 @@ size_t usrp_e_impl::recv( io_type, recv_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, - boost::bind(&get_recv_buffs, &_io_impl->transport, _1), + boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout_ms), boost::bind(&usrp_e_impl::handle_overrun, this, _1) ); } /*********************************************************************** - * Dummy Async Recv + * Async Recv **********************************************************************/ -bool usrp_e_impl::recv_async_msg(async_metadata_t &, size_t timeout_ms){ - boost::this_thread::sleep(boost::posix_time::milliseconds(timeout_ms)); - return false; +bool usrp_e_impl::recv_async_msg( + async_metadata_t &async_metadata, + size_t timeout_ms +){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + return _io_impl->async_msg_fifo->pop_with_timed_wait( + async_metadata, boost::posix_time::milliseconds(timeout_ms) + ); } diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 047db3f7c..3d4cef069 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -41,10 +41,6 @@ void usrp_e_impl::mboard_init(void){ _clock_config.pps_source = clock_config_t::PPS_SMA; //TODO poke the clock config regs - - //setup the tx policy - _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, 1); - _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); } /*********************************************************************** -- cgit v1.2.3 From bc824badaa981c1785d8c76d7cf56274d7c582b8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 9 Sep 2010 16:28:37 -0700 Subject: usrp-e: configure flag option for usrp-e support --- host/lib/usrp/usrp_e/CMakeLists.txt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index f0c125f26..da759d931 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -25,7 +25,18 @@ MESSAGE(STATUS "Configuring usrp-e support...") INCLUDE(CheckIncludeFileCXX) CHECK_INCLUDE_FILE_CXX(linux/usrp_e.h HAVE_LINUX_USRP_E_H) -IF(HAVE_LINUX_USRP_E_H) +IF(DEFINED ENABLE_USRP_E) + IF(ENABLE_USRP_E) + MESSAGE(STATUS "USRP-E support enabled by configure flag") + ELSE(ENABLE_USRP_E) + MESSAGE(STATUS "USRP-E support disabled by configure flag") + ENDIF(ENABLE_USRP_E) +ELSE(DEFINED ENABLE_USRP_E) #not defined: automatic enabling of component + SET(ENABLE_USRP_E ${HAVE_LINUX_USRP_E_H}) +ENDIF(DEFINED ENABLE_USRP_E) +SET(ENABLE_USRP_E ${ENABLE_USRP_E} CACHE BOOL "enable USRP-E support") + +IF(ENABLE_USRP_E) MESSAGE(STATUS " Building usrp-e support.") LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/clock_ctrl.cpp @@ -45,6 +56,6 @@ IF(HAVE_LINUX_USRP_E_H) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_regs.hpp ) -ELSE(HAVE_LINUX_USRP_E_H) +ELSE(ENABLE_USRP_E) MESSAGE(STATUS " Skipping usrp-e support.") -ENDIF(HAVE_LINUX_USRP_E_H) +ENDIF(ENABLE_USRP_E) -- cgit v1.2.3 From 082715d0c90b615874fe6bbe93069fa696b3d47a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 24 Sep 2010 15:56:52 -0700 Subject: usrp-e: updated dsp for multiple shift properties --- host/lib/usrp/usrp_e/dsp_impl.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index c133eafae..9312bb603 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -44,7 +44,9 @@ void usrp_e_impl::rx_ddc_init(void){ /*********************************************************************** * RX DDC Get **********************************************************************/ -void usrp_e_impl::rx_ddc_get(const wax::obj &key, wax::obj &val){ +void usrp_e_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp-e ddc0"); @@ -58,6 +60,10 @@ void usrp_e_impl::rx_ddc_get(const wax::obj &key, wax::obj &val){ val = _ddc_freq; return; + case DSP_PROP_FREQ_SHIFT_NAMES: + val = prop_names_t(1, ""); + return; + case DSP_PROP_CODEC_RATE: val = MASTER_CLOCK_RATE; return; @@ -73,7 +79,9 @@ void usrp_e_impl::rx_ddc_get(const wax::obj &key, wax::obj &val){ /*********************************************************************** * RX DDC Set **********************************************************************/ -void usrp_e_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val){ +void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_FREQ_SHIFT:{ @@ -119,7 +127,9 @@ void usrp_e_impl::tx_duc_init(void){ /*********************************************************************** * TX DUC Get **********************************************************************/ -void usrp_e_impl::tx_duc_get(const wax::obj &key, wax::obj &val){ +void usrp_e_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp-e duc0"); @@ -133,6 +143,10 @@ void usrp_e_impl::tx_duc_get(const wax::obj &key, wax::obj &val){ val = _duc_freq; return; + case DSP_PROP_FREQ_SHIFT_NAMES: + val = prop_names_t(1, ""); + return; + case DSP_PROP_CODEC_RATE: val = MASTER_CLOCK_RATE; return; @@ -148,7 +162,9 @@ void usrp_e_impl::tx_duc_get(const wax::obj &key, wax::obj &val){ /*********************************************************************** * TX DUC Set **********************************************************************/ -void usrp_e_impl::tx_duc_set(const wax::obj &key, const wax::obj &val){ +void usrp_e_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_FREQ_SHIFT:{ -- cgit v1.2.3 From 20c364cb6e2d175525c1885c8ac122187853dc95 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Sun, 26 Sep 2010 21:22:51 -0400 Subject: Really enable usrp_e support. Previous commit commented out the ansi flag so C++ comments in C compile. --- host/lib/usrp/usrp_e/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index da759d931..fbcd19276 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -25,6 +25,8 @@ MESSAGE(STATUS "Configuring usrp-e support...") INCLUDE(CheckIncludeFileCXX) CHECK_INCLUDE_FILE_CXX(linux/usrp_e.h HAVE_LINUX_USRP_E_H) +SET(ENABLE_USRP_E TRUE) + IF(DEFINED ENABLE_USRP_E) IF(ENABLE_USRP_E) MESSAGE(STATUS "USRP-E support enabled by configure flag") -- cgit v1.2.3 From cc97c6ee0b3dbc8e0ed6bfae01505fcb209d13cb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 15:12:30 -0700 Subject: usrp-e: update to build with the master --- host/lib/usrp/usrp_e/dboard_iface.cpp | 5 +++++ host/lib/usrp/usrp_e/io_impl.cpp | 18 +++++------------- 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index 1bd177f60..6898df8df 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -91,6 +91,7 @@ public: std::vector get_clock_rates(unit_t); double get_clock_rate(unit_t); void set_clock_enabled(unit_t, bool); + double get_codec_rate(unit_t); private: usrp_e_iface::sptr _iface; @@ -140,6 +141,10 @@ void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ } } +double usrp_e_dboard_iface::get_codec_rate(unit_t){ + return _clock->get_fpga_clock_rate(); +} + /*********************************************************************** * GPIO **********************************************************************/ diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 31ea4c6c0..e57d6ce35 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -39,6 +39,7 @@ static const size_t MAX_BUFF_SIZE = 2048; static const bool usrp_e_io_impl_verbose = false; static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; +static const double recv_timeout_ms = 100; /*********************************************************************** * Data Transport (phony zero-copy with read/write) @@ -74,7 +75,7 @@ private: boost::asio::buffer_size(buff) ); } - ssize_t recv(const boost::asio::mutable_buffer &buff){ + ssize_t recv(const boost::asio::mutable_buffer &buff, size_t to_ms){ //std::cout << boost::format( // "calling read on fd %d, buff size is %d" //) % _fd % boost::asio::buffer_size(buff) << std::endl; @@ -84,7 +85,7 @@ private: pollfd pfd; pfd.fd = _fd; pfd.events = POLLIN; - ssize_t poll_ret = poll(&pfd, 1, 100/*ms*/); + ssize_t poll_ret = poll(&pfd, 1, to_ms); if (poll_ret <= 0){ if (usrp_e_io_impl_verbose) std::cerr << boost::format( "usrp-e io impl recv(): poll() returned non-positive value: %d\n" @@ -170,7 +171,7 @@ void usrp_e_impl::io_impl::recv_pirate_loop( //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = this->transport.get_recv_buff(); + managed_recv_buffer::sptr buff = this->transport.get_recv_buff(recv_timeout_ms); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -262,7 +263,7 @@ bool get_send_buffs( ){ UHD_ASSERT_THROW(buffs.size() == 1); buffs[0] = trans->get_send_buff(); - return buffs[0].get(); + return buffs[0].get() != NULL; } size_t usrp_e_impl::send( @@ -292,15 +293,6 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ -bool get_recv_buffs( - data_transport *trans, - vrt_packet_handler::managed_recv_buffs_t &buffs -){ - UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = trans->get_recv_buff(); - return buffs[0].get(); -} - size_t usrp_e_impl::recv( const std::vector &buffs, size_t num_samps, -- cgit v1.2.3 From 46d2fc423d2fdcf32454621c6f41e555d2496702 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 17:56:36 -0700 Subject: usrp-e: untested attempt at zero copy iface for mmap --- host/lib/usrp/usrp_e/CMakeLists.txt | 1 + host/lib/usrp/usrp_e/io_impl.cpp | 97 ++---------- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 201 +++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 87 deletions(-) create mode 100644 host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index da759d931..bab868f90 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -54,6 +54,7 @@ IF(ENABLE_USRP_E) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_regs.hpp ) ELSE(ENABLE_USRP_E) diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index e57d6ce35..0b5fa054b 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -22,8 +22,6 @@ #include #include "../../transport/vrt_packet_handler.hpp" #include -#include //read, write -#include #include #include #include @@ -32,90 +30,15 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; +zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); + /*********************************************************************** * Constants **********************************************************************/ -static const size_t MAX_BUFF_SIZE = 2048; -static const bool usrp_e_io_impl_verbose = false; static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; static const double recv_timeout_ms = 100; -/*********************************************************************** - * Data Transport (phony zero-copy with read/write) - **********************************************************************/ -class data_transport: - public transport::phony_zero_copy_recv_if, - public transport::phony_zero_copy_send_if -{ -public: - data_transport(int fd): - transport::phony_zero_copy_recv_if(MAX_BUFF_SIZE), - transport::phony_zero_copy_send_if(MAX_BUFF_SIZE), - _fd(fd) - { - /* NOP */ - } - - size_t get_num_recv_frames(void) const{ - return 100; //FIXME no idea! - //this will be an important number when packet ring gets implemented - } - - size_t get_num_send_frames(void) const{ - return 100; //FIXME no idea! - //this will be an important number when packet ring gets implemented - } - -private: - int _fd; - ssize_t send(const boost::asio::const_buffer &buff){ - return write(_fd, - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff) - ); - } - ssize_t recv(const boost::asio::mutable_buffer &buff, size_t to_ms){ - //std::cout << boost::format( - // "calling read on fd %d, buff size is %d" - //) % _fd % boost::asio::buffer_size(buff) << std::endl; - - //setup and call poll on the file descriptor - //return 0 and do not read when poll times out - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLIN; - ssize_t poll_ret = poll(&pfd, 1, to_ms); - if (poll_ret <= 0){ - if (usrp_e_io_impl_verbose) std::cerr << boost::format( - "usrp-e io impl recv(): poll() returned non-positive value: %d\n" - " -> return 0 for timeout" - ) % poll_ret << std::endl; - return 0; //timeout - } - - //perform the blocking read(...) - ssize_t read_ret = read(_fd, - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff) - ); - if (read_ret < 0){ - if (usrp_e_io_impl_verbose) std::cerr << boost::format( - "usrp-e io impl recv(): read() returned small value: %d\n" - " -> return -1 for error" - ) % read_ret << std::endl; - return -1; - } - - //std::cout << "len " << int(read_ret) << std::endl; - //for (size_t i = 0; i < 9; i++){ - // std::cout << boost::format(" 0x%08x") % boost::asio::buffer_cast(buff)[i] << std::endl; - //} - - return read_ret; - } -}; - /*********************************************************************** * io impl details (internal to this file) * - pirate crew of 1 @@ -127,11 +50,11 @@ struct usrp_e_impl::io_impl{ //state management for the vrt packet handler code vrt_packet_handler::recv_state packet_handler_recv_state; vrt_packet_handler::send_state packet_handler_send_state; - data_transport transport; + zero_copy_if::sptr data_xport; bool continuous_streaming; - io_impl(int fd): - transport(fd), - recv_pirate_booty(recv_booty_type::make(transport.get_num_recv_frames())), + io_impl(usrp_e_iface::sptr iface): + data_xport(usrp_e_make_mmap_zero_copy(iface)), + recv_pirate_booty(recv_booty_type::make(data_xport->get_num_recv_frames())), async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) { /* NOP */ @@ -171,7 +94,7 @@ void usrp_e_impl::io_impl::recv_pirate_loop( //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = this->transport.get_recv_buff(recv_timeout_ms); + managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(recv_timeout_ms); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -229,7 +152,7 @@ void usrp_e_impl::io_init(void){ _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, tx_async_report_sid); _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); - _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface->get_file_descriptor())); + _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface)); //spawn a pirate, yarrr! _io_impl->recv_pirate_crew.create_thread(boost::bind( @@ -258,7 +181,7 @@ void usrp_e_impl::handle_overrun(size_t){ * Data Send **********************************************************************/ bool get_send_buffs( - data_transport *trans, + zero_copy_if::sptr trans, vrt_packet_handler::managed_send_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); @@ -285,7 +208,7 @@ size_t usrp_e_impl::send( io_type, send_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, - boost::bind(&get_send_buffs, &_io_impl->transport, _1), + boost::bind(&get_send_buffs, _io_impl->data_xport, _1), get_max_send_samps_per_packet() ); } diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp new file mode 100644 index 000000000..0910caa6f --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -0,0 +1,201 @@ +// +// 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 . +// + +#include +#include +#include +#include //mmap +#include //getpagesize +#include //poll +#include +#include "usrp_e_iface.hpp" + +using namespace uhd; +using namespace uhd::transport; + +static const bool debug_verbose = false; + +/*********************************************************************** + * The managed receive buffer implementation + **********************************************************************/ +class usrp_e_mmap_managed_recv_buffer : public managed_recv_buffer{ +public: + usrp_e_mmap_managed_recv_buffer( + const void *mem, size_t len, ring_buffer_info *info + ): + _buff(mem, len), _info(info) + { + /* NOP */ + } + + ~usrp_e_mmap_managed_recv_buffer(void){ + _info->flags = RB_KERNEL; + } + +private: + const boost::asio::const_buffer &get(void) const{ + return _buff; + } + + const boost::asio::const_buffer _buff; + ring_buffer_info *_info; +}; + +/*********************************************************************** + * The managed send buffer implementation + **********************************************************************/ +class usrp_e_mmap_managed_send_buffer : public managed_send_buffer{ +public: + usrp_e_mmap_managed_send_buffer( + void *mem, size_t len, ring_buffer_info *info, int fd + ): + _buff(mem, len), _info(info), _fd(fd), _commited(false) + { + /* NOP */ + } + + ~usrp_e_mmap_managed_send_buffer(void){ + if (not _commited) this->commit(0); + } + + ssize_t commit(size_t num_bytes){ + _commited = true; + _info->len = num_bytes; + _info->flags = RB_USER; + ssize_t ret = ::write(_fd, NULL, 0); + return (ret < 0)? ret : num_bytes; + } + +private: + const boost::asio::mutable_buffer &get(void) const{ + return _buff; + } + + const boost::asio::mutable_buffer _buff; + ring_buffer_info *_info; + int _fd; + bool _commited; +}; + +/*********************************************************************** + * The zero copy interface implementation + **********************************************************************/ +class usrp_e_mmap_zero_copy_impl : public zero_copy_if{ +public: + usrp_e_mmap_zero_copy_impl(usrp_e_iface::sptr iface): + _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) + { + //get system sizes + iface->ioctl(USRP_E_GET_RB_INFO, &_rb_size); + size_t page_size = getpagesize(); + _frame_size = page_size/2; + + //calculate the memory size + size_t map_size = + (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + + (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; + + //call mmap to get the memory + void *ring_buffer = mmap( + NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 + ); + UHD_ASSERT_THROW(ring_buffer != MAP_FAILED); + + //calculate the memory offsets for info and buffers + size_t recv_info_off = 0; + size_t recv_buff_off = recv_info_off + (_rb_size.num_pages_rx_flags * page_size); + size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); + size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); + + //set the internal pointers for info and buffers + typedef ring_buffer_info (*rbi_pta)[]; + boost::uint8_t *rb_ptr = reinterpret_cast(ring_buffer); + _recv_info = reinterpret_cast(rb_ptr + recv_info_off); + _recv_buff = rb_ptr + recv_buff_off; + _send_info = reinterpret_cast(rb_ptr + send_info_off); + _send_buff = rb_ptr + send_buff_off; + } + + managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms){ + //grab pointers to the info and buffer + ring_buffer_info *info = (*_recv_info) + _recv_index; + void *mem = _recv_buff + _frame_size*_recv_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_USER)){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLIN; + ssize_t poll_ret = poll(&pfd, 1, timeout_ms); + if (poll_ret <= 0) return managed_recv_buffer::sptr(); + } + + //increment the index for the next call + if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; + + //return the managed buffer for this frame + return managed_recv_buffer::sptr( + new usrp_e_mmap_managed_recv_buffer(mem, info->len, info) + ); + } + + size_t get_num_recv_frames(void) const{ + return _rb_size.num_rx_frames; + } + + managed_send_buffer::sptr get_send_buff(void){ + //grab pointers to the info and buffer + ring_buffer_info *info = (*_send_info) + _send_index; + void *mem = _send_buff + _frame_size*_send_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_KERNEL)){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLOUT; + ssize_t poll_ret = poll(&pfd, 1, -1 /*forever*/); + if (poll_ret <= 0) return managed_send_buffer::sptr(); + } + + //increment the index for the next call + if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; + + //return the managed buffer for this frame + return managed_send_buffer::sptr( + new usrp_e_mmap_managed_send_buffer(mem, _frame_size, info, _fd) + ); + } + + size_t get_num_send_frames(void) const{ + return _rb_size.num_tx_frames; + } + +private: + int _fd; + usrp_e_ring_buffer_size_t _rb_size; + size_t _frame_size; + ring_buffer_info (*_recv_info)[], (*_send_info)[]; + boost::uint8_t *_recv_buff, *_send_buff; + size_t _recv_index, _send_index; +}; + +/*********************************************************************** + * The zero copy interface make function + **********************************************************************/ +zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface){ + return zero_copy_if::sptr(new usrp_e_mmap_zero_copy_impl(iface)); +} -- cgit v1.2.3 From b34af3c910a54d8afd4b1f00f1254c3ab762c82a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 11:17:01 -0700 Subject: usrp-e: implemented mmap with new zero_copy timeout work, added much debug verbosity --- host/lib/usrp/usrp_e/io_impl.cpp | 48 ++++---- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 6 +- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 161 ++++++++++++------------- 3 files changed, 107 insertions(+), 108 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 0b5fa054b..1e577a4df 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -37,7 +37,7 @@ zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); **********************************************************************/ static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; -static const double recv_timeout_ms = 100; +static const bool recv_debug = true; /*********************************************************************** * io impl details (internal to this file) @@ -66,10 +66,10 @@ struct usrp_e_impl::io_impl{ recv_pirate_crew.join_all(); } - bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, size_t timeout_ms){ + bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){ UHD_ASSERT_THROW(buffs.size() == 1); boost::this_thread::disable_interruption di; //disable because the wait can throw - return recv_pirate_booty->pop_with_timed_wait(buffs.front(), boost::posix_time::milliseconds(timeout_ms)); + return recv_pirate_booty->pop_with_timed_wait(buffs.front(), timeout); } //a pirate's life is the life for me! @@ -94,9 +94,17 @@ void usrp_e_impl::io_impl::recv_pirate_loop( //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(recv_timeout_ms); + managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(); if (not buff.get()) continue; //ignore timeout/error buffers + if (recv_debug){ + std::cout << "len " << buff->size() << std::endl; + for (size_t i = 0; i < 9; i++){ + std::cout << boost::format(" 0x%08x") % buff->cast()[i] << std::endl; + } + std::cout << std::endl << std::endl; + } + try{ //extract the vrt header packet info vrt::if_packet_info_t if_packet_info; @@ -181,20 +189,18 @@ void usrp_e_impl::handle_overrun(size_t){ * Data Send **********************************************************************/ bool get_send_buffs( - zero_copy_if::sptr trans, + zero_copy_if::sptr trans, double timeout, vrt_packet_handler::managed_send_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = trans->get_send_buff(); + buffs[0] = trans->get_send_buff(timeout); return buffs[0].get() != NULL; } size_t usrp_e_impl::send( - const std::vector &buffs, - size_t num_samps, - const tx_metadata_t &metadata, - const io_type_t &io_type, - send_mode_t send_mode + const std::vector &buffs, size_t num_samps, + const tx_metadata_t &metadata, const io_type_t &io_type, + send_mode_t send_mode, double timeout ){ otw_type_t send_otw_type; send_otw_type.width = 16; @@ -208,7 +214,7 @@ size_t usrp_e_impl::send( io_type, send_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, - boost::bind(&get_send_buffs, _io_impl->data_xport, _1), + boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), get_max_send_samps_per_packet() ); } @@ -217,12 +223,9 @@ size_t usrp_e_impl::send( * Data Recv **********************************************************************/ size_t usrp_e_impl::recv( - const std::vector &buffs, - size_t num_samps, - rx_metadata_t &metadata, - const io_type_t &io_type, - recv_mode_t recv_mode, - size_t timeout_ms + const std::vector &buffs, size_t num_samps, + rx_metadata_t &metadata, const io_type_t &io_type, + recv_mode_t recv_mode, double timeout ){ otw_type_t recv_otw_type; recv_otw_type.width = 16; @@ -236,7 +239,7 @@ size_t usrp_e_impl::recv( io_type, recv_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, - boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout_ms), + boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), boost::bind(&usrp_e_impl::handle_overrun, this, _1) ); } @@ -245,11 +248,8 @@ size_t usrp_e_impl::recv( * Async Recv **********************************************************************/ bool usrp_e_impl::recv_async_msg( - async_metadata_t &async_metadata, - size_t timeout_ms + async_metadata_t &async_metadata, double timeout ){ boost::this_thread::disable_interruption di; //disable because the wait can throw - return _io_impl->async_msg_fifo->pop_with_timed_wait( - async_metadata, boost::posix_time::milliseconds(timeout_ms) - ); + return _io_impl->async_msg_fifo->pop_with_timed_wait(async_metadata, timeout); } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 2457e27cc..49912050e 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -82,9 +82,9 @@ public: ~usrp_e_impl(void); //the io interface - size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t); - size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, size_t); - bool recv_async_msg(uhd::async_metadata_t &, size_t); + size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); + size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); + bool recv_async_msg(uhd::async_metadata_t &, double); size_t get_max_send_samps_per_packet(void) const{return 503;} size_t get_max_recv_samps_per_packet(void) const{return 503;} diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index 0910caa6f..e62205a3f 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -15,86 +15,27 @@ // along with this program. If not, see . // +#include "usrp_e_iface.hpp" #include #include #include #include //mmap #include //getpagesize #include //poll -#include -#include "usrp_e_iface.hpp" +#include +#include +#include using namespace uhd; using namespace uhd::transport; -static const bool debug_verbose = false; - -/*********************************************************************** - * The managed receive buffer implementation - **********************************************************************/ -class usrp_e_mmap_managed_recv_buffer : public managed_recv_buffer{ -public: - usrp_e_mmap_managed_recv_buffer( - const void *mem, size_t len, ring_buffer_info *info - ): - _buff(mem, len), _info(info) - { - /* NOP */ - } - - ~usrp_e_mmap_managed_recv_buffer(void){ - _info->flags = RB_KERNEL; - } - -private: - const boost::asio::const_buffer &get(void) const{ - return _buff; - } - - const boost::asio::const_buffer _buff; - ring_buffer_info *_info; -}; - -/*********************************************************************** - * The managed send buffer implementation - **********************************************************************/ -class usrp_e_mmap_managed_send_buffer : public managed_send_buffer{ -public: - usrp_e_mmap_managed_send_buffer( - void *mem, size_t len, ring_buffer_info *info, int fd - ): - _buff(mem, len), _info(info), _fd(fd), _commited(false) - { - /* NOP */ - } - - ~usrp_e_mmap_managed_send_buffer(void){ - if (not _commited) this->commit(0); - } - - ssize_t commit(size_t num_bytes){ - _commited = true; - _info->len = num_bytes; - _info->flags = RB_USER; - ssize_t ret = ::write(_fd, NULL, 0); - return (ret < 0)? ret : num_bytes; - } - -private: - const boost::asio::mutable_buffer &get(void) const{ - return _buff; - } - - const boost::asio::mutable_buffer _buff; - ring_buffer_info *_info; - int _fd; - bool _commited; -}; +static const bool fp_verbose = true; //fast-path verbose +static const bool sp_verbose = true; //slow-path verbose /*********************************************************************** * The zero copy interface implementation **********************************************************************/ -class usrp_e_mmap_zero_copy_impl : public zero_copy_if{ +class usrp_e_mmap_zero_copy_impl : public zero_copy_if, public boost::enable_shared_from_this { public: usrp_e_mmap_zero_copy_impl(usrp_e_iface::sptr iface): _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) @@ -105,15 +46,26 @@ public: _frame_size = page_size/2; //calculate the memory size - size_t map_size = + _map_size = (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; + //print sizes summary + if (sp_verbose){ + std::cout << "page_size: " << page_size << std::endl; + std::cout << "frame_size: " << _frame_size << std::endl; + std::cout << "num_pages_rx_flags: " << _rb_size.num_pages_rx_flags << std::endl; + std::cout << "num_rx_frames: " << _rb_size.num_rx_frames << std::endl; + std::cout << "num_pages_tx_flags: " << _rb_size.num_pages_tx_flags << std::endl; + std::cout << "num_tx_frames: " << _rb_size.num_tx_frames << std::endl; + std::cout << "map_size: " << _map_size << std::endl; + } + //call mmap to get the memory - void *ring_buffer = mmap( - NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 + _mapped_mem = ::mmap( + NULL, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 ); - UHD_ASSERT_THROW(ring_buffer != MAP_FAILED); + UHD_ASSERT_THROW(_mapped_mem != MAP_FAILED); //calculate the memory offsets for info and buffers size_t recv_info_off = 0; @@ -121,16 +73,31 @@ public: size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); + //print offset summary + if (sp_verbose){ + std::cout << "recv_info_off: " << recv_info_off << std::endl; + std::cout << "recv_buff_off: " << recv_buff_off << std::endl; + std::cout << "send_info_off: " << send_info_off << std::endl; + std::cout << "send_buff_off: " << send_buff_off << std::endl; + } + //set the internal pointers for info and buffers typedef ring_buffer_info (*rbi_pta)[]; - boost::uint8_t *rb_ptr = reinterpret_cast(ring_buffer); + char *rb_ptr = reinterpret_cast(_mapped_mem); _recv_info = reinterpret_cast(rb_ptr + recv_info_off); _recv_buff = rb_ptr + recv_buff_off; _send_info = reinterpret_cast(rb_ptr + send_info_off); _send_buff = rb_ptr + send_buff_off; } - managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms){ + ~usrp_e_mmap_zero_copy_impl(void){ + if (sp_verbose) std::cout << "cleanup: munmap" << std::endl; + ::munmap(_mapped_mem, _map_size); + } + + managed_recv_buffer::sptr get_recv_buff(double timeout){ + if (fp_verbose) std::cout << "get_recv_buff: " << _recv_index << std::endl; + //grab pointers to the info and buffer ring_buffer_info *info = (*_recv_info) + _recv_index; void *mem = _recv_buff + _frame_size*_recv_index; @@ -140,7 +107,8 @@ public: pollfd pfd; pfd.fd = _fd; pfd.events = POLLIN; - ssize_t poll_ret = poll(&pfd, 1, timeout_ms); + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); + if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; if (poll_ret <= 0) return managed_recv_buffer::sptr(); } @@ -148,8 +116,10 @@ public: if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; //return the managed buffer for this frame - return managed_recv_buffer::sptr( - new usrp_e_mmap_managed_recv_buffer(mem, info->len, info) + if (fp_verbose) std::cout << " make_recv_buff: " << info->len << std::endl; + return managed_recv_buffer::make_safe( + boost::asio::const_buffer(mem, info->len), + boost::bind(&usrp_e_mmap_zero_copy_impl::release, shared_from_this(), info) ); } @@ -157,7 +127,9 @@ public: return _rb_size.num_rx_frames; } - managed_send_buffer::sptr get_send_buff(void){ + managed_send_buffer::sptr get_send_buff(double timeout){ + if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; + //grab pointers to the info and buffer ring_buffer_info *info = (*_send_info) + _send_index; void *mem = _send_buff + _frame_size*_send_index; @@ -167,7 +139,8 @@ public: pollfd pfd; pfd.fd = _fd; pfd.events = POLLOUT; - ssize_t poll_ret = poll(&pfd, 1, -1 /*forever*/); + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); + if (fp_verbose) std::cout << " POLLOUT: " << poll_ret << std::endl; if (poll_ret <= 0) return managed_send_buffer::sptr(); } @@ -175,8 +148,10 @@ public: if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; //return the managed buffer for this frame - return managed_send_buffer::sptr( - new usrp_e_mmap_managed_send_buffer(mem, _frame_size, info, _fd) + if (fp_verbose) std::cout << " make_send_buff: " << _frame_size << std::endl; + return managed_send_buffer::make_safe( + boost::asio::mutable_buffer(mem, _frame_size), + boost::bind(&usrp_e_mmap_zero_copy_impl::commit, shared_from_this(), info, _1) ); } @@ -185,11 +160,35 @@ public: } private: + + void release(ring_buffer_info *info){ + if (fp_verbose) std::cout << "recv buff: release" << std::endl; + info->flags = RB_KERNEL; + } + + void commit(ring_buffer_info *info, size_t len){ + if (fp_verbose) std::cout << "send buff: commit " << len << std::endl; + info->len = len; + info->flags = RB_USER; + if (::write(_fd, NULL, 0) < 0){ + std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl; + } + } + int _fd; + + //the mapped memory itself + void *_mapped_mem; + + //mapped memory sizes usrp_e_ring_buffer_size_t _rb_size; - size_t _frame_size; + size_t _frame_size, _map_size; + + //pointers to sections in the mapped memory ring_buffer_info (*_recv_info)[], (*_send_info)[]; - boost::uint8_t *_recv_buff, *_send_buff; + char *_recv_buff, *_send_buff; + + //indexes into sub-sections of mapped memory size_t _recv_index, _send_index; }; -- cgit v1.2.3 From f642942dc364c1d26a9128c1ba631d3604d0671a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 15:17:57 -0700 Subject: usrp-e: check if flags are ready after poll --- host/lib/usrp/usrp_e/io_impl.cpp | 6 +++--- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 1e577a4df..2802a6b87 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -130,12 +130,12 @@ void usrp_e_impl::io_impl::recv_pirate_loop( continue; } + //same number of frames as the data transport -> always immediate + recv_pirate_booty->push_with_wait(buff); + }catch(const std::exception &e){ std::cerr << "Error (usrp-e recv pirate loop): " << e.what() << std::endl; } - - //usrp-e back-pressures on receive: push with wait - recv_pirate_booty->push_with_wait(buff); } } diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index e62205a3f..9e25ed088 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -112,6 +112,12 @@ public: if (poll_ret <= 0) return managed_recv_buffer::sptr(); } + //check that the frame is really ready + if (not (info->flags & RB_USER)){ + if (fp_verbose) std::cout << " flags: not ready" << std::endl; + return managed_recv_buffer::sptr(); + } + //increment the index for the next call if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; @@ -144,6 +150,12 @@ public: if (poll_ret <= 0) return managed_send_buffer::sptr(); } + //check that the frame is really ready + if (not (info->flags & RB_KERNEL)){ + if (fp_verbose) std::cout << " flags: not ready" << std::endl; + return managed_send_buffer::sptr(); + } + //increment the index for the next call if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; -- cgit v1.2.3 From d5a0960455560e9f6077aa45d52aa01c469769dd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 6 Oct 2010 16:26:35 -0700 Subject: usrp-e: implemented the USER_PROCESS flag and CTM poll technique --- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 33 +++++++++++--------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index 9e25ed088..4e10bcc48 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -31,6 +31,7 @@ using namespace uhd::transport; static const bool fp_verbose = true; //fast-path verbose static const bool sp_verbose = true; //slow-path verbose +static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout /*********************************************************************** * The zero copy interface implementation @@ -104,19 +105,19 @@ public: //poll/wait for a ready frame if (not (info->flags & RB_USER)){ - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLIN; - ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); - if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; - if (poll_ret <= 0) return managed_recv_buffer::sptr(); - } - - //check that the frame is really ready - if (not (info->flags & RB_USER)){ - if (fp_verbose) std::cout << " flags: not ready" << std::endl; - return managed_recv_buffer::sptr(); - } + for (size_t i = 0; i < poll_breakout; i++){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLIN; + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3/poll_breakout)); + if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; + if (poll_ret > 0) goto found_user_frame; //good poll, continue on + } + return managed_recv_buffer::sptr(); //timed-out for real + } found_user_frame: + + //the process has claimed the frame + info->flags = RB_USER_PROCESS; //increment the index for the next call if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; @@ -150,12 +151,6 @@ public: if (poll_ret <= 0) return managed_send_buffer::sptr(); } - //check that the frame is really ready - if (not (info->flags & RB_KERNEL)){ - if (fp_verbose) std::cout << " flags: not ready" << std::endl; - return managed_send_buffer::sptr(); - } - //increment the index for the next call if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; -- cgit v1.2.3 From be6a6b291400dde7b2b3b935e2eedd8d892e54f8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 10:27:30 -0700 Subject: usrp-e: use frame size to calculate the max samples per packet --- host/lib/usrp/usrp_e/io_impl.cpp | 43 ++++++++++++++++++-------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 6 ++-- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 8 +++++ 3 files changed, 42 insertions(+), 15 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 2802a6b87..406b7269f 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -91,7 +91,6 @@ void usrp_e_impl::io_impl::recv_pirate_loop( ){ set_thread_priority_safe(); recv_pirate_crew_raiding = true; - //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(); @@ -143,6 +142,15 @@ void usrp_e_impl::io_impl::recv_pirate_loop( * Helper Functions **********************************************************************/ void usrp_e_impl::io_init(void){ + //setup otw types + _send_otw_type.width = 16; + _send_otw_type.shift = 0; + _send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + + _recv_otw_type.width = 16; + _recv_otw_type.shift = 0; + _recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + //setup rx data path _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); @@ -197,21 +205,25 @@ bool get_send_buffs( return buffs[0].get() != NULL; } +size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + size_t bpp = _io_impl->data_xport->get_send_frame_size() - hdr_size; + return bpp/_send_otw_type.get_sample_size(); +} + size_t usrp_e_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, send_mode_t send_mode, double timeout ){ - otw_type_t send_otw_type; - send_otw_type.width = 16; - send_otw_type.shift = 0; - send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - return vrt_packet_handler::send( _io_impl->packet_handler_send_state, //last state of the send handler buffs, num_samps, //buffer to fill metadata, send_mode, //samples metadata - io_type, send_otw_type, //input and output types to convert + io_type, _send_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), @@ -222,21 +234,26 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ +size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + size_t bpp = _io_impl->data_xport->get_recv_frame_size() - hdr_size; + return bpp/_recv_otw_type.get_sample_size(); +} + size_t usrp_e_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, double timeout ){ - otw_type_t recv_otw_type; - recv_otw_type.width = 16; - recv_otw_type.shift = 0; - recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - return vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler buffs, num_samps, //buffer to fill metadata, recv_mode, //samples metadata - io_type, recv_otw_type, //input and output types to convert + io_type, _recv_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 49912050e..95d80fed5 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -85,8 +86,8 @@ public: size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); bool recv_async_msg(uhd::async_metadata_t &, double); - size_t get_max_send_samps_per_packet(void) const{return 503;} - size_t get_max_recv_samps_per_packet(void) const{return 503;} + size_t get_max_send_samps_per_packet(void) const; + size_t get_max_recv_samps_per_packet(void) const; private: //interface to ioctls and file descriptor @@ -97,6 +98,7 @@ private: //handle io stuff UHD_PIMPL_DECL(io_impl) _io_impl; + uhd::otw_type_t _send_otw_type, _recv_otw_type; void io_init(void); void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); void handle_overrun(size_t); diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index 4e10bcc48..bc18c490b 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -134,6 +134,10 @@ public: return _rb_size.num_rx_frames; } + size_t get_recv_frame_size(void) const{ + return _frame_size; + } + managed_send_buffer::sptr get_send_buff(double timeout){ if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; @@ -166,6 +170,10 @@ public: return _rb_size.num_tx_frames; } + size_t get_send_frame_size(void) const{ + return _frame_size; + } + private: void release(ring_buffer_info *info){ -- cgit v1.2.3 From 369c0e1dbc1518bd0fe2f81bec5e197d0c3bfe41 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 17:41:19 -0700 Subject: usrp2: implement fc seq number on tx header packing --- host/lib/usrp/usrp2/io_impl.cpp | 54 ++++++++++++++++++++++++-------------- host/lib/usrp/usrp2/usrp2_impl.cpp | 6 ++--- host/lib/usrp/usrp2/usrp2_impl.hpp | 6 ++--- 3 files changed, 41 insertions(+), 25 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index eba704059..b7585afe9 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -18,11 +18,11 @@ #include "../../transport/vrt_packet_handler.hpp" #include "usrp2_impl.hpp" #include "usrp2_regs.hpp" +#include #include #include #include #include -#include //htonl and ntohl #include #include #include @@ -32,7 +32,12 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; +static const int underflow_flags = 0 + | async_metadata_t::EVENT_CODE_UNDERFLOW + | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET +; + +static const size_t vrt_send_header_offset_words32 = 1; /*********************************************************************** * io impl details (internal to this file) @@ -63,6 +68,27 @@ struct usrp2_impl::io_impl{ return recv_pirate_booty->pop_elems_with_timed_wait(buffs, timeout); } + bool get_send_buffs( + const std::vector &trans, + vrt_packet_handler::managed_send_buffs_t &buffs, + double timeout + ){ + UHD_ASSERT_THROW(trans.size() == buffs.size()); + + //calculate the 16-bit sequence number for the special header + const boost::uint32_t next_seq = uhd::htonx(boost::uint32_t( + packet_handler_send_state.next_packet_seq & 0xffff + )); + + //grab a managed buffer for each index + for (size_t i = 0; i < buffs.size(); i++){ + buffs[i] = trans[i]->get_send_buff(timeout); + if (not buffs[i].get()) return false; + buffs[i]->cast()[0] = next_seq; + } + return true; + } + //state management for the vrt packet handler code vrt_packet_handler::recv_state packet_handler_recv_state; vrt_packet_handler::send_state packet_handler_send_state; @@ -146,7 +172,9 @@ void usrp2_impl::io_init(void){ //send a small data packet so the usrp2 knows the udp source port BOOST_FOREACH(zero_copy_if::sptr data_transport, _data_transports){ managed_send_buffer::sptr send_buff = data_transport->get_send_buff(); - static const boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); + static const boost::uint32_t data = uhd::htonx( + boost::uint32_t(USRP2_INVALID_VRT_HEADER) + ); std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) @@ -183,23 +211,10 @@ bool usrp2_impl::recv_async_msg( /*********************************************************************** * Send Data **********************************************************************/ -static bool get_send_buffs( - const std::vector &trans, - vrt_packet_handler::managed_send_buffs_t &buffs, - double timeout -){ - UHD_ASSERT_THROW(trans.size() == buffs.size()); - bool good = true; - for (size_t i = 0; i < buffs.size(); i++){ - buffs[i] = trans[i]->get_send_buff(timeout); - good = good and (buffs[i].get() != NULL); - } - return good; -} - size_t usrp2_impl::get_max_send_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + vrt_send_header_offset_words32*sizeof(boost::uint32_t) - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; const size_t bpp = _data_transports.front()->get_send_frame_size() - hdr_size; @@ -218,8 +233,9 @@ size_t usrp2_impl::send( io_type, _tx_otw_type, //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_pack_be, - boost::bind(&get_send_buffs, _data_transports, _1, timeout), - get_max_send_samps_per_packet() + boost::bind(&usrp2_impl::io_impl::get_send_buffs, _io_impl.get(), _data_transports, _1, timeout), + get_max_send_samps_per_packet(), + vrt_send_header_offset_words32 ); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index a680708ad..8429a2593 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -17,7 +17,7 @@ #include "usrp2_impl.hpp" #include -#include +#include #include #include #include @@ -128,7 +128,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){ //create a ctrl and data transport for each address std::vector ctrl_transports; - std::vector data_transports; + std::vector data_transports; BOOST_FOREACH(const std::string &addr, std::split_string(device_addr["addr"])){ ctrl_transports.push_back(udp_simple::make_connected( @@ -154,7 +154,7 @@ UHD_STATIC_BLOCK(register_usrp2_device){ **********************************************************************/ usrp2_impl::usrp2_impl( std::vector ctrl_transports, - std::vector data_transports + std::vector data_transports ): _data_transports(data_transports) { diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 558726a2b..6d35e925d 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -33,7 +33,7 @@ #include #include #include //mtu -#include +#include #include #include @@ -178,7 +178,7 @@ public: */ usrp2_impl( std::vector ctrl_transports, - std::vector data_transports + std::vector data_transports ); ~usrp2_impl(void); @@ -208,7 +208,7 @@ private: uhd::dict _mboard_dict; //io impl methods and members - std::vector _data_transports; + std::vector _data_transports; uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); -- cgit v1.2.3 From 37f1f1451f65aace9ca978ac3edcaa31d16e8c0d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 18:04:37 -0700 Subject: usrp2: add fc control registers, use small timeout for control packets again --- host/lib/usrp/usrp2/usrp2_iface.cpp | 12 +----------- host/lib/usrp/usrp2/usrp2_regs.hpp | 5 +++++ 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 2d450bfc6..6fdde7b2e 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -30,17 +30,7 @@ using namespace uhd; using namespace uhd::transport; -/*! - * FIXME: large timeout, ethernet pause frames... - * - * Use a large timeout to work-around the fact that - * flow-control may throttle outgoing control packets - * due to its use of ethernet pause frames. - * - * This will be fixed when host-based flow control is implemented, - * along with larger incoming send buffers using the on-board SRAM. - */ -static const size_t CONTROL_TIMEOUT_MS = 3000; //3 seconds +static const size_t CONTROL_TIMEOUT_MS = 200; class usrp2_iface_impl : public usrp2_iface{ public: diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 064ad4e95..bdd5194f9 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -193,9 +193,14 @@ #define U2_REG_TX_CTRL_CLEAR_STATE _SR_ADDR(SR_TX_CTRL + 1) #define U2_REG_TX_CTRL_REPORT_SID _SR_ADDR(SR_TX_CTRL + 2) #define U2_REG_TX_CTRL_POLICY _SR_ADDR(SR_TX_CTRL + 3) +#define U2_REG_TX_CTRL_CYCLES_PER_ACK _SR_ADDR(SR_TX_CTRL + 4) +#define U2_REG_TX_CTRL_PACKETS_PER_ACK _SR_ADDR(SR_TX_CTRL + 5) #define U2_FLAG_TX_CTRL_POLICY_WAIT (0x1 << 0) #define U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET (0x1 << 1) #define U2_FLAG_TX_CTRL_POLICY_NEXT_BURST (0x1 << 2) +//enable flag for registers: cycles and packets per ack +#define U2_FLAG_TX_CTRL_ACK_ENB (1ul << 31) + #endif /* INCLUDED_USRP2_REGS_HPP */ -- cgit v1.2.3 From 453b450aa2f40f1ab3689855654fd2167f554ccc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 11 Oct 2010 16:31:51 -0700 Subject: usrp2: implemented flow control monitor set registers in mboard impl to enable asyn fc packets modified microblaze code to handle dummy data packet offset --- firmware/microblaze/apps/txrx_uhd.c | 2 +- host/lib/usrp/usrp2/fw_common.h | 2 +- host/lib/usrp/usrp2/io_impl.cpp | 103 +++++++++++++++++++++++++++++++----- host/lib/usrp/usrp2/mboard_impl.cpp | 14 +++-- host/lib/usrp/usrp2/usrp2_impl.cpp | 4 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 7 ++- 6 files changed, 110 insertions(+), 22 deletions(-) (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 1dd6e80ac..e38eb621d 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -372,7 +372,7 @@ eth_pkt_inspector(dbsm_t *sm, int bufno) // In the future, a hardware state machine will do this... if ( //warning! magic numbers approaching.... (((buff + ((2 + 14 + 20)/sizeof(uint32_t)))[0] & 0xffff) == USRP2_UDP_DATA_PORT) && - ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != USRP2_INVALID_VRT_HEADER) + ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[1] != USRP2_INVALID_VRT_HEADER) ) return false; //test if its an ip recovery packet diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index e812e1221..783e5c772 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -34,7 +34,7 @@ extern "C" { //fpga and firmware compatibility numbers #define USRP2_FPGA_COMPAT_NUM 2 -#define USRP2_FW_COMPAT_NUM 6 +#define USRP2_FW_COMPAT_NUM 7 //used to differentiate control packets over data port #define USRP2_INVALID_VRT_HEADER 0 diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index b7585afe9..6d5eb488c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -32,6 +32,9 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; +/*********************************************************************** + * constants + **********************************************************************/ static const int underflow_flags = 0 | async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET @@ -39,6 +42,67 @@ static const int underflow_flags = 0 static const size_t vrt_send_header_offset_words32 = 1; +/*********************************************************************** + * flow control monitor for a single tx channel + * - the pirate thread calls update + * - the get send buffer calls check + **********************************************************************/ +class flow_control_monitor{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new flow control monitor. + * \param max_seqs_out num seqs before throttling + */ + flow_control_monitor(size_t max_seqs_out){ + _last_seq_out = 0; + _last_seq_ack = 0; + _max_seqs_out = max_seqs_out; + } + + /*! + * Check the flow control condition. + * \param seq the sequence to go out + * \param timeout the timeout in seconds + * \return false on timeout + */ + UHD_INLINE bool check_fc_condition(boost::uint16_t seq, double timeout){ + boost::unique_lock lock(_fc_mutex); + _last_seq_out = seq; + return _fc_cond.timed_wait( + lock, + boost::posix_time::microseconds(long(timeout*1e6)), + boost::bind(&flow_control_monitor::ready, this) + ); + } + + /*! + * Update the flow control condition. + * \param seq the last sequence number to be ACK'd + */ + UHD_INLINE void update_fc_condition(boost::uint16_t seq){ + boost::unique_lock lock(_fc_mutex); + _last_seq_ack = seq; + lock.unlock(); + _fc_cond.notify_one(); + } + +private: + bool ready(void){ + //return true; + //std::cout << "_last_seq_out " << _last_seq_out << std::endl; + //std::cout << "_last_seq_ack " << _last_seq_ack << std::endl; + //std::cout << "boost::uint16_t(_last_seq_out -_last_seq_ack) " << boost::uint16_t(_last_seq_out -_last_seq_ack) << std::endl; + return boost::uint16_t(_last_seq_out -_last_seq_ack) < boost::uint16_t(_max_seqs_out); + } + + boost::mutex _fc_mutex; + boost::condition _fc_cond; + boost::uint16_t _last_seq_out, _last_seq_ack; + size_t _max_seqs_out; +}; + /*********************************************************************** * io impl details (internal to this file) * - pirate crew @@ -49,12 +113,14 @@ static const size_t vrt_send_header_offset_words32 = 1; struct usrp2_impl::io_impl{ typedef alignment_buffer alignment_buffer_type; - io_impl(size_t num_frames, size_t width): + io_impl(size_t num_recv_frames, size_t send_frame_size, size_t width): packet_handler_recv_state(width), - recv_pirate_booty(alignment_buffer_type::make(num_frames, width)), + recv_pirate_booty(alignment_buffer_type::make(num_recv_frames, width)), async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) { - /* NOP */ + for (size_t i = 0; i < width; i++) fc_mons.push_back( + flow_control_monitor::sptr(new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size)) + ); } ~io_impl(void){ @@ -76,19 +142,22 @@ struct usrp2_impl::io_impl{ UHD_ASSERT_THROW(trans.size() == buffs.size()); //calculate the 16-bit sequence number for the special header - const boost::uint32_t next_seq = uhd::htonx(boost::uint32_t( - packet_handler_send_state.next_packet_seq & 0xffff - )); + const boost::uint16_t seq_num = boost::uint16_t(packet_handler_send_state.next_packet_seq & 0xffff); + const boost::uint32_t fc_word32 = uhd::htonx(boost::uint32_t(seq_num)); //grab a managed buffer for each index for (size_t i = 0; i < buffs.size(); i++){ + if (not fc_mons[i]->check_fc_condition(seq_num, timeout)) return false; buffs[i] = trans[i]->get_send_buff(timeout); if (not buffs[i].get()) return false; - buffs[i]->cast()[0] = next_seq; + buffs[i]->cast()[0] = fc_word32; } return true; } + //flow control monitors + std::vector fc_mons; + //state management for the vrt packet handler code vrt_packet_handler::recv_state packet_handler_recv_state; vrt_packet_handler::send_state packet_handler_send_state; @@ -138,6 +207,13 @@ void usrp2_impl::io_impl::recv_pirate_loop( ); metadata.event_code = vrt_packet_handler::get_context_code(vrt_hdr, if_packet_info); + //catch the flow control packets and react + if (metadata.event_code == 0){ + boost::uint32_t fc_word32 = uhd::ntohx((vrt_hdr + if_packet_info.num_header_words32)[1]); + this->fc_mons[index]->update_fc_condition(fc_word32 & 0xffff); + continue; + } + //print the famous U, and push the metadata into the message queue if (metadata.event_code & underflow_flags) std::cerr << "U" << std::flush; async_msg_fifo->push_with_pop_on_full(metadata); @@ -172,21 +248,22 @@ void usrp2_impl::io_init(void){ //send a small data packet so the usrp2 knows the udp source port BOOST_FOREACH(zero_copy_if::sptr data_transport, _data_transports){ managed_send_buffer::sptr send_buff = data_transport->get_send_buff(); - static const boost::uint32_t data = uhd::htonx( - boost::uint32_t(USRP2_INVALID_VRT_HEADER) - ); + static const boost::uint32_t data[2] = { + uhd::htonx(boost::uint32_t(0 /* don't care seq num */)), + uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER)) + }; std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) while (data_transport->get_recv_buff().get()){}; } - //the number of recv frames is the number for the first transport //the assumption is that all data transports should be identical - size_t num_frames = _data_transports.front()->get_num_recv_frames(); + const size_t num_recv_frames = _data_transports.front()->get_num_recv_frames(); + const size_t send_frame_size = _data_transports.front()->get_send_frame_size(); //create new io impl - _io_impl = UHD_PIMPL_MAKE(io_impl, (num_frames, _data_transports.size())); + _io_impl = UHD_PIMPL_MAKE(io_impl, (num_recv_frames, send_frame_size, _data_transports.size())); //create a new pirate thread for each zc if (yarr!!) for (size_t i = 0; i < _data_transports.size(); i++){ diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index a0e6adfad..37e69b39d 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -38,10 +38,11 @@ using namespace uhd::usrp; usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, - size_t recv_frame_size + size_t recv_samps_per_packet, + size_t send_bytes_per_packet ): _index(index), - _recv_frame_size(recv_frame_size) + _recv_samps_per_packet(recv_samps_per_packet) { //make a new interface for usrp2 stuff _iface = usrp2_iface::make(ctrl_transport); @@ -75,7 +76,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); //init the rx control registers - _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_frame_size); + _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_samps_per_packet); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 @@ -93,6 +94,11 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1); //sid 1 (different from rx) _iface->poke32(U2_REG_TX_CTRL_POLICY, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); + const size_t cycles_per_ack = size_t(_clock_ctrl->get_master_clock_rate()/100); //100 aps + //_iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | cycles_per_ack); //FIXME total pause frames + static const double sram_frac = 1.0/8.0; //fraction of sram to fill before ack + const size_t packets_per_ack = size_t(usrp2_impl::sram_bytes*sram_frac/send_bytes_per_packet); + _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | packets_per_ack); //init the ddc init_ddc_config(); @@ -178,7 +184,7 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word( - stream_cmd, _recv_frame_size + stream_cmd, _recv_samps_per_packet )); _iface->poke32(U2_REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); _iface->poke32(U2_REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 8429a2593..79bf2b260 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -173,7 +173,9 @@ usrp2_impl::usrp2_impl( //create a new mboard handler for each control transport for(size_t i = 0; i < ctrl_transports.size(); i++){ _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( - i, ctrl_transports[i], this->get_max_recv_samps_per_packet() + i, ctrl_transports[i], + this->get_max_recv_samps_per_packet(), + _data_transports[i]->get_send_frame_size() ))); //use an empty name when there is only one mboard std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast(i) : ""; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 6d35e925d..2077b0a50 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -84,7 +84,8 @@ public: usrp2_mboard_impl( size_t index, uhd::transport::udp_simple::sptr, - size_t recv_frame_size + size_t recv_samps_per_packet, + size_t send_bytes_per_packet ); ~usrp2_mboard_impl(void); @@ -95,7 +96,7 @@ public: private: size_t _index; int _rev_hi, _rev_lo; - const size_t _recv_frame_size; + const size_t _recv_samps_per_packet; //properties for this mboard void get(const wax::obj &, wax::obj &); @@ -171,6 +172,8 @@ private: */ class usrp2_impl : public uhd::device{ public: + static const size_t sram_bytes = size_t(1 << 20); + /*! * Create a new usrp2 impl base. * \param ctrl_transports the udp transports for control -- cgit v1.2.3 From 1314feb429b8c2713d9fd0e9da077825d0a9c3bc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 11 Oct 2010 18:09:56 -0700 Subject: usrp2: use 32-bit flow control sequence numbers --- host/include/uhd/types/metadata.hpp | 4 ++-- host/lib/usrp/usrp2/fw_common.h | 2 +- host/lib/usrp/usrp2/io_impl.cpp | 29 ++++++++++++----------------- 3 files changed, 15 insertions(+), 20 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 65952941c..96c4ad0d3 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -130,7 +130,7 @@ namespace uhd{ /*! * Event codes: - * - success: a packet was successfully transmitted + * - eob ack: an eob packet was successfully transmitted * - underflow: an internal send buffer has emptied * - sequence error: packet loss between host and device * - time error: packet had time that was late (or too early) @@ -138,7 +138,7 @@ namespace uhd{ * - sequence error in burst: packet loss within a burst */ enum event_code_t { - EVENT_CODE_SUCCESS = 0x1, + EVENT_CODE_EOB_ACK = 0x1, EVENT_CODE_UNDERFLOW = 0x2, EVENT_CODE_SEQ_ERROR = 0x4, EVENT_CODE_TIME_ERROR = 0x8, diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 783e5c772..2cd3ee595 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -33,7 +33,7 @@ extern "C" { #endif //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 2 +#define USRP2_FPGA_COMPAT_NUM 3 #define USRP2_FW_COMPAT_NUM 7 //used to differentiate control packets over data port diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 6d5eb488c..2d1ebe57b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -49,13 +49,14 @@ static const size_t vrt_send_header_offset_words32 = 1; **********************************************************************/ class flow_control_monitor{ public: + typedef boost::uint32_t seq_type; typedef boost::shared_ptr sptr; /*! * Make a new flow control monitor. * \param max_seqs_out num seqs before throttling */ - flow_control_monitor(size_t max_seqs_out){ + flow_control_monitor(seq_type max_seqs_out){ _last_seq_out = 0; _last_seq_ack = 0; _max_seqs_out = max_seqs_out; @@ -67,7 +68,7 @@ public: * \param timeout the timeout in seconds * \return false on timeout */ - UHD_INLINE bool check_fc_condition(boost::uint16_t seq, double timeout){ + UHD_INLINE bool check_fc_condition(seq_type seq, double timeout){ boost::unique_lock lock(_fc_mutex); _last_seq_out = seq; return _fc_cond.timed_wait( @@ -81,7 +82,7 @@ public: * Update the flow control condition. * \param seq the last sequence number to be ACK'd */ - UHD_INLINE void update_fc_condition(boost::uint16_t seq){ + UHD_INLINE void update_fc_condition(seq_type seq){ boost::unique_lock lock(_fc_mutex); _last_seq_ack = seq; lock.unlock(); @@ -90,17 +91,12 @@ public: private: bool ready(void){ - //return true; - //std::cout << "_last_seq_out " << _last_seq_out << std::endl; - //std::cout << "_last_seq_ack " << _last_seq_ack << std::endl; - //std::cout << "boost::uint16_t(_last_seq_out -_last_seq_ack) " << boost::uint16_t(_last_seq_out -_last_seq_ack) << std::endl; - return boost::uint16_t(_last_seq_out -_last_seq_ack) < boost::uint16_t(_max_seqs_out); + return seq_type(_last_seq_out -_last_seq_ack) < _max_seqs_out; } boost::mutex _fc_mutex; boost::condition _fc_cond; - boost::uint16_t _last_seq_out, _last_seq_ack; - size_t _max_seqs_out; + seq_type _last_seq_out, _last_seq_ack, _max_seqs_out; }; /*********************************************************************** @@ -141,16 +137,15 @@ struct usrp2_impl::io_impl{ ){ UHD_ASSERT_THROW(trans.size() == buffs.size()); - //calculate the 16-bit sequence number for the special header - const boost::uint16_t seq_num = boost::uint16_t(packet_handler_send_state.next_packet_seq & 0xffff); - const boost::uint32_t fc_word32 = uhd::htonx(boost::uint32_t(seq_num)); + //calculate the flow control word + const boost::uint32_t fc_word32 = packet_handler_send_state.next_packet_seq; //grab a managed buffer for each index for (size_t i = 0; i < buffs.size(); i++){ - if (not fc_mons[i]->check_fc_condition(seq_num, timeout)) return false; + if (not fc_mons[i]->check_fc_condition(fc_word32, timeout)) return false; buffs[i] = trans[i]->get_send_buff(timeout); if (not buffs[i].get()) return false; - buffs[i]->cast()[0] = fc_word32; + buffs[i]->cast()[0] = uhd::htonx(fc_word32); } return true; } @@ -209,8 +204,8 @@ void usrp2_impl::io_impl::recv_pirate_loop( //catch the flow control packets and react if (metadata.event_code == 0){ - boost::uint32_t fc_word32 = uhd::ntohx((vrt_hdr + if_packet_info.num_header_words32)[1]); - this->fc_mons[index]->update_fc_condition(fc_word32 & 0xffff); + boost::uint32_t fc_word32 = (vrt_hdr + if_packet_info.num_header_words32)[1]; + this->fc_mons[index]->update_fc_condition(uhd::ntohx(fc_word32)); continue; } -- cgit v1.2.3 From d54fd2abffd8849bf41a5f8084a828e6472ba342 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 11 Oct 2010 18:21:16 -0700 Subject: usrp2: use select rather than manually polling the simple udp socket --- host/include/uhd/transport/udp_simple.hpp | 4 +-- host/lib/transport/udp_simple.cpp | 44 +++++++++++++++---------------- host/lib/usrp/usrp2/usrp2_iface.cpp | 4 +-- host/lib/usrp/usrp2/usrp2_impl.cpp | 5 +--- 4 files changed, 26 insertions(+), 31 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp index c84393ecf..83f895ba9 100644 --- a/host/include/uhd/transport/udp_simple.hpp +++ b/host/include/uhd/transport/udp_simple.hpp @@ -73,10 +73,10 @@ public: * Receive into the provided buffer. * Blocks until data is received or a timeout occurs. * \param buff a mutable buffer to receive into - * \param timeout_ms the timeout in milliseconds + * \param timeout the timeout in seconds * \return the number of bytes received or zero on timeout */ - virtual size_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms) = 0; + virtual size_t recv(const boost::asio::mutable_buffer &buff, double timeout = 0.1) = 0; }; }} //namespace diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp index 89750f99d..5829b462b 100644 --- a/host/lib/transport/udp_simple.cpp +++ b/host/lib/transport/udp_simple.cpp @@ -27,23 +27,25 @@ using namespace uhd::transport; * Helper Functions **********************************************************************/ /*! - * A receive timeout for a socket: - * - * It seems that asio cannot have timeouts with synchronous io. - * However, we can implement a polling loop that will timeout. - * This is okay bacause this is the slow-path implementation. - * + * Wait for available data or timeout. * \param socket the asio socket - * \param timeout_ms the timeout in milliseconds + * \param timeout the timeout in seconds + * \return false for timeout, true for data */ -static void reasonable_recv_timeout( - boost::asio::ip::udp::socket &socket, size_t timeout_ms +static bool wait_available( + boost::asio::ip::udp::socket &socket, double timeout ){ - boost::asio::deadline_timer timer(socket.get_io_service()); - timer.expires_from_now(boost::posix_time::milliseconds(timeout_ms)); - while (not (socket.available() or timer.expires_from_now().is_negative())){ - boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - } + //setup timeval for timeout + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = long(timeout*1e6); + + //setup rset for timeout + fd_set rset; + FD_ZERO(&rset); + FD_SET(socket.native(), &rset); + + return ::select(socket.native()+1, &rset, NULL, NULL, &tv) > 0; } /*********************************************************************** @@ -57,7 +59,7 @@ public: //send/recv size_t send(const boost::asio::const_buffer &); - size_t recv(const boost::asio::mutable_buffer &, size_t); + size_t recv(const boost::asio::mutable_buffer &, double); private: boost::asio::ip::udp::socket *_socket; @@ -86,9 +88,8 @@ size_t udp_connected_impl::send(const boost::asio::const_buffer &buff){ return _socket->send(boost::asio::buffer(buff)); } -size_t udp_connected_impl::recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms){ - reasonable_recv_timeout(*_socket, timeout_ms); - if (not _socket->available()) return 0; +size_t udp_connected_impl::recv(const boost::asio::mutable_buffer &buff, double timeout){ + if (not wait_available(*_socket, timeout)) return 0; return _socket->receive(boost::asio::buffer(buff)); } @@ -103,7 +104,7 @@ public: //send/recv size_t send(const boost::asio::const_buffer &); - size_t recv(const boost::asio::mutable_buffer &, size_t); + size_t recv(const boost::asio::mutable_buffer &, double); private: boost::asio::ip::udp::socket *_socket; @@ -137,9 +138,8 @@ size_t udp_broadcast_impl::send(const boost::asio::const_buffer &buff){ return _socket->send_to(boost::asio::buffer(buff), _receiver_endpoint); } -size_t udp_broadcast_impl::recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms){ - reasonable_recv_timeout(*_socket, timeout_ms); - if (not _socket->available()) return 0; +size_t udp_broadcast_impl::recv(const boost::asio::mutable_buffer &buff, double timeout){ + if (not wait_available(*_socket, timeout)) return 0; boost::asio::ip::udp::endpoint sender_endpoint; return _socket->receive_from(boost::asio::buffer(buff), sender_endpoint); } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 6fdde7b2e..55c42567e 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -30,8 +30,6 @@ using namespace uhd; using namespace uhd::transport; -static const size_t CONTROL_TIMEOUT_MS = 200; - class usrp2_iface_impl : public usrp2_iface{ public: /*********************************************************************** @@ -177,7 +175,7 @@ public: boost::uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; //allocate max bytes for recv const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast(usrp2_ctrl_data_in_mem); while(true){ - size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem), CONTROL_TIMEOUT_MS); + size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem)); if(len >= sizeof(boost::uint32_t) and ntohl(ctrl_data_in->proto_ver) != USRP2_FW_COMPAT_NUM){ throw std::runtime_error(str(boost::format( "Expected protocol compatibility number %d, but got %d:\n" diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 79bf2b260..1d9f25019 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -35,9 +35,6 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -//! wait this long for a control response when discovering devices -static const size_t DISCOVERY_TIMEOUT_MS = 100; - /*********************************************************************** * Helper Functions **********************************************************************/ @@ -99,7 +96,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ boost::uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; //allocate max bytes for recv const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast(usrp2_ctrl_data_in_mem); while(true){ - size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem), DISCOVERY_TIMEOUT_MS); + size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem)); //std::cout << len << "\n"; if (len > offsetof(usrp2_ctrl_data_t, data)){ //handle the received data -- cgit v1.2.3 From b49e2955b0f68d59e7903f89a26c39dc9b3614fd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 11 Oct 2010 18:38:06 -0700 Subject: usrp2: enable the cycles per ack, and drain recv without the timeout (fixes previous conflict) --- host/lib/usrp/usrp2/io_impl.cpp | 2 +- host/lib/usrp/usrp2/mboard_impl.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 2d1ebe57b..c9271cc8c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -250,7 +250,7 @@ void usrp2_impl::io_init(void){ std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff().get()){}; + while (data_transport->get_recv_buff(0).get()){}; } //the assumption is that all data transports should be identical diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 37e69b39d..ddf147c8d 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -95,7 +95,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1); //sid 1 (different from rx) _iface->poke32(U2_REG_TX_CTRL_POLICY, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); const size_t cycles_per_ack = size_t(_clock_ctrl->get_master_clock_rate()/100); //100 aps - //_iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | cycles_per_ack); //FIXME total pause frames + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | cycles_per_ack); static const double sram_frac = 1.0/8.0; //fraction of sram to fill before ack const size_t packets_per_ack = size_t(usrp2_impl::sram_bytes*sram_frac/send_bytes_per_packet); _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | packets_per_ack); @@ -121,7 +121,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( } usrp2_mboard_impl::~usrp2_mboard_impl(void){ - /* NOP */ + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, 0); + _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_ACK, 0); } /*********************************************************************** -- cgit v1.2.3 From f9755b0ab33eb20abb5689893061f3b4039505fd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 12 Oct 2010 10:55:07 -0700 Subject: uhd: test eob ack message, usrp2: remove rx drain on init with the promise of a reset register --- host/examples/test_async_messages.cpp | 32 ++++++++++++++++++++------------ host/lib/usrp/usrp2/io_impl.cpp | 2 -- host/lib/usrp/usrp2/mboard_impl.cpp | 5 ----- 3 files changed, 20 insertions(+), 19 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index e4a996ef5..fa39bcde6 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -27,13 +27,13 @@ namespace po = boost::program_options; /*! - * Test that no messages are received: + * Test the eob ack message: * Send a burst of many samples that will fragment internally. - * We expect to not get any async messages. + * We expect to get an eob ack async message. */ -void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ +void test_ack_async_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); - std::cout << "Test no async message... " << std::flush; + std::cout << "Test eob ack message... " << std::flush; uhd::tx_metadata_t md; md.start_of_burst = true; @@ -50,19 +50,27 @@ void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ ); uhd::async_metadata_t async_md; - if (dev->recv_async_msg(async_md)){ + if (not dev->recv_async_msg(async_md)){ std::cout << boost::format( "failed:\n" - " Got unexpected event code 0x%x.\n" - ) % async_md.event_code << std::endl; - //clear the async messages - while (dev->recv_async_msg(async_md, 0)){}; + " Async message recv timed out.\n" + ) << std::endl; + return; } - else{ + + switch(async_md.event_code){ + case uhd::async_metadata_t::EVENT_CODE_EOB_ACK: std::cout << boost::format( "success:\n" - " Did not get an async message.\n" + " Got event code eob ack message.\n" ) << std::endl; + break; + + default: + std::cout << boost::format( + "failed:\n" + " Got unexpected event code 0x%x.\n" + ) % async_md.event_code << std::endl; } } @@ -195,7 +203,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //------------------------------------------------------------------ // begin asyc messages test //------------------------------------------------------------------ - test_no_async_message(sdev); + test_ack_async_message(sdev); test_underflow_message(sdev); test_time_error_message(sdev); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index c9271cc8c..48ff7d509 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -249,8 +249,6 @@ void usrp2_impl::io_init(void){ }; std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); - //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff(0).get()){}; } //the assumption is that all data transports should be identical diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index ddf147c8d..65066f125 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -70,11 +70,6 @@ usrp2_mboard_impl::usrp2_mboard_impl( _allowed_decim_and_interp_rates.push_back(i); } - //Issue a stop streaming command (in case it was left running). - //Since this command is issued before the networking is setup, - //most if not all junk packets will never make it to the socket. - this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); - //init the rx control registers _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_samps_per_packet); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); -- cgit v1.2.3 From 35eda148fc3979c022c58166fa628d5b7dbfd80b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 13 Oct 2010 11:59:15 -0700 Subject: usrp2: increment tx sequence after commit --- host/lib/transport/vrt_packet_handler.hpp | 3 ++- host/lib/usrp/usrp2/io_impl.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 939517411..d5f03de0e 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -318,7 +318,7 @@ template UHD_INLINE T get_context_code( ){ //load the rest of the if_packet_info in here if_packet_info.num_payload_words32 = (num_samps*chans_per_otw_buff*otw_type.get_sample_size())/sizeof(boost::uint32_t); - if_packet_info.packet_count = state.next_packet_seq++; + if_packet_info.packet_count = state.next_packet_seq; //get send buffers for each channel managed_send_buffs_t send_buffs(buffs.size()/chans_per_otw_buff); @@ -345,6 +345,7 @@ template UHD_INLINE T get_context_code( size_t num_bytes_total = (vrt_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t); send_buffs[i]->commit(num_bytes_total); } + state.next_packet_seq++; //increment sequence after commits return num_samps; } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 48ff7d509..d6f7e8476 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -211,6 +211,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( //print the famous U, and push the metadata into the message queue if (metadata.event_code & underflow_flags) std::cerr << "U" << std::flush; + //else std::cout << "metadata.event_code " << metadata.event_code << std::endl; async_msg_fifo->push_with_pop_on_full(metadata); continue; } -- cgit v1.2.3 From c6042a0b317a6f74d2b74b259f14431f5c8246d4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 13 Oct 2010 14:28:52 -0700 Subject: usrp2: added docs on flow control ricer args and using usrp2 with a switch implemented flow control param hints in the mboard impl --- host/docs/transport.rst | 11 +++++++++++ host/docs/usrp2.rst | 15 +++++++-------- host/lib/usrp/usrp2/mboard_impl.cpp | 22 ++++++++++++++-------- host/lib/usrp/usrp2/usrp2_impl.cpp | 8 +++++--- host/lib/usrp/usrp2/usrp2_impl.hpp | 7 +++++-- host/lib/usrp/usrp2/usrp2_regs.hpp | 8 ++++---- 6 files changed, 46 insertions(+), 25 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/docs/transport.rst b/host/docs/transport.rst index 432db4bb5..2f730f8e4 100644 --- a/host/docs/transport.rst +++ b/host/docs/transport.rst @@ -39,6 +39,17 @@ The following parameters can be used to alter the transport's default behavior: **Note:** num_send_frames and concurrency_hint will not have an effect as the asynchronous send implementation is currently disabled. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Flow control parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The host-based flow control expects periodic update packets from the device. +These update packets inform the host of the last packet consumed by the device, +which allows the host to determine throttling conditions for the transmission of packets. +The following mechanisms affect the transmission of periodic update packets: + +* **ups_per_fifo:** The number of update packets for each FIFO's worth of bytes sent into the device +* **ups_per_sec:** The number of update packets per second + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Resize socket buffers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 1ebab388a..8fa666a49 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -39,12 +39,10 @@ Use the card burner tool (windows) ------------------------------------------------------------------------ Setup networking ------------------------------------------------------------------------ -The USRP2 only supports gigabit ethernet, and -will not work with a 10/100 Mbps interface. -Because the USRP2 uses gigabit ethernet pause frames for flow control, -you cannot use multiple USRP2s with a switch or a hub. -It is recommended that each USRP2 be plugged directly into its own -dedicated gigabit ethernet interface on the host computer. +The USRP2 only supports gigabit ethernet, +and will not work with a 10/100 Mbps interface. +However, a 10/100 Mbps interface can be connected indirectly +to a USRP2 through a gigabit ethernet switch. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Setup the host interface @@ -63,8 +61,9 @@ It is recommended that you change or disable your firewall settings. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Multiple device configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -As described above, you will need one ethernet interface per USRP2. -Each ethernet interface should have its own subnet, +For maximum throughput, one ethernet interface per USRP2 is recommended, +although multiple devices may be connected via a gigabit ethernet switch. +In any case, each ethernet interface should have its own subnet, and the corresponding USRP2 device should be assigned an address in that subnet. Example: diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 65066f125..5210eee94 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -39,7 +39,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, size_t recv_samps_per_packet, - size_t send_bytes_per_packet + size_t send_bytes_per_packet, + const device_addr_t &flow_control_hints ): _index(index), _recv_samps_per_packet(recv_samps_per_packet) @@ -89,11 +90,16 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1); //sid 1 (different from rx) _iface->poke32(U2_REG_TX_CTRL_POLICY, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); - const size_t cycles_per_ack = size_t(_clock_ctrl->get_master_clock_rate()/100); //100 aps - _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | cycles_per_ack); - static const double sram_frac = 1.0/8.0; //fraction of sram to fill before ack - const size_t packets_per_ack = size_t(usrp2_impl::sram_bytes*sram_frac/send_bytes_per_packet); - _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_ACK, U2_FLAG_TX_CTRL_ACK_ENB | packets_per_ack); + + //setting the cycles per update + const double ups_per_sec = flow_control_hints.cast("ups_per_sec", 100); + const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec); + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up); + + //setting the packets per update + const double ups_per_fifo = flow_control_hints.cast("ups_per_fifo", 8); + const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/send_bytes_per_packet); + _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_UP, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up); //init the ddc init_ddc_config(); @@ -116,8 +122,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( } usrp2_mboard_impl::~usrp2_mboard_impl(void){ - _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_ACK, 0); - _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_ACK, 0); + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, 0); + _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_UP, 0); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 1d9f25019..e271f839c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -138,7 +138,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){ //create the usrp2 implementation guts return device::sptr( - new usrp2_impl(ctrl_transports, data_transports) + new usrp2_impl(ctrl_transports, data_transports, device_addr) ); } @@ -151,7 +151,8 @@ UHD_STATIC_BLOCK(register_usrp2_device){ **********************************************************************/ usrp2_impl::usrp2_impl( std::vector ctrl_transports, - std::vector data_transports + std::vector data_transports, + const device_addr_t &flow_control_hints ): _data_transports(data_transports) { @@ -172,7 +173,8 @@ usrp2_impl::usrp2_impl( _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( i, ctrl_transports[i], this->get_max_recv_samps_per_packet(), - _data_transports[i]->get_send_frame_size() + _data_transports[i]->get_send_frame_size(), + flow_control_hints ))); //use an empty name when there is only one mboard std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast(i) : ""; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 2077b0a50..3aa6e9cd5 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -85,7 +85,8 @@ public: size_t index, uhd::transport::udp_simple::sptr, size_t recv_samps_per_packet, - size_t send_bytes_per_packet + size_t send_bytes_per_packet, + const uhd::device_addr_t &flow_control_hints ); ~usrp2_mboard_impl(void); @@ -178,10 +179,12 @@ public: * Create a new usrp2 impl base. * \param ctrl_transports the udp transports for control * \param data_transports the udp transports for data + * \param flow_control_hints optional flow control params */ usrp2_impl( std::vector ctrl_transports, - std::vector data_transports + std::vector data_transports, + const uhd::device_addr_t &flow_control_hints ); ~usrp2_impl(void); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index bdd5194f9..c3a4d22de 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -193,14 +193,14 @@ #define U2_REG_TX_CTRL_CLEAR_STATE _SR_ADDR(SR_TX_CTRL + 1) #define U2_REG_TX_CTRL_REPORT_SID _SR_ADDR(SR_TX_CTRL + 2) #define U2_REG_TX_CTRL_POLICY _SR_ADDR(SR_TX_CTRL + 3) -#define U2_REG_TX_CTRL_CYCLES_PER_ACK _SR_ADDR(SR_TX_CTRL + 4) -#define U2_REG_TX_CTRL_PACKETS_PER_ACK _SR_ADDR(SR_TX_CTRL + 5) +#define U2_REG_TX_CTRL_CYCLES_PER_UP _SR_ADDR(SR_TX_CTRL + 4) +#define U2_REG_TX_CTRL_PACKETS_PER_UP _SR_ADDR(SR_TX_CTRL + 5) #define U2_FLAG_TX_CTRL_POLICY_WAIT (0x1 << 0) #define U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET (0x1 << 1) #define U2_FLAG_TX_CTRL_POLICY_NEXT_BURST (0x1 << 2) -//enable flag for registers: cycles and packets per ack -#define U2_FLAG_TX_CTRL_ACK_ENB (1ul << 31) +//enable flag for registers: cycles and packets per update packet +#define U2_FLAG_TX_CTRL_UP_ENB (1ul << 31) #endif /* INCLUDED_USRP2_REGS_HPP */ -- cgit v1.2.3 From c25fd486f82d646cf8a08582c6e7105fd3c58c45 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 13 Oct 2010 15:01:45 -0700 Subject: udp: fix to use concurrency hint, default hint is zero when no async enabled --- host/lib/transport/udp_zero_copy_asio.cpp | 31 ++++++++++++++++++++----------- host/lib/usrp/usrp2/io_impl.cpp | 1 + 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index d84aeefdd..938ae4473 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -59,16 +59,23 @@ static const size_t DEFAULT_NUM_RECV_FRAMES = 32; #else static const size_t DEFAULT_NUM_RECV_FRAMES = MIN_RECV_SOCK_BUFF_SIZE/udp_simple::mtu; #endif + //The non-async send only ever requires a single frame //because the buffer will be committed before a new get. #ifdef USE_ASIO_ASYNC_SEND static const size_t DEFAULT_NUM_SEND_FRAMES = 32; #else -static const size_t DEFAULT_NUM_SEND_FRAMES = MIN_SEND_SOCK_BUFF_SIZE/udp_simple::mtu;; +static const size_t DEFAULT_NUM_SEND_FRAMES = MIN_SEND_SOCK_BUFF_SIZE/udp_simple::mtu; #endif -//a single concurrent thread for io_service seems to be the fastest +//The number of service threads to spawn for async ASIO: +//A single concurrent thread for io_service seems to be the fastest. +//Threads are disabled when no async implementations are enabled. +#if defined(USE_ASIO_ASYNC_RECV) || defined(USE_ASIO_ASYNC_SEND) static const size_t CONCURRENCY_HINT = 1; +#else +static const size_t CONCURRENCY_HINT = 0; +#endif /*********************************************************************** * Zero Copy UDP implementation with ASIO: @@ -86,11 +93,12 @@ public: const std::string &port, const device_addr_t &hints ): - _io_service(hints.cast("concurrency_hint", CONCURRENCY_HINT)), _recv_frame_size(size_t(hints.cast("recv_frame_size", udp_simple::mtu))), _num_recv_frames(size_t(hints.cast("num_recv_frames", DEFAULT_NUM_RECV_FRAMES))), _send_frame_size(size_t(hints.cast("send_frame_size", udp_simple::mtu))), - _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_SEND_FRAMES))) + _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_SEND_FRAMES))), + _concurrency_hint(hints.cast("concurrency_hint", CONCURRENCY_HINT)), + _io_service(_concurrency_hint) { //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; @@ -129,7 +137,7 @@ public: //spawn the service threads that will run the io service _work = new asio::io_service::work(_io_service); //new work to delete later - for (size_t i = 0; i < CONCURRENCY_HINT; i++) _thread_group.create_thread( + for (size_t i = 0; i < _concurrency_hint; i++) _thread_group.create_thread( boost::bind(&udp_zero_copy_asio_impl::service, this) ); } @@ -292,12 +300,6 @@ public: size_t get_send_frame_size(void) const {return _send_frame_size;} private: - //asio guts -> socket and service - asio::ip::udp::socket *_socket; - asio::io_service _io_service; - asio::io_service::work *_work; - int _sock_fd; - //memory management -> buffers and fifos boost::thread_group _thread_group; boost::shared_array _send_buffer, _recv_buffer; @@ -305,6 +307,13 @@ private: pending_buffs_type::sptr _pending_recv_buffs, _pending_send_buffs; const size_t _recv_frame_size, _num_recv_frames; const size_t _send_frame_size, _num_send_frames; + + //asio guts -> socket and service + size_t _concurrency_hint; + asio::io_service _io_service; + asio::ip::udp::socket *_socket; + asio::io_service::work *_work; + int _sock_fd; }; /*********************************************************************** diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index d6f7e8476..25fd1c484 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -69,6 +69,7 @@ public: * \return false on timeout */ UHD_INLINE bool check_fc_condition(seq_type seq, double timeout){ + boost::this_thread::disable_interruption di; //disable because the wait can throw boost::unique_lock lock(_fc_mutex); _last_seq_out = seq; return _fc_cond.timed_wait( -- cgit v1.2.3 From 4582a2deb385c0a4849f5d20c44a5469779bcbb2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 14 Oct 2010 11:51:48 -0700 Subject: usrp2: move udp port initialization into mboard impl so its done before async registers are setup --- host/lib/usrp/usrp2/io_impl.cpp | 10 ---------- host/lib/usrp/usrp2/mboard_impl.cpp | 16 ++++++++++++++-- host/lib/usrp/usrp2/usrp2_impl.cpp | 3 +-- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 25fd1c484..8314cf9ae 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -242,16 +242,6 @@ void usrp2_impl::io_impl::recv_pirate_loop( * Helper Functions **********************************************************************/ void usrp2_impl::io_init(void){ - //send a small data packet so the usrp2 knows the udp source port - BOOST_FOREACH(zero_copy_if::sptr data_transport, _data_transports){ - managed_send_buffer::sptr send_buff = data_transport->get_send_buff(); - static const boost::uint32_t data[2] = { - uhd::htonx(boost::uint32_t(0 /* don't care seq num */)), - uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER)) - }; - std::memcpy(send_buff->cast(), &data, sizeof(data)); - send_buff->commit(sizeof(data)); - } //the assumption is that all data transports should be identical const size_t num_recv_frames = _data_transports.front()->get_num_recv_frames(); diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 5210eee94..8f3ae5c1b 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,13 +39,24 @@ using namespace uhd::usrp; usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, + transport::zero_copy_if::sptr data_transport, size_t recv_samps_per_packet, - size_t send_bytes_per_packet, const device_addr_t &flow_control_hints ): _index(index), _recv_samps_per_packet(recv_samps_per_packet) { + //Send a small data packet so the usrp2 knows the udp source port. + //This setup must happen before further initialization occurs + //or the async update packets will cause ICMP destination unreachable. + transport::managed_send_buffer::sptr send_buff = data_transport->get_send_buff(); + static const boost::uint32_t data[2] = { + uhd::htonx(boost::uint32_t(0 /* don't care seq num */)), + uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER)) + }; + std::memcpy(send_buff->cast(), &data, sizeof(data)); + send_buff->commit(sizeof(data)); + //make a new interface for usrp2 stuff _iface = usrp2_iface::make(ctrl_transport); @@ -98,7 +110,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( //setting the packets per update const double ups_per_fifo = flow_control_hints.cast("ups_per_fifo", 8); - const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/send_bytes_per_packet); + const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size()); _iface->poke32(U2_REG_TX_CTRL_PACKETS_PER_UP, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up); //init the ddc diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index e271f839c..afc69f703 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -171,9 +171,8 @@ usrp2_impl::usrp2_impl( //create a new mboard handler for each control transport for(size_t i = 0; i < ctrl_transports.size(); i++){ _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( - i, ctrl_transports[i], + i, ctrl_transports[i], data_transports[i], this->get_max_recv_samps_per_packet(), - _data_transports[i]->get_send_frame_size(), flow_control_hints ))); //use an empty name when there is only one mboard diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 3aa6e9cd5..2531bd6cb 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -84,8 +84,8 @@ public: usrp2_mboard_impl( size_t index, uhd::transport::udp_simple::sptr, + uhd::transport::zero_copy_if::sptr, size_t recv_samps_per_packet, - size_t send_bytes_per_packet, const uhd::device_addr_t &flow_control_hints ); ~usrp2_mboard_impl(void); -- cgit v1.2.3 From 9348c2764dbbdf01e34a3ec7b5c8e74964b355e0 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 14 Oct 2010 21:41:14 -0400 Subject: usrp_e: back out dynamic send/recv samples calculation. --- host/lib/usrp/usrp_e/io_impl.cpp | 6 +++++- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 406b7269f..d89a7db07 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -37,7 +37,7 @@ zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); **********************************************************************/ static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; -static const bool recv_debug = true; +static const bool recv_debug = false; /*********************************************************************** * io impl details (internal to this file) @@ -205,6 +205,7 @@ bool get_send_buffs( return buffs[0].get() != NULL; } +#if 0 size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -213,6 +214,7 @@ size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ size_t bpp = _io_impl->data_xport->get_send_frame_size() - hdr_size; return bpp/_send_otw_type.get_sample_size(); } +#endif size_t usrp_e_impl::send( const std::vector &buffs, size_t num_samps, @@ -234,6 +236,7 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ +#if 0 size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -243,6 +246,7 @@ size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ size_t bpp = _io_impl->data_xport->get_recv_frame_size() - hdr_size; return bpp/_recv_otw_type.get_sample_size(); } +#endif size_t usrp_e_impl::recv( const std::vector &buffs, size_t num_samps, diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 95d80fed5..9799cd645 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -86,8 +86,13 @@ public: size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); bool recv_async_msg(uhd::async_metadata_t &, double); +#if 0 size_t get_max_send_samps_per_packet(void) const; size_t get_max_recv_samps_per_packet(void) const; +#else + size_t get_max_send_samps_per_packet(void) const{return 503;} + size_t get_max_recv_samps_per_packet(void) const{return 503;} +#endif private: //interface to ioctls and file descriptor -- cgit v1.2.3 From 6b203950d9583ab882628311402e26cf40838aa0 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 14 Oct 2010 21:42:10 -0400 Subject: usrp_e: Disable debug. --- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index bc18c490b..274bb043e 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -29,8 +29,8 @@ using namespace uhd; using namespace uhd::transport; -static const bool fp_verbose = true; //fast-path verbose -static const bool sp_verbose = true; //slow-path verbose +static const bool fp_verbose = false; //fast-path verbose +static const bool sp_verbose = false; //slow-path verbose static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout /*********************************************************************** -- cgit v1.2.3 From 972fae172ae30323ed57795ca5a4aad790bac7f9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 15 Oct 2010 14:37:26 -0700 Subject: usrp2: temp fix to send dummy packets and flush so FPGA vita machine are in known state --- host/lib/usrp/usrp2/io_impl.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 8314cf9ae..00061ae47 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -241,6 +241,8 @@ void usrp2_impl::io_impl::recv_pirate_loop( /*********************************************************************** * Helper Functions **********************************************************************/ +#include //TODO remove when hack below is fixed + void usrp2_impl::io_init(void){ //the assumption is that all data transports should be identical @@ -250,6 +252,30 @@ void usrp2_impl::io_init(void){ //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, (num_recv_frames, send_frame_size, _data_transports.size())); + //TODO temporary fix for weird power up state, remove when FPGA fixed + { + //send an initial packet to all transports + tx_metadata_t md; md.end_of_burst = true; + this->send( + std::vector(_data_transports.size(), NULL), 0, md, + io_type_t::COMPLEX_FLOAT32, device::SEND_MODE_ONE_PACKET, 0 + ); + + //issue a stream command to each motherboard + BOOST_FOREACH(usrp2_mboard_impl::sptr mboard, _mboards){ + (*mboard)[MBOARD_PROP_STREAM_CMD] = stream_cmd_t(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + (*mboard)[MBOARD_PROP_STREAM_CMD] = stream_cmd_t(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); + } + + //wait + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + //flush all transport receive queues (no timeout) + BOOST_FOREACH(zero_copy_if::sptr xport, _data_transports){ + while(xport->get_recv_buff(0).get() != NULL){}; + } + } + //create a new pirate thread for each zc if (yarr!!) for (size_t i = 0; i < _data_transports.size(); i++){ _io_impl->recv_pirate_crew.create_thread(boost::bind( -- cgit v1.2.3 From a2abd6bc615cb63e585e7fafa9ea8491bb25f5b5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 15 Oct 2010 17:05:45 -0700 Subject: usrp2: dont need to start streaming for this hack --- host/lib/usrp/usrp2/io_impl.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 00061ae47..95a627266 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -263,7 +263,6 @@ void usrp2_impl::io_init(void){ //issue a stream command to each motherboard BOOST_FOREACH(usrp2_mboard_impl::sptr mboard, _mboards){ - (*mboard)[MBOARD_PROP_STREAM_CMD] = stream_cmd_t(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); (*mboard)[MBOARD_PROP_STREAM_CMD] = stream_cmd_t(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); } -- cgit v1.2.3 From 2d71c7a6e973b5715ca8e14cac99fb81fca9822c Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 22 Oct 2010 12:47:02 -0700 Subject: BasicRX: GPIOs now output 0 to decrease noise pickup. --- host/lib/usrp/dboard/db_basic_and_lf.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 41f6f8002..c58d0e326 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -95,6 +95,11 @@ UHD_STATIC_BLOCK(reg_basic_and_lf_dboards){ **********************************************************************/ basic_rx::basic_rx(ctor_args_t args, double max_freq) : rx_dboard_base(args){ _max_freq = max_freq; + + //set GPIOs to output 0x0000 to decrease noise pickup + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0000); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0xFFFF); + this->get_iface()->write_gpio(dboard_iface::UNIT_RX, 0x0000); } basic_rx::~basic_rx(void){ -- cgit v1.2.3 From 971f6de77c6b67515b5d37d748e823da155b310c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 24 Oct 2010 16:01:47 -0700 Subject: dbsrx: allow for setup time after changing the vco selection --- host/lib/usrp/dboard/db_dbsrx.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index aecd7249d..8ec87a4f7 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -374,6 +374,9 @@ void dbsrx::set_lo_freq(double target_freq){ //update vco selection and check vtune send_reg(0x2, 0x2); read_reg(0x0, 0x0); + + //allow for setup time before checking condition again + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); } if(dbsrx_debug) std::cerr << boost::format( -- cgit v1.2.3 From fa689c7202a0cab6bf0debc3524f1f46636a7ba0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 08:31:01 -0700 Subject: usrp_e: fix to get compiling with next branch --- host/lib/usrp/usrp_e/dboard_impl.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index d4a27cb72..f2840dcfc 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -87,6 +87,7 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeprom.id, _dboard_manager->get_rx_subdev(key.name), _rx_codec_proxy->get_link(), GAIN_GROUP_POLICY_RX @@ -145,6 +146,7 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeprom.id, _dboard_manager->get_tx_subdev(key.name), _tx_codec_proxy->get_link(), GAIN_GROUP_POLICY_TX -- cgit v1.2.3 From fa7704be20005a705efdc96aa785d80911638107 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 13:10:48 -0700 Subject: usrp-e: implemented fpga loading and compat checking --- host/examples/rx_to_file.cpp | 8 ++-- host/examples/rx_to_udp.cpp | 8 ++-- host/lib/usrp/usrp_e/fpga-downloader.cc | 30 ++++++++------ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 69 ++++++++++++++++++++++++++++++--- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 4 +- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 2 +- 6 files changed, 94 insertions(+), 27 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/examples/rx_to_file.cpp b/host/examples/rx_to_file.cpp index 79d3e9d8b..f08f7cee3 100644 --- a/host/examples/rx_to_file.cpp +++ b/host/examples/rx_to_file.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -40,7 +40,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") @@ -53,7 +53,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //print the help message if (vm.count("help")){ - std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl; + std::cout << boost::format("UHD RX to File %s") % desc << std::endl; return ~0; } @@ -62,7 +62,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/examples/rx_to_udp.cpp b/host/examples/rx_to_udp.cpp index 34b278599..c8b3d506b 100644 --- a/host/examples/rx_to_udp.cpp +++ b/host/examples/rx_to_udp.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -46,7 +46,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") @@ -61,7 +61,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //print the help message if (vm.count("help")){ - std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl; + std::cout << boost::format("UHD RX to UDP %s") % desc << std::endl; return ~0; } @@ -70,7 +70,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc index ff8671e98..b0d56e856 100644 --- a/host/lib/usrp/usrp_e/fpga-downloader.cc +++ b/host/lib/usrp/usrp_e/fpga-downloader.cc @@ -15,11 +15,14 @@ // along with this program. If not, see . // +#include + #include #include #include #include #include +#include #include #include @@ -82,8 +85,9 @@ 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; + if (not export_file.is_open()) throw std::runtime_error( + "Failed to open gpio export file." + ); export_file << gpio_num << std::endl; @@ -92,15 +96,17 @@ gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) std::fstream direction_file; std::string direction_file_name; - direction_file_name = base_path.str() + "/direction"; + if (gpio_num != 114) { + 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; + 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; @@ -251,11 +257,11 @@ void usrp_e_load_fpga(const std::string &bin_file){ gpio gpio_init_b(INIT_B, IN); gpio gpio_done (DONE, IN); - std::cout << "FPGA config file: " << bin_file << std::endl; + std::cout << "Loading FPGA image: " << bin_file << "... " << std::flush; prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); - std::cout << "Done = " << gpio_done.get_value() << std::endl; + 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/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 5c0e1dbb0..0a7295ff9 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -16,13 +16,17 @@ // #include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" #include #include #include #include +#include #include #include +#include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -66,7 +70,64 @@ static device_addrs_t usrp_e_find(const device_addr_t &hint){ * Make **********************************************************************/ static device::sptr usrp_e_make(const device_addr_t &device_addr){ - return device::sptr(new usrp_e_impl(device_addr["node"])); + + //The fpga is loaded when: + // 1) The compatibility number matches. + // 2) The hash in the hash-file matches. + + //setup the main interface into fpga + std::string node = device_addr["node"]; + std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; + usrp_e_iface::sptr iface = usrp_e_iface::make(node); + + //------------------------------------------------------------------ + //-- Handle the FPGA loading... + //-- The image can be confimed as already loaded when: + //-- 1) The compatibility number matches. + //-- 2) The hash in the hash-file matches. + //------------------------------------------------------------------ + + //extract the fpga path for usrp-e + std::string usrp_e_fpga_image = find_image_path( + device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" + ); + + //calculate a hash of the fpga file + size_t fpga_hash = 0; + { + std::ifstream file(usrp_e_fpga_image.c_str()); + if (not file.good()) throw std::runtime_error( + "cannot open fpga file for read: " + usrp_e_fpga_image + ); + do{ + boost::hash_combine(fpga_hash, file.get()); + } while (file.good()); + file.close(); + } + + //read the compatibility number + boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + + //read the hash in the hash-file + size_t loaded_hash = 0; + try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} + + //if not loaded: load the fpga image and write the hash-file + if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ + usrp_e_load_fpga(usrp_e_fpga_image); + try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} + } + + //check that the compatibility is correct + fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + if (fpga_compat_num != USRP_E_COMPAT_NUM){ + throw std::runtime_error(str(boost::format( + "Expected fpga compatibility number 0x%x, but got 0x%x:\n" + "The fpga build is not compatible with the host code build." + ) % USRP_E_COMPAT_NUM % fpga_compat_num)); + } + + return device::sptr(new usrp_e_impl(iface)); } UHD_STATIC_BLOCK(register_usrp_e_device){ @@ -76,11 +137,9 @@ UHD_STATIC_BLOCK(register_usrp_e_device){ /*********************************************************************** * Structors **********************************************************************/ -usrp_e_impl::usrp_e_impl(const std::string &node){ - std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; +usrp_e_impl::usrp_e_impl(usrp_e_iface::sptr iface): _iface(iface){ - //setup various interfaces into hardware - _iface = usrp_e_iface::make(node); + //setup interfaces into hardware _clock_ctrl = usrp_e_clock_ctrl::make(_iface); _codec_ctrl = usrp_e_codec_ctrl::make(_iface); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 9799cd645..421a9623d 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -31,6 +31,8 @@ #define INCLUDED_USRP_E_IMPL_HPP static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control +static const char *hash_file_path = "/tmp/usrp_e100_hash"; +static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; //! load an fpga image from a bin file into the usrp-e fpga extern void usrp_e_load_fpga(const std::string &bin_file); @@ -79,7 +81,7 @@ private: class usrp_e_impl : public uhd::device{ public: //structors - usrp_e_impl(const std::string &node); + usrp_e_impl(usrp_e_iface::sptr); ~usrp_e_impl(void); //the io interface diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index a4f42093e..f74358f00 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -30,7 +30,7 @@ #define UE_REG_MISC_CGEN_ST UE_REG_MISC_BASE + 6 #define UE_REG_MISC_TEST UE_REG_MISC_BASE + 8 #define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 -#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 +#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 12 ///////////////////////////////////////////////////// // Slave 1 -- UART -- cgit v1.2.3 From 0208b28e58e3719dc4dfb8df73fe5ae49e4a6306 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 15:57:35 -0700 Subject: usrp-e: use clock control to get clock rate, removed temporary constant --- host/lib/usrp/usrp_e/dsp_impl.cpp | 16 ++++++++-------- host/lib/usrp/usrp_e/io_impl.cpp | 17 ++++++++--------- host/lib/usrp/usrp_e/mboard_impl.cpp | 2 +- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 5 +---- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 5 ----- 5 files changed, 18 insertions(+), 27 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index 9312bb603..97f173c1a 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -65,11 +65,11 @@ void usrp_e_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_CODEC_RATE: - val = MASTER_CLOCK_RATE; + val = _clock_ctrl->get_fpga_clock_rate(); return; case DSP_PROP_HOST_RATE: - val = MASTER_CLOCK_RATE/_ddc_decim; + val = _clock_ctrl->get_fpga_clock_rate()/_ddc_decim; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -87,7 +87,7 @@ void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); _iface->poke32(UE_REG_DSP_RX_FREQ, - dsp_type1::calc_cordic_word_and_update(new_freq, MASTER_CLOCK_RATE) + dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) ); _ddc_freq = new_freq; //shadow } @@ -95,7 +95,7 @@ void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ case DSP_PROP_HOST_RATE:{ //set the decimation - _ddc_decim = rint(MASTER_CLOCK_RATE/val.as()); + _ddc_decim = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); //set the scaling @@ -148,11 +148,11 @@ void usrp_e_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_CODEC_RATE: - val = MASTER_CLOCK_RATE; + val = _clock_ctrl->get_fpga_clock_rate(); return; case DSP_PROP_HOST_RATE: - val = MASTER_CLOCK_RATE/_duc_interp; + val = _clock_ctrl->get_fpga_clock_rate()/_duc_interp; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -170,14 +170,14 @@ void usrp_e_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); _iface->poke32(UE_REG_DSP_TX_FREQ, - dsp_type1::calc_cordic_word_and_update(new_freq, MASTER_CLOCK_RATE) + dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) ); _duc_freq = new_freq; //shadow } return; case DSP_PROP_HOST_RATE:{ - _duc_interp = rint(MASTER_CLOCK_RATE/val.as()); + _duc_interp = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); //set the interpolation _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp)); diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index d89a7db07..9996e7172 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -73,7 +73,7 @@ struct usrp_e_impl::io_impl{ } //a pirate's life is the life for me! - void recv_pirate_loop(); + void recv_pirate_loop(usrp_e_clock_ctrl::sptr); typedef bounded_buffer recv_booty_type; recv_booty_type::sptr recv_pirate_booty; bounded_buffer::sptr async_msg_fifo; @@ -86,9 +86,8 @@ struct usrp_e_impl::io_impl{ * - while raiding, loot for recv buffers * - put booty into the alignment buffer **********************************************************************/ -void usrp_e_impl::io_impl::recv_pirate_loop( - -){ +void usrp_e_impl::io_impl::recv_pirate_loop(usrp_e_clock_ctrl::sptr clock_ctrl) +{ set_thread_priority_safe(); recv_pirate_crew_raiding = true; @@ -119,7 +118,7 @@ void usrp_e_impl::io_impl::recv_pirate_loop( metadata.channel = 0; metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; metadata.time_spec = time_spec_t( - time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), MASTER_CLOCK_RATE + time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), clock_ctrl->get_fpga_clock_rate() ); metadata.event_code = vrt_packet_handler::get_context_code(vrt_hdr, if_packet_info); @@ -172,7 +171,7 @@ void usrp_e_impl::io_init(void){ //spawn a pirate, yarrr! _io_impl->recv_pirate_crew.create_thread(boost::bind( - &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get() + &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl )); } @@ -182,7 +181,7 @@ void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ stream_cmd, get_max_recv_samps_per_packet() )); _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); - _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(MASTER_CLOCK_RATE)); + _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); } void usrp_e_impl::handle_overrun(size_t){ @@ -226,7 +225,7 @@ size_t usrp_e_impl::send( buffs, num_samps, //buffer to fill metadata, send_mode, //samples metadata io_type, _send_otw_type, //input and output types to convert - MASTER_CLOCK_RATE, //master clock tick rate + _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), get_max_send_samps_per_packet() @@ -258,7 +257,7 @@ size_t usrp_e_impl::recv( buffs, num_samps, //buffer to fill metadata, recv_mode, //samples metadata io_type, _recv_otw_type, //input and output types to convert - MASTER_CLOCK_RATE, //master clock tick rate + _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), boost::bind(&usrp_e_impl::handle_overrun, this, _1) diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 3d4cef069..f0118aa4b 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -125,7 +125,7 @@ void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_TIME_NOW: case MBOARD_PROP_TIME_NEXT_PPS:{ time_spec_t time_spec = val.as(); - _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(MASTER_CLOCK_RATE)); + _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); boost::uint32_t imm_flags = (key.as() == MBOARD_PROP_TIME_NOW)? 1 : 0; _iface->poke32(UE_REG_TIME64_IMM, imm_flags); _iface->poke32(UE_REG_TIME64_SECS, time_spec.get_full_secs()); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 0a7295ff9..1b71c0a52 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -71,10 +71,6 @@ static device_addrs_t usrp_e_find(const device_addr_t &hint){ **********************************************************************/ static device::sptr usrp_e_make(const device_addr_t &device_addr){ - //The fpga is loaded when: - // 1) The compatibility number matches. - // 2) The hash in the hash-file matches. - //setup the main interface into fpga std::string node = device_addr["node"]; std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; @@ -86,6 +82,7 @@ static device::sptr usrp_e_make(const device_addr_t &device_addr){ //-- 1) The compatibility number matches. //-- 2) The hash in the hash-file matches. //------------------------------------------------------------------ + static const char *hash_file_path = "/tmp/usrp_e100_hash"; //extract the fpga path for usrp-e std::string usrp_e_fpga_image = find_image_path( diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 421a9623d..e55b46b80 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -30,8 +30,6 @@ #ifndef INCLUDED_USRP_E_IMPL_HPP #define INCLUDED_USRP_E_IMPL_HPP -static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control -static const char *hash_file_path = "/tmp/usrp_e100_hash"; static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; //! load an fpga image from a bin file into the usrp-e fpga @@ -100,9 +98,6 @@ private: //interface to ioctls and file descriptor usrp_e_iface::sptr _iface; - //FIXME fetch from ioctl? - static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); - //handle io stuff UHD_PIMPL_DECL(io_impl) _io_impl; uhd::otw_type_t _send_otw_type, _recv_otw_type; -- cgit v1.2.3 From a8fcdba5f76d08212835c5966be67248428fe9fa Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 4 Nov 2010 17:43:30 -0400 Subject: usrp_e: Comment out fpga loading until we unload module during load. --- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 1b71c0a52..cd39dbb07 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -111,7 +111,8 @@ static device::sptr usrp_e_make(const device_addr_t &device_addr){ //if not loaded: load the fpga image and write the hash-file if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ - usrp_e_load_fpga(usrp_e_fpga_image); +// usrp_e_load_fpga(usrp_e_fpga_image); +std::cout << "Here is where I load the fpga" << std::endl; try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} } -- cgit v1.2.3 From bab641f4fdf954d6023904ca18c4bb4f6a362e47 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 4 Nov 2010 17:44:08 -0400 Subject: usrp_e : Fix register definitions for COMPAT and others. --- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index f74358f00..8bfb08b6f 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -30,7 +30,9 @@ #define UE_REG_MISC_CGEN_ST UE_REG_MISC_BASE + 6 #define UE_REG_MISC_TEST UE_REG_MISC_BASE + 8 #define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 -#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 12 +#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 +#define UE_REG_MISC_XFER_RATE UE_REG_MISC_BASE + 14 +#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 16 ///////////////////////////////////////////////////// // Slave 1 -- UART -- cgit v1.2.3 From 81c9f77306dc82f250bfb2871b8bd7db67a40085 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 8 Nov 2010 17:22:37 -0800 Subject: usrp2: implemented clear state for RX and TX control, and zero sample command support --- firmware/microblaze/lib/net_common.c | 2 +- host/include/uhd/usrp/dsp_utils.hpp | 5 +---- host/lib/usrp/dsp_utils.cpp | 6 ++---- host/lib/usrp/usrp2/io_impl.cpp | 25 ------------------------- host/lib/usrp/usrp2/mboard_impl.cpp | 13 +++++-------- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 - host/lib/usrp/usrp2/usrp2_regs.hpp | 2 +- 7 files changed, 10 insertions(+), 44 deletions(-) (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/lib/net_common.c b/firmware/microblaze/lib/net_common.c index 0a085db3a..6305408d6 100644 --- a/firmware/microblaze/lib/net_common.c +++ b/firmware/microblaze/lib/net_common.c @@ -298,7 +298,7 @@ handle_icmp_packet(struct ip_addr src, struct ip_addr dst, sr_tx_ctrl->cyc_per_up = 0; //the end continuous streaming command - sr_rx_ctrl->cmd = (1 << 31) | 1; //one sample, asap + sr_rx_ctrl->cmd = 1 << 31; //no samples now sr_rx_ctrl->time_secs = 0; sr_rx_ctrl->time_ticks = 0; //latch the command diff --git a/host/include/uhd/usrp/dsp_utils.hpp b/host/include/uhd/usrp/dsp_utils.hpp index 8ec04dd2f..5b81ce322 100644 --- a/host/include/uhd/usrp/dsp_utils.hpp +++ b/host/include/uhd/usrp/dsp_utils.hpp @@ -85,12 +85,9 @@ namespace dsp_type1{ /*! * Calculate the stream command word from the stream command struct. * \param stream_cmd the requested stream command with mode, flags, timestamp - * \param num_samps_continuous number of samples to request in continuous mode * \return the 32-bit stream command word */ - UHD_API boost::uint32_t calc_stream_cmd_word( - const stream_cmd_t &stream_cmd, size_t num_samps_continuous - ); + UHD_API boost::uint32_t calc_stream_cmd_word(const stream_cmd_t &stream_cmd); } //namespace dsp_type1 diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp index 10ae9a086..2553e4a25 100644 --- a/host/lib/usrp/dsp_utils.cpp +++ b/host/lib/usrp/dsp_utils.cpp @@ -109,9 +109,7 @@ boost::uint32_t dsp_type1::calc_iq_scale_word(unsigned rate){ return calc_iq_scale_word(scale, scale); } -boost::uint32_t dsp_type1::calc_stream_cmd_word( - const stream_cmd_t &stream_cmd, size_t num_samps_continuous -){ +boost::uint32_t dsp_type1::calc_stream_cmd_word(const stream_cmd_t &stream_cmd){ UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff); //setup the mode to instruction flags @@ -133,6 +131,6 @@ boost::uint32_t dsp_type1::calc_stream_cmd_word( word |= boost::uint32_t((stream_cmd.stream_now)? 1 : 0) << 31; word |= boost::uint32_t((inst_chain)? 1 : 0) << 30; word |= boost::uint32_t((inst_reload)? 1 : 0) << 29; - word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? num_samps_continuous : 1); + word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? 1 : 0); return word; } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 39e6c167f..844df603c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -241,8 +241,6 @@ void usrp2_impl::io_impl::recv_pirate_loop( /*********************************************************************** * Helper Functions **********************************************************************/ -#include //TODO remove when hack below is fixed - void usrp2_impl::io_init(void){ //the assumption is that all data transports should be identical @@ -252,29 +250,6 @@ void usrp2_impl::io_init(void){ //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, (num_recv_frames, send_frame_size, _data_transports.size())); - //TODO temporary fix for weird power up state, remove when FPGA fixed - { - //send an initial packet to all transports - tx_metadata_t md; md.end_of_burst = true; - this->send( - std::vector(_data_transports.size(), NULL), 0, md, - io_type_t::COMPLEX_FLOAT32, device::SEND_MODE_ONE_PACKET, 0 - ); - - //issue a stream command to each motherboard - BOOST_FOREACH(usrp2_mboard_impl::sptr mboard, _mboards){ - (*mboard)[MBOARD_PROP_STREAM_CMD] = stream_cmd_t(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); - } - - //wait - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - //flush all transport receive queues (no timeout) - BOOST_FOREACH(zero_copy_if::sptr xport, _data_transports){ - while(xport->get_recv_buff(0).get() != NULL){}; - } - } - //create a new pirate thread for each zc if (yarr!!) for (size_t i = 0; i < _data_transports.size(); i++){ _io_impl->recv_pirate_crew.create_thread(boost::bind( diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index bb9b6d1a9..d4dc8a4bd 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -40,7 +40,6 @@ usrp2_mboard_impl::usrp2_mboard_impl( const device_addr_t &flow_control_hints ): _index(index), - _recv_samps_per_packet(recv_samps_per_packet), _iface(usrp2_iface::make(ctrl_transport)) { //Send a small data packet so the usrp2 knows the udp source port. @@ -74,9 +73,9 @@ usrp2_mboard_impl::usrp2_mboard_impl( } //init the rx control registers - _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_samps_per_packet); + _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset + _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, recv_samps_per_packet); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); - _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 | (0x1 << 28) //if data with stream id | (0x1 << 26) //has trailer @@ -88,8 +87,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(U2_REG_TIME64_TPS, size_t(get_master_clock_freq())); //init the tx control registers - _iface->poke32(U2_REG_TX_CTRL_NUM_CHAN, 0); //1 channel _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset + _iface->poke32(U2_REG_TX_CTRL_NUM_CHAN, 0); //1 channel _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1); //sid 1 (different from rx) _iface->poke32(U2_REG_TX_CTRL_POLICY, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); @@ -97,6 +96,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( const double ups_per_sec = flow_control_hints.cast("ups_per_sec", 100); const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec); _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up); + _iface->poke32(U2_REG_TX_CTRL_CYCLES_PER_UP, 0); //cycles per update is disabled //setting the packets per update const double ups_per_fifo = flow_control_hints.cast("ups_per_fifo", 8); @@ -187,7 +187,6 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ } void usrp2_mboard_impl::handle_overflow(void){ - _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); if (_continuous_streaming){ //re-issue the stream command if already continuous this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); } @@ -195,9 +194,7 @@ void usrp2_mboard_impl::handle_overflow(void){ void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ _continuous_streaming = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS; - _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word( - stream_cmd, _recv_samps_per_packet - )); + _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word(stream_cmd)); _iface->poke32(U2_REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); _iface->poke32(U2_REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index e4980a539..e41cefc10 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -98,7 +98,6 @@ public: private: size_t _index; - const size_t _recv_samps_per_packet; bool _continuous_streaming; //interfaces diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index c3a4d22de..cef7cf2e6 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -179,7 +179,7 @@ #define U2_REG_RX_CTRL_TIME_SECS _SR_ADDR(SR_RX_CTRL + 1) #define U2_REG_RX_CTRL_TIME_TICKS _SR_ADDR(SR_RX_CTRL + 2) -#define U2_REG_RX_CTRL_CLEAR_OVERRUN _SR_ADDR(SR_RX_CTRL + 3) // write anything to clear overrun +#define U2_REG_RX_CTRL_CLEAR_STATE _SR_ADDR(SR_RX_CTRL + 3) #define U2_REG_RX_CTRL_VRT_HEADER _SR_ADDR(SR_RX_CTRL + 4) // word 0 of packet. FPGA fills in packet counter #define U2_REG_RX_CTRL_VRT_STREAM_ID _SR_ADDR(SR_RX_CTRL + 5) // word 1 of packet. #define U2_REG_RX_CTRL_VRT_TRAILER _SR_ADDR(SR_RX_CTRL + 6) -- cgit v1.2.3 From 7824f130bd1296c78f5b0311d1c253f0476c6cab Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Tue, 9 Nov 2010 18:13:25 -0800 Subject: usrp_e : Unload the module before loading the FPGA. Reload after the fpga is loaded. --- host/lib/usrp/usrp_e/fpga-downloader.cc | 6 ++++++ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc index b0d56e856..5fd2c8dd0 100644 --- a/host/lib/usrp/usrp_e/fpga-downloader.cc +++ b/host/lib/usrp/usrp_e/fpga-downloader.cc @@ -259,9 +259,15 @@ void usrp_e_load_fpga(const std::string &bin_file){ std::cout << "Loading FPGA image: " << bin_file << "... " << std::flush; + system("/sbin/rmmod usrp_e"); + 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); + + system("/sbin/modprobe usrp_e"); + } + diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index cd39dbb07..70cc399fb 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -111,8 +111,10 @@ static device::sptr usrp_e_make(const device_addr_t &device_addr){ //if not loaded: load the fpga image and write the hash-file if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ -// usrp_e_load_fpga(usrp_e_fpga_image); -std::cout << "Here is where I load the fpga" << std::endl; + iface.reset(); + usrp_e_load_fpga(usrp_e_fpga_image); + std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl; + iface = usrp_e_iface::make(node); try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} } -- cgit v1.2.3 From 073518083f2c7044d4b0c16948a192c5623d0752 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 9 Nov 2010 18:38:27 -0800 Subject: usrp_e: use the transport to calculate the max spp (with a fix to init the xport first) --- host/lib/usrp/usrp_e/io_impl.cpp | 9 +++------ host/lib/usrp/usrp_e/usrp_e_impl.hpp | 5 ----- 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 9996e7172..e863944e8 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -150,6 +150,9 @@ void usrp_e_impl::io_init(void){ _recv_otw_type.shift = 0; _recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + //setup before the registers (transport called to calculate max spp) + _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface)); + //setup rx data path _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); @@ -167,8 +170,6 @@ void usrp_e_impl::io_init(void){ _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, tx_async_report_sid); _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); - _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface)); - //spawn a pirate, yarrr! _io_impl->recv_pirate_crew.create_thread(boost::bind( &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl @@ -204,7 +205,6 @@ bool get_send_buffs( return buffs[0].get() != NULL; } -#if 0 size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -213,7 +213,6 @@ size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ size_t bpp = _io_impl->data_xport->get_send_frame_size() - hdr_size; return bpp/_send_otw_type.get_sample_size(); } -#endif size_t usrp_e_impl::send( const std::vector &buffs, size_t num_samps, @@ -235,7 +234,6 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ -#if 0 size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -245,7 +243,6 @@ size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ size_t bpp = _io_impl->data_xport->get_recv_frame_size() - hdr_size; return bpp/_recv_otw_type.get_sample_size(); } -#endif size_t usrp_e_impl::recv( const std::vector &buffs, size_t num_samps, diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index e55b46b80..b5f21810d 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -86,13 +86,8 @@ public: size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); bool recv_async_msg(uhd::async_metadata_t &, double); -#if 0 size_t get_max_send_samps_per_packet(void) const; size_t get_max_recv_samps_per_packet(void) const; -#else - size_t get_max_send_samps_per_packet(void) const{return 503;} - size_t get_max_recv_samps_per_packet(void) const{return 503;} -#endif private: //interface to ioctls and file descriptor -- cgit v1.2.3 From 61d9cda7f64e10d8039bf7b6de5ca8068f11e5bb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 9 Nov 2010 18:44:39 -0800 Subject: usrp-e: check the return code on system call, also removes warnings --- host/lib/usrp/usrp_e/fpga-downloader.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc index 5fd2c8dd0..4dc537919 100644 --- a/host/lib/usrp/usrp_e/fpga-downloader.cc +++ b/host/lib/usrp/usrp_e/fpga-downloader.cc @@ -16,6 +16,7 @@ // #include +#include #include #include @@ -259,7 +260,7 @@ void usrp_e_load_fpga(const std::string &bin_file){ std::cout << "Loading FPGA image: " << bin_file << "... " << std::flush; - system("/sbin/rmmod usrp_e"); + UHD_ASSERT_THROW(std::system("/sbin/rmmod usrp_e") == 0); prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); @@ -267,7 +268,7 @@ void usrp_e_load_fpga(const std::string &bin_file){ send_file_to_fpga(bin_file, gpio_init_b, gpio_done); - system("/sbin/modprobe usrp_e"); + UHD_ASSERT_THROW(std::system("/sbin/modprobe usrp_e") == 0); } -- cgit v1.2.3 From d33a6cab6646692e06ef34317f6c831ac9c91148 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 9 Nov 2010 18:48:54 -0800 Subject: usrp_e: renamed directory to usrp_e100 to reflect product name --- host/lib/usrp/CMakeLists.txt | 2 +- host/lib/usrp/usrp_e/CMakeLists.txt | 64 ----- host/lib/usrp/usrp_e/clock_ctrl.cpp | 237 ----------------- host/lib/usrp/usrp_e/clock_ctrl.hpp | 88 ------- host/lib/usrp/usrp_e/codec_ctrl.cpp | 296 --------------------- host/lib/usrp/usrp_e/codec_ctrl.hpp | 90 ------- host/lib/usrp/usrp_e/codec_impl.cpp | 149 ----------- host/lib/usrp/usrp_e/dboard_iface.cpp | 298 ---------------------- host/lib/usrp/usrp_e/dboard_impl.cpp | 172 ------------- host/lib/usrp/usrp_e/dsp_impl.cpp | 192 -------------- host/lib/usrp/usrp_e/fpga-downloader.cc | 274 -------------------- host/lib/usrp/usrp_e/io_impl.cpp | 272 -------------------- host/lib/usrp/usrp_e/mboard_impl.cpp | 159 ------------ host/lib/usrp/usrp_e/usrp_e_iface.cpp | 194 -------------- host/lib/usrp/usrp_e/usrp_e_iface.hpp | 112 -------- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 201 --------------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 164 ------------ host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 215 ---------------- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 198 -------------- host/lib/usrp/usrp_e100/CMakeLists.txt | 64 +++++ host/lib/usrp/usrp_e100/clock_ctrl.cpp | 237 +++++++++++++++++ host/lib/usrp/usrp_e100/clock_ctrl.hpp | 88 +++++++ host/lib/usrp/usrp_e100/codec_ctrl.cpp | 296 +++++++++++++++++++++ host/lib/usrp/usrp_e100/codec_ctrl.hpp | 90 +++++++ host/lib/usrp/usrp_e100/codec_impl.cpp | 149 +++++++++++ host/lib/usrp/usrp_e100/dboard_iface.cpp | 298 ++++++++++++++++++++++ host/lib/usrp/usrp_e100/dboard_impl.cpp | 172 +++++++++++++ host/lib/usrp/usrp_e100/dsp_impl.cpp | 192 ++++++++++++++ host/lib/usrp/usrp_e100/fpga-downloader.cc | 274 ++++++++++++++++++++ host/lib/usrp/usrp_e100/io_impl.cpp | 272 ++++++++++++++++++++ host/lib/usrp/usrp_e100/mboard_impl.cpp | 159 ++++++++++++ host/lib/usrp/usrp_e100/usrp_e_iface.cpp | 194 ++++++++++++++ host/lib/usrp/usrp_e100/usrp_e_iface.hpp | 112 ++++++++ host/lib/usrp/usrp_e100/usrp_e_impl.cpp | 201 +++++++++++++++ host/lib/usrp/usrp_e100/usrp_e_impl.hpp | 164 ++++++++++++ host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp | 215 ++++++++++++++++ host/lib/usrp/usrp_e100/usrp_e_regs.hpp | 198 ++++++++++++++ 37 files changed, 3376 insertions(+), 3376 deletions(-) delete mode 100644 host/lib/usrp/usrp_e/CMakeLists.txt delete mode 100644 host/lib/usrp/usrp_e/clock_ctrl.cpp delete mode 100644 host/lib/usrp/usrp_e/clock_ctrl.hpp delete mode 100644 host/lib/usrp/usrp_e/codec_ctrl.cpp delete mode 100644 host/lib/usrp/usrp_e/codec_ctrl.hpp delete mode 100644 host/lib/usrp/usrp_e/codec_impl.cpp delete mode 100644 host/lib/usrp/usrp_e/dboard_iface.cpp delete mode 100644 host/lib/usrp/usrp_e/dboard_impl.cpp delete mode 100644 host/lib/usrp/usrp_e/dsp_impl.cpp delete mode 100644 host/lib/usrp/usrp_e/fpga-downloader.cc delete mode 100644 host/lib/usrp/usrp_e/io_impl.cpp delete mode 100644 host/lib/usrp/usrp_e/mboard_impl.cpp delete mode 100644 host/lib/usrp/usrp_e/usrp_e_iface.cpp delete mode 100644 host/lib/usrp/usrp_e/usrp_e_iface.hpp delete mode 100644 host/lib/usrp/usrp_e/usrp_e_impl.cpp delete mode 100644 host/lib/usrp/usrp_e/usrp_e_impl.hpp delete mode 100644 host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp delete mode 100644 host/lib/usrp/usrp_e/usrp_e_regs.hpp create mode 100644 host/lib/usrp/usrp_e100/CMakeLists.txt create mode 100644 host/lib/usrp/usrp_e100/clock_ctrl.cpp create mode 100644 host/lib/usrp/usrp_e100/clock_ctrl.hpp create mode 100644 host/lib/usrp/usrp_e100/codec_ctrl.cpp create mode 100644 host/lib/usrp/usrp_e100/codec_ctrl.hpp create mode 100644 host/lib/usrp/usrp_e100/codec_impl.cpp create mode 100644 host/lib/usrp/usrp_e100/dboard_iface.cpp create mode 100644 host/lib/usrp/usrp_e100/dboard_impl.cpp create mode 100644 host/lib/usrp/usrp_e100/dsp_impl.cpp create mode 100644 host/lib/usrp/usrp_e100/fpga-downloader.cc create mode 100644 host/lib/usrp/usrp_e100/io_impl.cpp create mode 100644 host/lib/usrp/usrp_e100/mboard_impl.cpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e_iface.cpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e_iface.hpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e_impl.cpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e_impl.hpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e_regs.hpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index bb7e83214..073b3c80b 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -35,4 +35,4 @@ LIBUHD_APPEND_SOURCES( INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/dboard/CMakeLists.txt) INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/CMakeLists.txt) INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/CMakeLists.txt) -INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/CMakeLists.txt) +INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/CMakeLists.txt) diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt deleted file mode 100644 index 6c5d281dd..000000000 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright 2010 Ettus Research LLC -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -#This file will be included by cmake, use absolute paths! - -######################################################################## -# Conditionally configure the USRP-E support -######################################################################## -MESSAGE(STATUS "Configuring usrp-e support...") - -INCLUDE(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(linux/usrp_e.h HAVE_LINUX_USRP_E_H) - -SET(ENABLE_USRP_E TRUE) - -IF(DEFINED ENABLE_USRP_E) - IF(ENABLE_USRP_E) - MESSAGE(STATUS "USRP-E support enabled by configure flag") - ELSE(ENABLE_USRP_E) - MESSAGE(STATUS "USRP-E support disabled by configure flag") - ENDIF(ENABLE_USRP_E) -ELSE(DEFINED ENABLE_USRP_E) #not defined: automatic enabling of component - SET(ENABLE_USRP_E ${HAVE_LINUX_USRP_E_H}) -ENDIF(DEFINED ENABLE_USRP_E) -SET(ENABLE_USRP_E ${ENABLE_USRP_E} CACHE BOOL "enable USRP-E support") - -IF(ENABLE_USRP_E) - MESSAGE(STATUS " Building usrp-e support.") - LIBUHD_APPEND_SOURCES( - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/clock_ctrl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/clock_ctrl.hpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_ctrl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_ctrl.hpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/codec_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dboard_iface.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/dsp_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/fpga-downloader.cc - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/io_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/mboard_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.hpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.hpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_regs.hpp - ) -ELSE(ENABLE_USRP_E) - MESSAGE(STATUS " Skipping usrp-e support.") -ENDIF(ENABLE_USRP_E) diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp deleted file mode 100644 index 9d4625305..000000000 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "clock_ctrl.hpp" -#include "ad9522_regs.hpp" -#include -#include -#include "usrp_e_regs.hpp" //spi slave constants -#include -#include -#include -#include - -using namespace uhd; - -template static void set_clock_divider( - size_t divider, div_type &low, div_type &high, bypass_type &bypass -){ - high = divider/2 - 1; - low = divider - high - 2; - bypass = (divider == 1)? 1 : 0; -} - -/*********************************************************************** - * Constants - **********************************************************************/ -static const bool enable_test_clock = false; -static const size_t ref_clock_doubler = 2; //enabled below -static const double ref_clock_rate = 10e6 * ref_clock_doubler; - -static const size_t r_counter = 1; -static const size_t a_counter = 0; -static const size_t b_counter = 20 / ref_clock_doubler; -static const size_t prescaler = 8; //set below with enum, set to 8 when input is under 2400 MHz -static const size_t vco_divider = 5; //set below with enum - -static const size_t n_counter = prescaler * b_counter + a_counter; -static const size_t vco_clock_rate = ref_clock_rate/r_counter * n_counter; //between 1400 and 1800 MHz -static const double master_clock_rate = vco_clock_rate/vco_divider; - -static const size_t fpga_clock_divider = size_t(master_clock_rate/64e6); -static const size_t codec_clock_divider = size_t(master_clock_rate/64e6); - -/*********************************************************************** - * Clock Control Implementation - **********************************************************************/ -class usrp_e_clock_ctrl_impl : public usrp_e_clock_ctrl{ -public: - usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ - _iface = iface; - - //init the clock gen registers - //Note: out0 should already be clocking the FPGA or this isnt going to work - _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; - _ad9522_regs.enable_clock_doubler = 1; //enable ref clock doubler - _ad9522_regs.enb_stat_eeprom_at_stat_pin = 0; //use status pin - _ad9522_regs.status_pin_control = 0x1; //n divider - _ad9522_regs.ld_pin_control = 0x00; //dld - _ad9522_regs.refmon_pin_control = 0x12; //show ref2 - - _ad9522_regs.enable_ref2 = 1; - _ad9522_regs.enable_ref1 = 0; - _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; - - _ad9522_regs.set_r_counter(r_counter); - _ad9522_regs.a_counter = a_counter; - _ad9522_regs.set_b_counter(b_counter); - _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; - - _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; - _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; - - _ad9522_regs.vco_calibration_now = 1; //calibrate it! - _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; - _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; - - //setup fpga master clock - _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; - set_clock_divider(fpga_clock_divider, - _ad9522_regs.divider0_low_cycles, - _ad9522_regs.divider0_high_cycles, - _ad9522_regs.divider0_bypass - ); - - //setup codec clock - _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; - set_clock_divider(codec_clock_divider, - _ad9522_regs.divider1_low_cycles, - _ad9522_regs.divider1_high_cycles, - _ad9522_regs.divider1_bypass - ); - - //setup test clock (same divider as codec clock) - _ad9522_regs.out4_format = ad9522_regs_t::OUT4_FORMAT_CMOS; - _ad9522_regs.out4_cmos_configuration = (enable_test_clock)? - ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : - ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; - - //setup a list of register ranges to write - typedef std::pair range_t; - static const std::vector ranges = boost::assign::list_of - (range_t(0x000, 0x000)) (range_t(0x010, 0x01F)) - (range_t(0x0F0, 0x0FD)) (range_t(0x190, 0x19B)) - (range_t(0x1E0, 0x1E1)) (range_t(0x230, 0x230)) - ; - - //write initial register values and latch/update - BOOST_FOREACH(const range_t &range, ranges){ - for(boost::uint16_t addr = range.first; addr <= range.second; addr++){ - this->send_reg(addr); - } - } - this->latch_regs(); - //test read: - //boost::uint32_t reg = _ad9522_regs.get_read_reg(0x01b); - //boost::uint32_t result = _iface->transact_spi( - // UE_SPI_SS_AD9522, - // spi_config_t::EDGE_RISE, - // reg, 24, true /*no*/ - //); - //std::cout << "result " << std::hex << result << std::endl; - this->enable_rx_dboard_clock(false); - this->enable_tx_dboard_clock(false); - } - - ~usrp_e_clock_ctrl_impl(void){ - this->enable_rx_dboard_clock(false); - this->enable_tx_dboard_clock(false); - } - - double get_fpga_clock_rate(void){ - return master_clock_rate/fpga_clock_divider; - } - - /*********************************************************************** - * RX Dboard Clock Control (output 9, divider 3) - **********************************************************************/ - void enable_rx_dboard_clock(bool enb){ - _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_CMOS; - _ad9522_regs.out9_cmos_configuration = (enb)? - ad9522_regs_t::OUT9_CMOS_CONFIGURATION_B_ON : - ad9522_regs_t::OUT9_CMOS_CONFIGURATION_OFF; - this->send_reg(0x0F9); - this->latch_regs(); - } - - std::vector get_rx_dboard_clock_rates(void){ - std::vector rates; - for(size_t div = 1; div <= 16+16; div++) - rates.push_back(master_clock_rate/div); - return rates; - } - - void set_rx_dboard_clock_rate(double rate){ - assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); - size_t divider = size_t(master_clock_rate/rate); - //set the divider registers - set_clock_divider(divider, - _ad9522_regs.divider3_low_cycles, - _ad9522_regs.divider3_high_cycles, - _ad9522_regs.divider3_bypass - ); - this->send_reg(0x199); - this->send_reg(0x19a); - this->latch_regs(); - } - - /*********************************************************************** - * TX Dboard Clock Control (output 6, divider 2) - **********************************************************************/ - void enable_tx_dboard_clock(bool enb){ - _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_CMOS; - _ad9522_regs.out6_cmos_configuration = (enb)? - ad9522_regs_t::OUT6_CMOS_CONFIGURATION_B_ON : - ad9522_regs_t::OUT6_CMOS_CONFIGURATION_OFF; - this->send_reg(0x0F6); - this->latch_regs(); - } - - std::vector get_tx_dboard_clock_rates(void){ - return get_rx_dboard_clock_rates(); //same master clock, same dividers... - } - - void set_tx_dboard_clock_rate(double rate){ - assert_has(get_tx_dboard_clock_rates(), rate, "tx dboard clock rate"); - size_t divider = size_t(master_clock_rate/rate); - //set the divider registers - set_clock_divider(divider, - _ad9522_regs.divider2_low_cycles, - _ad9522_regs.divider2_high_cycles, - _ad9522_regs.divider2_bypass - ); - this->send_reg(0x196); - this->send_reg(0x197); - this->latch_regs(); - } - -private: - usrp_e_iface::sptr _iface; - ad9522_regs_t _ad9522_regs; - - void latch_regs(void){ - _ad9522_regs.io_update = 1; - this->send_reg(0x232); - } - - void send_reg(boost::uint16_t addr){ - boost::uint32_t reg = _ad9522_regs.get_write_reg(addr); - //std::cout << "clock control write reg: " << std::hex << reg << std::endl; - _iface->transact_spi( - UE_SPI_SS_AD9522, - spi_config_t::EDGE_RISE, - reg, 24, false /*no rb*/ - ); - } -}; - -/*********************************************************************** - * Clock Control Make - **********************************************************************/ -usrp_e_clock_ctrl::sptr usrp_e_clock_ctrl::make(usrp_e_iface::sptr iface){ - return sptr(new usrp_e_clock_ctrl_impl(iface)); -} diff --git a/host/lib/usrp/usrp_e/clock_ctrl.hpp b/host/lib/usrp/usrp_e/clock_ctrl.hpp deleted file mode 100644 index 3b5103ed1..000000000 --- a/host/lib/usrp/usrp_e/clock_ctrl.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_USRP_E_CLOCK_CTRL_HPP -#define INCLUDED_USRP_E_CLOCK_CTRL_HPP - -#include "usrp_e_iface.hpp" -#include -#include -#include - -/*! - * The usrp-e clock control: - * - Setup system clocks. - * - Disable/enable clock lines. - */ -class usrp_e_clock_ctrl : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - /*! - * Make a new clock control object. - * \param iface the usrp_e iface object - * \return the clock control object - */ - static sptr make(usrp_e_iface::sptr iface); - - /*! - * Get the rate of the fpga clock line. - * \return the fpga clock rate in Hz - */ - virtual double get_fpga_clock_rate(void) = 0; - - /*! - * Get the possible rates of the rx dboard clock. - * \return a vector of clock rates in Hz - */ - virtual std::vector get_rx_dboard_clock_rates(void) = 0; - - /*! - * Get the possible rates of the tx dboard clock. - * \return a vector of clock rates in Hz - */ - virtual std::vector get_tx_dboard_clock_rates(void) = 0; - - /*! - * Set the rx dboard clock rate to a possible rate. - * \param rate the new clock rate in Hz - * \throw exception when rate cannot be achieved - */ - virtual void set_rx_dboard_clock_rate(double rate) = 0; - - /*! - * Set the tx dboard clock rate to a possible rate. - * \param rate the new clock rate in Hz - * \throw exception when rate cannot be achieved - */ - virtual void set_tx_dboard_clock_rate(double rate) = 0; - - /*! - * Enable/disable the rx dboard clock. - * \param enb true to enable - */ - virtual void enable_rx_dboard_clock(bool enb) = 0; - - /*! - * Enable/disable the tx dboard clock. - * \param enb true to enable - */ - virtual void enable_tx_dboard_clock(bool enb) = 0; - -}; - -#endif /* INCLUDED_USRP_E_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp deleted file mode 100644 index a728d7e46..000000000 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ /dev/null @@ -1,296 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "codec_ctrl.hpp" -#include "ad9862_regs.hpp" -#include -#include -#include -#include -#include -#include -#include "usrp_e_regs.hpp" //spi slave constants -#include -#include - -using namespace uhd; - -static const bool codec_debug = false; - -const gain_range_t usrp_e_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); -const gain_range_t usrp_e_codec_ctrl::rx_pga_gain_range(0, 20, 1); - -/*********************************************************************** - * Codec Control Implementation - **********************************************************************/ -class usrp_e_codec_ctrl_impl : public usrp_e_codec_ctrl{ -public: - //structors - usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface); - ~usrp_e_codec_ctrl_impl(void); - - //aux adc and dac control - float read_aux_adc(aux_adc_t which); - void write_aux_dac(aux_dac_t which, float volts); - - //pga gain control - void set_tx_pga_gain(float); - float get_tx_pga_gain(void); - void set_rx_pga_gain(float, char); - float get_rx_pga_gain(char); - -private: - usrp_e_iface::sptr _iface; - ad9862_regs_t _ad9862_regs; - aux_adc_t _last_aux_adc_a, _last_aux_adc_b; - void send_reg(boost::uint8_t addr); - void recv_reg(boost::uint8_t addr); -}; - -/*********************************************************************** - * Codec Control Structors - **********************************************************************/ -usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ - _iface = iface; - - //soft reset - _ad9862_regs.soft_reset = 1; - this->send_reg(0); - - //initialize the codec register settings - _ad9862_regs.sdio_bidir = ad9862_regs_t::SDIO_BIDIR_SDIO_SDO; - _ad9862_regs.lsb_first = ad9862_regs_t::LSB_FIRST_MSB; - _ad9862_regs.soft_reset = 0; - - //setup rx side of codec - _ad9862_regs.byp_buffer_a = 1; - _ad9862_regs.byp_buffer_b = 1; - _ad9862_regs.buffer_a_pd = 1; - _ad9862_regs.buffer_b_pd = 1; - _ad9862_regs.rx_pga_a = 0;//0x1f; //TODO bring under api control - _ad9862_regs.rx_pga_b = 0;//0x1f; //TODO bring under api control - _ad9862_regs.rx_twos_comp = 1; - _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS; - - //setup tx side of codec - _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH; - _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; - _ad9862_regs.tx_retime = ad9862_regs_t::TX_RETIME_CLKOUT2; - _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control - _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; - _ad9862_regs.interp = ad9862_regs_t::INTERP_2; - _ad9862_regs.tx_twos_comp = 1; - _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_BYPASS; - _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; - _ad9862_regs.dac_a_coarse_gain = 0x3; - _ad9862_regs.dac_b_coarse_gain = 0x3; - _ad9862_regs.edges = ad9862_regs_t::EDGES_NORMAL; - - //setup the dll - _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL; - _ad9862_regs.dll_mult = ad9862_regs_t::DLL_MULT_2; - _ad9862_regs.dll_mode = ad9862_regs_t::DLL_MODE_FAST; - - //write the register settings to the codec - for (uint8_t addr = 0; addr <= 25; addr++){ - this->send_reg(addr); - } - - //aux adc clock - _ad9862_regs.clk_4 = ad9862_regs_t::CLK_4_1_4; - this->send_reg(34); -} - -usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ - //set aux dacs to zero - this->write_aux_dac(AUX_DAC_A, 0); - this->write_aux_dac(AUX_DAC_B, 0); - this->write_aux_dac(AUX_DAC_C, 0); - this->write_aux_dac(AUX_DAC_D, 0); - - //power down - _ad9862_regs.all_rx_pd = 1; - this->send_reg(1); - _ad9862_regs.tx_digital_pd = 1; - _ad9862_regs.tx_analog_pd = ad9862_regs_t::TX_ANALOG_PD_BOTH; - this->send_reg(8); -} - -/*********************************************************************** - * Codec Control Gain Control Methods - **********************************************************************/ -static const int mtpgw = 255; //maximum tx pga gain word - -void usrp_e_codec_ctrl_impl::set_tx_pga_gain(float gain){ - int gain_word = int(mtpgw*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); - _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw); - this->send_reg(16); -} - -float usrp_e_codec_ctrl_impl::get_tx_pga_gain(void){ - return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/mtpgw) + tx_pga_gain_range.min; -} - -static const int mrpgw = 0x14; //maximum rx pga gain word - -void usrp_e_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){ - int gain_word = int(mrpgw*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min)); - gain_word = std::clip(gain_word, 0, mrpgw); - switch(which){ - case 'A': - _ad9862_regs.rx_pga_a = gain_word; - this->send_reg(2); - return; - case 'B': - _ad9862_regs.rx_pga_b = gain_word; - this->send_reg(3); - return; - default: UHD_THROW_INVALID_CODE_PATH(); - } -} - -float usrp_e_codec_ctrl_impl::get_rx_pga_gain(char which){ - int gain_word; - switch(which){ - case 'A': gain_word = _ad9862_regs.rx_pga_a; break; - case 'B': gain_word = _ad9862_regs.rx_pga_b; break; - default: UHD_THROW_INVALID_CODE_PATH(); - } - return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/mrpgw) + rx_pga_gain_range.min; -} - -/*********************************************************************** - * Codec Control AUX ADC Methods - **********************************************************************/ -static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){ - return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; -} - -float usrp_e_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ - //check to see if the switch needs to be set - bool write_switch = false; - switch(which){ - - case AUX_ADC_A1: - case AUX_ADC_A2: - if (which != _last_aux_adc_a){ - _ad9862_regs.select_a = (which == AUX_ADC_A1)? - ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2; - _last_aux_adc_a = which; - write_switch = true; - } - break; - - case AUX_ADC_B1: - case AUX_ADC_B2: - if (which != _last_aux_adc_b){ - _ad9862_regs.select_b = (which == AUX_ADC_B1)? - ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2; - _last_aux_adc_b = which; - write_switch = true; - } - break; - - } - - //write the switch if it changed - if(write_switch) this->send_reg(34); - - //map aux adcs to register values to read - static const uhd::dict aux_dac_to_addr = boost::assign::map_list_of - (AUX_ADC_A2, 26) (AUX_ADC_A1, 28) - (AUX_ADC_B2, 30) (AUX_ADC_B1, 32) - ; - - //read the value - this->recv_reg(aux_dac_to_addr[which]+0); - this->recv_reg(aux_dac_to_addr[which]+1); - - //return the value scaled to volts - switch(which){ - case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0); - case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0); - case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0); - case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0); - } - UHD_ASSERT_THROW(false); -} - -/*********************************************************************** - * Codec Control AUX DAC Methods - **********************************************************************/ -void usrp_e_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ - //special case for aux dac d (aka sigma delta word) - if (which == AUX_DAC_D){ - boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff); - _ad9862_regs.sig_delt_11_4 = boost::uint8_t(dac_word >> 4); - _ad9862_regs.sig_delt_3_0 = boost::uint8_t(dac_word & 0xf); - this->send_reg(42); - this->send_reg(43); - return; - } - - //calculate the dac word for aux dac a, b, c - boost::uint8_t dac_word = std::clip(boost::math::iround(volts*0xff/3.3), 0, 0xff); - - //setup a lookup table for the aux dac params (reg ref, reg addr) - typedef boost::tuple dac_params_t; - uhd::dict aux_dac_to_params = boost::assign::map_list_of - (AUX_DAC_A, dac_params_t(&_ad9862_regs.aux_dac_a, 36)) - (AUX_DAC_B, dac_params_t(&_ad9862_regs.aux_dac_b, 37)) - (AUX_DAC_C, dac_params_t(&_ad9862_regs.aux_dac_c, 38)) - ; - - //set the aux dac register - UHD_ASSERT_THROW(aux_dac_to_params.has_key(which)); - boost::uint8_t *reg_ref, reg_addr; - boost::tie(reg_ref, reg_addr) = aux_dac_to_params[which]; - *reg_ref = dac_word; - this->send_reg(reg_addr); -} - -/*********************************************************************** - * Codec Control SPI Methods - **********************************************************************/ -void usrp_e_codec_ctrl_impl::send_reg(boost::uint8_t addr){ - boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); - if (codec_debug) std::cout << "codec control write reg: " << std::hex << reg << std::endl; - _iface->transact_spi( - UE_SPI_SS_AD9862, - spi_config_t::EDGE_RISE, - reg, 16, false /*no rb*/ - ); -} - -void usrp_e_codec_ctrl_impl::recv_reg(boost::uint8_t addr){ - boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); - if (codec_debug) std::cout << "codec control read reg: " << std::hex << reg << std::endl; - boost::uint32_t ret = _iface->transact_spi( - UE_SPI_SS_AD9862, - spi_config_t::EDGE_RISE, - reg, 16, true /*rb*/ - ); - if (codec_debug) std::cout << "codec control read ret: " << std::hex << ret << std::endl; - _ad9862_regs.set_reg(addr, boost::uint16_t(ret)); -} - -/*********************************************************************** - * Codec Control Make - **********************************************************************/ -usrp_e_codec_ctrl::sptr usrp_e_codec_ctrl::make(usrp_e_iface::sptr iface){ - return sptr(new usrp_e_codec_ctrl_impl(iface)); -} diff --git a/host/lib/usrp/usrp_e/codec_ctrl.hpp b/host/lib/usrp/usrp_e/codec_ctrl.hpp deleted file mode 100644 index 87b6ff951..000000000 --- a/host/lib/usrp/usrp_e/codec_ctrl.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_USRP_E_CODEC_CTRL_HPP -#define INCLUDED_USRP_E_CODEC_CTRL_HPP - -#include "usrp_e_iface.hpp" -#include -#include -#include - -/*! - * The usrp-e codec control: - * - Init/power down codec. - * - Read aux adc, write aux dac. - */ -class usrp_e_codec_ctrl : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - static const uhd::gain_range_t tx_pga_gain_range; - static const uhd::gain_range_t rx_pga_gain_range; - - /*! - * Make a new codec control object. - * \param iface the usrp_e iface object - * \return the codec control object - */ - static sptr make(usrp_e_iface::sptr iface); - - //! aux adc identifier constants - enum aux_adc_t{ - AUX_ADC_A2 = 0xA2, - AUX_ADC_A1 = 0xA1, - AUX_ADC_B2 = 0xB2, - AUX_ADC_B1 = 0xB1 - }; - - /*! - * Read an auxiliary adc: - * The internals remember which aux adc was read last. - * Therefore, the aux adc switch is only changed as needed. - * \param which which of the 4 adcs - * \return a value in volts - */ - virtual float read_aux_adc(aux_adc_t which) = 0; - - //! aux dac identifier constants - enum aux_dac_t{ - AUX_DAC_A = 0xA, - AUX_DAC_B = 0xB, - AUX_DAC_C = 0xC, - AUX_DAC_D = 0xD //really the sigma delta output - }; - - /*! - * Write an auxiliary dac. - * \param which which of the 4 dacs - * \param volts the level in in volts - */ - virtual void write_aux_dac(aux_dac_t which, float volts) = 0; - - //! Set the TX PGA gain - virtual void set_tx_pga_gain(float gain) = 0; - - //! Get the TX PGA gain - virtual float get_tx_pga_gain(void) = 0; - - //! Set the RX PGA gain ('A' or 'B') - virtual void set_rx_pga_gain(float gain, char which) = 0; - - //! Get the RX PGA gain ('A' or 'B') - virtual float get_rx_pga_gain(char which) = 0; -}; - -#endif /* INCLUDED_USRP_E_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e/codec_impl.cpp b/host/lib/usrp/usrp_e/codec_impl.cpp deleted file mode 100644 index 696fb37ec..000000000 --- a/host/lib/usrp/usrp_e/codec_impl.cpp +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; - -/*********************************************************************** - * Helper Methods - **********************************************************************/ -void usrp_e_impl::codec_init(void){ - //make proxies - _rx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp_e_impl::rx_codec_get, this, _1, _2), - boost::bind(&usrp_e_impl::rx_codec_set, this, _1, _2) - ); - _tx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp_e_impl::tx_codec_get, this, _1, _2), - boost::bind(&usrp_e_impl::tx_codec_set, this, _1, _2) - ); -} - -/*********************************************************************** - * RX Codec Properties - **********************************************************************/ -static const std::string ad9862_pga_gain_name = "ad9862 pga"; - -void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case CODEC_PROP_NAME: - val = std::string("usrp-e adc - ad9522"); - return; - - case CODEC_PROP_OTHERS: - val = prop_names_t(); - return; - - case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); - return; - - case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = usrp_e_codec_ctrl::rx_pga_gain_range; - return; - - case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_rx_pga_gain('A'); - return; - - case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_rx_pga_gain('B'); - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void usrp_e_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the set request conditioned on the key - switch(key.as()){ - case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_rx_pga_gain(val.as(), 'A'); - return; - - case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_rx_pga_gain(val.as(), 'B'); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Codec Properties - **********************************************************************/ -void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case CODEC_PROP_NAME: - val = std::string("usrp-e dac - ad9522"); - return; - - case CODEC_PROP_OTHERS: - val = prop_names_t(); - return; - - case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); - return; - - case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = usrp_e_codec_ctrl::tx_pga_gain_range; - return; - - case CODEC_PROP_GAIN_I: //only one gain for I and Q - case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_tx_pga_gain(); - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void usrp_e_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the set request conditioned on the key - switch(key.as()){ - case CODEC_PROP_GAIN_I: //only one gain for I and Q - case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_tx_pga_gain(val.as()); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp deleted file mode 100644 index 6898df8df..000000000 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ /dev/null @@ -1,298 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_iface.hpp" -#include "usrp_e_regs.hpp" -#include "clock_ctrl.hpp" -#include "codec_ctrl.hpp" -#include -#include -#include -#include -#include //i2c and spi constants - -using namespace uhd; -using namespace uhd::usrp; -using namespace boost::assign; - -class usrp_e_dboard_iface : public dboard_iface{ -public: - - usrp_e_dboard_iface( - usrp_e_iface::sptr iface, - usrp_e_clock_ctrl::sptr clock, - usrp_e_codec_ctrl::sptr codec - ){ - _iface = iface; - _clock = clock; - _codec = codec; - - //init the clock rate shadows - this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); - this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); - - _iface->poke16(UE_REG_GPIO_RX_DBG, 0); - _iface->poke16(UE_REG_GPIO_TX_DBG, 0); - } - - ~usrp_e_dboard_iface(void){ - /* NOP */ - } - - special_props_t get_special_props(void){ - special_props_t props; - props.soft_clock_divider = false; - props.mangle_i2c_addrs = false; - return props; - } - - void write_aux_dac(unit_t, aux_dac_t, float); - float read_aux_adc(unit_t, aux_adc_t); - - void set_pin_ctrl(unit_t, boost::uint16_t); - void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); - void set_gpio_ddr(unit_t, boost::uint16_t); - void write_gpio(unit_t, boost::uint16_t); - void set_gpio_debug(unit_t, int); - boost::uint16_t read_gpio(unit_t); - - void write_i2c(boost::uint8_t, const byte_vector_t &); - byte_vector_t read_i2c(boost::uint8_t, size_t); - - void write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ); - - boost::uint32_t read_write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ); - - void set_clock_rate(unit_t, double); - std::vector get_clock_rates(unit_t); - double get_clock_rate(unit_t); - void set_clock_enabled(unit_t, bool); - double get_codec_rate(unit_t); - -private: - usrp_e_iface::sptr _iface; - usrp_e_clock_ctrl::sptr _clock; - usrp_e_codec_ctrl::sptr _codec; - uhd::dict _clock_rates; -}; - -/*********************************************************************** - * Make Function - **********************************************************************/ -dboard_iface::sptr make_usrp_e_dboard_iface( - usrp_e_iface::sptr iface, - usrp_e_clock_ctrl::sptr clock, - usrp_e_codec_ctrl::sptr codec -){ - return dboard_iface::sptr(new usrp_e_dboard_iface(iface, clock, codec)); -} - -/*********************************************************************** - * Clock Rates - **********************************************************************/ -void usrp_e_dboard_iface::set_clock_rate(unit_t unit, double rate){ - _clock_rates[unit] = rate; - switch(unit){ - case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate); - case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate); - } -} - -std::vector usrp_e_dboard_iface::get_clock_rates(unit_t unit){ - switch(unit){ - case UNIT_RX: return _clock->get_rx_dboard_clock_rates(); - case UNIT_TX: return _clock->get_tx_dboard_clock_rates(); - default: UHD_THROW_INVALID_CODE_PATH(); - } -} - -double usrp_e_dboard_iface::get_clock_rate(unit_t unit){ - return _clock_rates[unit]; -} - -void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ - switch(unit){ - case UNIT_RX: return _clock->enable_rx_dboard_clock(enb); - case UNIT_TX: return _clock->enable_tx_dboard_clock(enb); - } -} - -double usrp_e_dboard_iface::get_codec_rate(unit_t){ - return _clock->get_fpga_clock_rate(); -} - -/*********************************************************************** - * GPIO - **********************************************************************/ -void usrp_e_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){ - UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption - switch(unit){ - case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_SEL, value); return; - case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_SEL, value); return; - } -} - -void usrp_e_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_DDR, value); return; - case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_DDR, value); return; - } -} - -void usrp_e_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_IO, value); return; - case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_IO, value); return; - } -} - -boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t unit){ - switch(unit){ - case UNIT_RX: return _iface->peek16(UE_REG_GPIO_RX_IO); - case UNIT_TX: return _iface->peek16(UE_REG_GPIO_TX_IO); - default: UHD_THROW_INVALID_CODE_PATH(); - } -} - -void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ - //define mapping of unit to atr regs to register address - static const uhd::dict< - unit_t, uhd::dict - > unit_to_atr_to_addr = map_list_of - (UNIT_RX, 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) - ) - (UNIT_TX, 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) - ) - ; - _iface->poke16(unit_to_atr_to_addr[unit][atr], value); -} - -void usrp_e_dboard_iface::set_gpio_debug(unit_t unit, int which){ - //set this unit to all outputs - this->set_gpio_ddr(unit, 0xffff); - - //calculate the debug selections - boost::uint32_t dbg_sels = 0x0; - int sel = (which == 0)? GPIO_SEL_DEBUG_0 : GPIO_SEL_DEBUG_1; - for(size_t i = 0; i < 16; i++) dbg_sels |= sel << i; - - //set the debug on and which debug selection - switch(unit){ - case UNIT_RX: - _iface->poke16(UE_REG_GPIO_RX_DBG, 0xffff); - _iface->poke16(UE_REG_GPIO_RX_SEL, dbg_sels); - return; - - case UNIT_TX: - _iface->poke16(UE_REG_GPIO_TX_DBG, 0xffff); - _iface->poke16(UE_REG_GPIO_TX_SEL, dbg_sels); - return; - } -} - -/*********************************************************************** - * SPI - **********************************************************************/ -/*! - * Static function to convert a unit type to a spi slave device number. - * \param unit the dboard interface unit type enum - * \return the slave device number - */ -static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit){ - switch(unit){ - case dboard_iface::UNIT_TX: return UE_SPI_SS_TX_DB; - case dboard_iface::UNIT_RX: return UE_SPI_SS_RX_DB; - } - throw std::invalid_argument("unknown unit type"); -} - -void usrp_e_dboard_iface::write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits -){ - _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); -} - -boost::uint32_t usrp_e_dboard_iface::read_write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits -){ - return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); -} - -/*********************************************************************** - * I2C - **********************************************************************/ -void usrp_e_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ - return _iface->write_i2c(addr, bytes); -} - -byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ - return _iface->read_i2c(addr, num_bytes); -} - -/*********************************************************************** - * Aux DAX/ADC - **********************************************************************/ -void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which, float value){ - //same aux dacs for each unit - static const uhd::dict which_to_aux_dac = map_list_of - (AUX_DAC_A, usrp_e_codec_ctrl::AUX_DAC_A) - (AUX_DAC_B, usrp_e_codec_ctrl::AUX_DAC_B) - (AUX_DAC_C, usrp_e_codec_ctrl::AUX_DAC_C) - (AUX_DAC_D, usrp_e_codec_ctrl::AUX_DAC_D) - ; - _codec->write_aux_dac(which_to_aux_dac[which], value); -} - -float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, aux_adc_t which){ - static const uhd::dict< - unit_t, uhd::dict - > unit_to_which_to_aux_adc = map_list_of - (UNIT_RX, map_list_of - (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A1) - (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B1) - ) - (UNIT_TX, map_list_of - (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A2) - (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B2) - ) - ; - return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]); -} diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp deleted file mode 100644 index f2840dcfc..000000000 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" -#include -#include -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; - -/*********************************************************************** - * Dboard Initialization - **********************************************************************/ -void usrp_e_impl::dboard_init(void){ - _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); - _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); - - //create a new dboard interface and manager - _dboard_iface = make_usrp_e_dboard_iface( - _iface, _clock_ctrl, _codec_ctrl - ); - _dboard_manager = dboard_manager::make( - _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface - ); - - //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 &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case DBOARD_PROP_NAME: - val = std::string("usrp-e dboard (rx unit)"); - return; - - case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_rx_subdev(key.name); - return; - - case DBOARD_PROP_SUBDEV_NAMES: - val = _dboard_manager->get_rx_subdev_names(); - return; - - case DBOARD_PROP_DBOARD_ID: - val = _rx_db_eeprom.id; - return; - - case DBOARD_PROP_DBOARD_IFACE: - val = _dboard_iface; - return; - - case DBOARD_PROP_CODEC: - val = _rx_codec_proxy->get_link(); - return; - - case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group( - _rx_db_eeprom.id, - _dboard_manager->get_rx_subdev(key.name), - _rx_codec_proxy->get_link(), - GAIN_GROUP_POLICY_RX - ); - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -/*********************************************************************** - * RX Dboard Set - **********************************************************************/ -void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ - switch(key.as()){ - case DBOARD_PROP_DBOARD_ID: - _rx_db_eeprom.id = val.as(); - _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes()); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Dboard Get - **********************************************************************/ -void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case DBOARD_PROP_NAME: - val = std::string("usrp-e dboard (tx unit)"); - return; - - case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_tx_subdev(key.name); - return; - - case DBOARD_PROP_SUBDEV_NAMES: - val = _dboard_manager->get_tx_subdev_names(); - return; - - case DBOARD_PROP_DBOARD_ID: - val = _tx_db_eeprom.id; - return; - - case DBOARD_PROP_DBOARD_IFACE: - val = _dboard_iface; - return; - - case DBOARD_PROP_CODEC: - val = _tx_codec_proxy->get_link(); - return; - - case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group( - _tx_db_eeprom.id, - _dboard_manager->get_tx_subdev(key.name), - _tx_codec_proxy->get_link(), - GAIN_GROUP_POLICY_TX - ); - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -/*********************************************************************** - * TX Dboard Set - **********************************************************************/ -void usrp_e_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ - switch(key.as()){ - case DBOARD_PROP_DBOARD_ID: - _tx_db_eeprom.id = val.as(); - _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes()); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp deleted file mode 100644 index 97f173c1a..000000000 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" -#include -#include -#include -#include - -#define rint boost::math::iround - -using namespace uhd; -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) - ); - - //initial config and update - rx_ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); - rx_ddc_set(DSP_PROP_HOST_RATE, double(64e6/10)); -} - -/*********************************************************************** - * RX DDC Get - **********************************************************************/ -void usrp_e_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - switch(key.as()){ - case DSP_PROP_NAME: - val = std::string("usrp-e ddc0"); - return; - - case DSP_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case DSP_PROP_FREQ_SHIFT: - val = _ddc_freq; - return; - - case DSP_PROP_FREQ_SHIFT_NAMES: - val = prop_names_t(1, ""); - return; - - case DSP_PROP_CODEC_RATE: - val = _clock_ctrl->get_fpga_clock_rate(); - return; - - case DSP_PROP_HOST_RATE: - val = _clock_ctrl->get_fpga_clock_rate()/_ddc_decim; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -/*********************************************************************** - * RX DDC Set - **********************************************************************/ -void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - switch(key.as()){ - - case DSP_PROP_FREQ_SHIFT:{ - double new_freq = val.as(); - _iface->poke32(UE_REG_DSP_RX_FREQ, - dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) - ); - _ddc_freq = new_freq; //shadow - } - return; - - case DSP_PROP_HOST_RATE:{ - //set the decimation - _ddc_decim = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); - _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); - - //set the scaling - static const boost::int16_t default_rx_scale_iq = 1024; - _iface->poke32(UE_REG_DSP_RX_SCALE_IQ, - dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) - ); - } - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * 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) - ); - - //initial config and update - tx_duc_set(DSP_PROP_FREQ_SHIFT, double(0)); - tx_duc_set(DSP_PROP_HOST_RATE, double(64e6/10)); -} - -/*********************************************************************** - * TX DUC Get - **********************************************************************/ -void usrp_e_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - switch(key.as()){ - case DSP_PROP_NAME: - val = std::string("usrp-e duc0"); - return; - - case DSP_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case DSP_PROP_FREQ_SHIFT: - val = _duc_freq; - return; - - case DSP_PROP_FREQ_SHIFT_NAMES: - val = prop_names_t(1, ""); - return; - - case DSP_PROP_CODEC_RATE: - val = _clock_ctrl->get_fpga_clock_rate(); - return; - - case DSP_PROP_HOST_RATE: - val = _clock_ctrl->get_fpga_clock_rate()/_duc_interp; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -/*********************************************************************** - * TX DUC Set - **********************************************************************/ -void usrp_e_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - switch(key.as()){ - - case DSP_PROP_FREQ_SHIFT:{ - double new_freq = val.as(); - _iface->poke32(UE_REG_DSP_TX_FREQ, - dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) - ); - _duc_freq = new_freq; //shadow - } - return; - - case DSP_PROP_HOST_RATE:{ - _duc_interp = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); - - //set the interpolation - _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp)); - - //set the scaling - _iface->poke32(UE_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_duc_interp)); - } - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc deleted file mode 100644 index 4dc537919..000000000 --- a/host/lib/usrp/usrp_e/fpga-downloader.cc +++ /dev/null @@ -1,274 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -/* - * 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 (not export_file.is_open()) throw std::runtime_error( - "Failed to open gpio export file." - ); - - 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; - - if (gpio_num != 114) { - 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); -} -*/ - -void 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 << "Loading FPGA image: " << bin_file << "... " << std::flush; - - UHD_ASSERT_THROW(std::system("/sbin/rmmod usrp_e") == 0); - - 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); - - UHD_ASSERT_THROW(std::system("/sbin/modprobe usrp_e") == 0); - -} - diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp deleted file mode 100644 index e863944e8..000000000 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" -#include -#include -#include -#include "../../transport/vrt_packet_handler.hpp" -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::transport; - -zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); - -/*********************************************************************** - * Constants - **********************************************************************/ -static const size_t tx_async_report_sid = 1; -static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; -static const bool recv_debug = false; - -/*********************************************************************** - * io impl details (internal to this file) - * - pirate crew of 1 - * - bounded buffer - * - thread loop - * - vrt packet handler states - **********************************************************************/ -struct usrp_e_impl::io_impl{ - //state management for the vrt packet handler code - vrt_packet_handler::recv_state packet_handler_recv_state; - vrt_packet_handler::send_state packet_handler_send_state; - zero_copy_if::sptr data_xport; - bool continuous_streaming; - io_impl(usrp_e_iface::sptr iface): - data_xport(usrp_e_make_mmap_zero_copy(iface)), - recv_pirate_booty(recv_booty_type::make(data_xport->get_num_recv_frames())), - async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) - { - /* NOP */ - } - - ~io_impl(void){ - recv_pirate_crew_raiding = false; - recv_pirate_crew.interrupt_all(); - recv_pirate_crew.join_all(); - } - - bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){ - UHD_ASSERT_THROW(buffs.size() == 1); - boost::this_thread::disable_interruption di; //disable because the wait can throw - return recv_pirate_booty->pop_with_timed_wait(buffs.front(), timeout); - } - - //a pirate's life is the life for me! - void recv_pirate_loop(usrp_e_clock_ctrl::sptr); - typedef bounded_buffer recv_booty_type; - recv_booty_type::sptr recv_pirate_booty; - bounded_buffer::sptr async_msg_fifo; - boost::thread_group recv_pirate_crew; - bool recv_pirate_crew_raiding; -}; - -/*********************************************************************** - * Receive Pirate Loop - * - while raiding, loot for recv buffers - * - put booty into the alignment buffer - **********************************************************************/ -void usrp_e_impl::io_impl::recv_pirate_loop(usrp_e_clock_ctrl::sptr clock_ctrl) -{ - set_thread_priority_safe(); - recv_pirate_crew_raiding = true; - - while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(); - if (not buff.get()) continue; //ignore timeout/error buffers - - if (recv_debug){ - std::cout << "len " << buff->size() << std::endl; - for (size_t i = 0; i < 9; i++){ - std::cout << boost::format(" 0x%08x") % buff->cast()[i] << std::endl; - } - std::cout << std::endl << std::endl; - } - - try{ - //extract the vrt header packet info - vrt::if_packet_info_t if_packet_info; - if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); - const boost::uint32_t *vrt_hdr = buff->cast(); - vrt::if_hdr_unpack_le(vrt_hdr, if_packet_info); - - //handle a tx async report message - if (if_packet_info.sid == tx_async_report_sid and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ - - //fill in the async metadata - async_metadata_t metadata; - metadata.channel = 0; - metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; - metadata.time_spec = time_spec_t( - time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), clock_ctrl->get_fpga_clock_rate() - ); - metadata.event_code = vrt_packet_handler::get_context_code(vrt_hdr, if_packet_info); - - //print the famous U, and push the metadata into the message queue - if (metadata.event_code & underflow_flags) std::cerr << "U" << std::flush; - async_msg_fifo->push_with_pop_on_full(metadata); - continue; - } - - //same number of frames as the data transport -> always immediate - recv_pirate_booty->push_with_wait(buff); - - }catch(const std::exception &e){ - std::cerr << "Error (usrp-e recv pirate loop): " << e.what() << std::endl; - } - } -} - -/*********************************************************************** - * Helper Functions - **********************************************************************/ -void usrp_e_impl::io_init(void){ - //setup otw types - _send_otw_type.width = 16; - _send_otw_type.shift = 0; - _send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - - _recv_otw_type.width = 16; - _recv_otw_type.shift = 0; - _recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - - //setup before the registers (transport called to calculate max spp) - _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface)); - - //setup rx data path - _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); - _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); - _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 1); //reset - _iface->poke32(UE_REG_CTRL_RX_VRT_HEADER, 0 - | (0x1 << 28) //if data with stream id - | (0x1 << 26) //has trailer - | (0x3 << 22) //integer time other - | (0x1 << 20) //fractional time sample count - ); - _iface->poke32(UE_REG_CTRL_RX_VRT_STREAM_ID, 0); - _iface->poke32(UE_REG_CTRL_RX_VRT_TRAILER, 0); - - //setup the tx policy - _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, tx_async_report_sid); - _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); - - //spawn a pirate, yarrr! - _io_impl->recv_pirate_crew.create_thread(boost::bind( - &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl - )); -} - -void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ - _io_impl->continuous_streaming = (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, dsp_type1::calc_stream_cmd_word( - stream_cmd, get_max_recv_samps_per_packet() - )); - _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); - _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); -} - -void usrp_e_impl::handle_overrun(size_t){ - std::cerr << "O"; //the famous OOOOOOOOOOO - _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 0); - if (_io_impl->continuous_streaming){ - this->issue_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - } -} - -/*********************************************************************** - * Data Send - **********************************************************************/ -bool get_send_buffs( - zero_copy_if::sptr trans, double timeout, - vrt_packet_handler::managed_send_buffs_t &buffs -){ - UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = trans->get_send_buff(timeout); - return buffs[0].get() != NULL; -} - -size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ - static const size_t hdr_size = 0 - + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - ; - size_t bpp = _io_impl->data_xport->get_send_frame_size() - hdr_size; - return bpp/_send_otw_type.get_sample_size(); -} - -size_t usrp_e_impl::send( - const std::vector &buffs, size_t num_samps, - const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode, double timeout -){ - return vrt_packet_handler::send( - _io_impl->packet_handler_send_state, //last state of the send handler - buffs, num_samps, //buffer to fill - metadata, send_mode, //samples metadata - io_type, _send_otw_type, //input and output types to convert - _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate - uhd::transport::vrt::if_hdr_pack_le, - boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), - get_max_send_samps_per_packet() - ); -} - -/*********************************************************************** - * Data Recv - **********************************************************************/ -size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ - static const size_t hdr_size = 0 - + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - ; - size_t bpp = _io_impl->data_xport->get_recv_frame_size() - hdr_size; - return bpp/_recv_otw_type.get_sample_size(); -} - -size_t usrp_e_impl::recv( - const std::vector &buffs, size_t num_samps, - rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, double timeout -){ - return vrt_packet_handler::recv( - _io_impl->packet_handler_recv_state, //last state of the recv handler - buffs, num_samps, //buffer to fill - metadata, recv_mode, //samples metadata - io_type, _recv_otw_type, //input and output types to convert - _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate - uhd::transport::vrt::if_hdr_unpack_le, - boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), - boost::bind(&usrp_e_impl::handle_overrun, this, _1) - ); -} - -/*********************************************************************** - * Async Recv - **********************************************************************/ -bool usrp_e_impl::recv_async_msg( - async_metadata_t &async_metadata, double timeout -){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - return _io_impl->async_msg_fifo->pop_with_timed_wait(async_metadata, timeout); -} diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp deleted file mode 100644 index f0118aa4b..000000000 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" -#include -#include -#include -#include -#include -#include - -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){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - 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: - UHD_ASSERT_THROW(key.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: - UHD_ASSERT_THROW(key.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_RX_DSP: - UHD_ASSERT_THROW(key.name == ""); - val = _rx_ddc_proxy->get_link(); - return; - - case MBOARD_PROP_RX_DSP_NAMES: - val = prop_names_t(1, ""); - return; - - case MBOARD_PROP_TX_DSP: - UHD_ASSERT_THROW(key.name == ""); - val = _tx_duc_proxy->get_link(); - return; - - case MBOARD_PROP_TX_DSP_NAMES: - val = prop_names_t(1, ""); - return; - - case MBOARD_PROP_CLOCK_CONFIG: - val = _clock_config; - return; - - case MBOARD_PROP_RX_SUBDEV_SPEC: - val = _rx_subdev_spec; - return; - - case MBOARD_PROP_TX_SUBDEV_SPEC: - val = _tx_subdev_spec; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -/*********************************************************************** - * Mboard Set - **********************************************************************/ -void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ - //handle the get request conditioned on the key - switch(key.as()){ - - case MBOARD_PROP_STREAM_CMD: - issue_stream_cmd(val.as()); - return; - - case MBOARD_PROP_TIME_NOW: - case MBOARD_PROP_TIME_NEXT_PPS:{ - time_spec_t time_spec = val.as(); - _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); - boost::uint32_t imm_flags = (key.as() == MBOARD_PROP_TIME_NOW)? 1 : 0; - _iface->poke32(UE_REG_TIME64_IMM, imm_flags); - _iface->poke32(UE_REG_TIME64_SECS, time_spec.get_full_secs()); - } - return; - - case MBOARD_PROP_RX_SUBDEV_SPEC: - _rx_subdev_spec = val.as(); - verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link()); - //sanity check - UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); - //set the mux - _iface->poke32(UE_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( - _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as() - )); - return; - - case MBOARD_PROP_TX_SUBDEV_SPEC: - _tx_subdev_spec = val.as(); - verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link()); - //sanity check - UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); - //set the mux - _iface->poke32(UE_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( - _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as() - )); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.cpp b/host/lib/usrp/usrp_e/usrp_e_iface.cpp deleted file mode 100644 index f00e92946..000000000 --- a/host/lib/usrp/usrp_e/usrp_e_iface.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_iface.hpp" -#include -#include //ioctl -#include //open, close -#include //ioctl structures and constants -#include -#include //mutex -#include - -using namespace uhd; - -class usrp_e_iface_impl : public usrp_e_iface{ -public: - - int get_file_descriptor(void){ - return _node_fd; - } - - /******************************************************************* - * Structors - ******************************************************************/ - usrp_e_iface_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 - )); - } - } - - ~usrp_e_iface_impl(void){ - //close the device node file descriptor - ::close(_node_fd); - } - - /******************************************************************* - * IOCTL: provides the communication base for all other calls - ******************************************************************/ - void ioctl(int request, void *mem){ - boost::mutex::scoped_lock lock(_ctrl_mutex); - - if (::ioctl(_node_fd, request, mem) < 0){ - throw std::runtime_error(str( - boost::format("ioctl failed with request %d") % request - )); - } - } - - /******************************************************************* - * Peek and Poke - ******************************************************************/ - void 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 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 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 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]; - } - - /******************************************************************* - * I2C - ******************************************************************/ - static const size_t max_i2c_data_bytes = 10; - - void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ - //allocate some memory for this transaction - UHD_ASSERT_THROW(bytes.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(mem); - data->addr = addr; - data->len = bytes.size(); - std::copy(bytes.begin(), bytes.end(), data->data); - - //call the spi ioctl - this->ioctl(USRP_E_I2C_WRITE, data); - } - - byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ - //allocate some memory for this transaction - UHD_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(mem); - data->addr = addr; - data->len = num_bytes; - - //call the spi ioctl - this->ioctl(USRP_E_I2C_READ, data); - - //unload the data - byte_vector_t bytes(data->len); - UHD_ASSERT_THROW(bytes.size() == num_bytes); - std::copy(data->data, data->data+bytes.size(), bytes.begin()); - return bytes; - } - - /******************************************************************* - * SPI - ******************************************************************/ - boost::uint32_t transact_spi( - int which_slave, - const spi_config_t &config, - boost::uint32_t bits, - size_t num_bits, - bool readback - ){ - //load data struct - usrp_e_spi data; - data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; - data.slave = which_slave; - data.length = num_bits; - data.data = bits; - - //load the flags - data.flags = 0; - data.flags |= (config.miso_edge == spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; - data.flags |= (config.mosi_edge == spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; - - //call the spi ioctl - this->ioctl(USRP_E_SPI, &data); - - //unload the data - return data.data; - } - -private: - int _node_fd; - boost::mutex _ctrl_mutex; -}; - -/*********************************************************************** - * Public Make Function - **********************************************************************/ -usrp_e_iface::sptr usrp_e_iface::make(const std::string &node){ - return sptr(new usrp_e_iface_impl(node)); -} diff --git a/host/lib/usrp/usrp_e/usrp_e_iface.hpp b/host/lib/usrp/usrp_e/usrp_e_iface.hpp deleted file mode 100644 index 59aac43d9..000000000 --- a/host/lib/usrp/usrp_e/usrp_e_iface.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_USRP_E_IFACE_HPP -#define INCLUDED_USRP_E_IFACE_HPP - -#include -#include -#include -#include -#include - -//////////////////////////////////////////////////////////////////////// -// I2C addresses -//////////////////////////////////////////////////////////////////////// -#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx -#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) -#define I2C_ADDR_TX_DB (I2C_DEV_EEPROM | 0x4) -#define I2C_ADDR_RX_DB (I2C_DEV_EEPROM | 0x5) -//////////////////////////////////////////////////////////////////////// - -/*! - * The usrp-e interface class: - * Provides a set of functions to implementation layer. - * Including spi, peek, poke, control... - */ -class usrp_e_iface : boost::noncopyable, public uhd::i2c_iface{ -public: - typedef boost::shared_ptr sptr; - - /*! - * Make a new usrp-e interface with the control transport. - * \param node the device node name - * \return a new usrp-e interface object - */ - static sptr make(const std::string &node); - - /*! - * Get the underlying file descriptor. - * \return the file descriptor - */ - virtual int get_file_descriptor(void) = 0; - - /*! - * 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 - */ - virtual void ioctl(int request, void *mem) = 0; - - /*! - * Write a register (32 bits) - * \param addr the address - * \param data the 32bit data - */ - virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; - - /*! - * Read a register (32 bits) - * \param addr the address - * \return the 32bit data - */ - virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; - - /*! - * Write a register (16 bits) - * \param addr the address - * \param data the 16bit data - */ - virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; - - /*! - * Read a register (16 bits) - * \param addr the address - * \return the 16bit data - */ - virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; - - /*! - * Perform an spi transaction. - * \param which_slave the slave device number - * \param config spi config args - * \param data the bits to write - * \param num_bits how many bits in data - * \param readback true to readback a value - * \return spi data if readback set - */ - virtual boost::uint32_t transact_spi( - int which_slave, - const uhd::spi_config_t &config, - boost::uint32_t data, - size_t num_bits, - bool readback - ) = 0; -}; - -#endif /* INCLUDED_USRP_E_IFACE_HPP */ diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp deleted file mode 100644 index 70cc399fb..000000000 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; -namespace fs = boost::filesystem; - -/*********************************************************************** - * Helper Functions - **********************************************************************/ -static std::string abs_path(const std::string &file_path){ - return fs::system_complete(fs::path(file_path)).file_string(); -} - -/*********************************************************************** - * Discovery - **********************************************************************/ -static device_addrs_t usrp_e_find(const device_addr_t &hint){ - device_addrs_t usrp_e_addrs; - - //return an empty list of addresses when type is set to non-usrp-e - if (hint.has_key("type") and hint["type"] != "usrp-e") return usrp_e_addrs; - - //device node not provided, assume its 0 - if (not hint.has_key("node")){ - device_addr_t new_addr = hint; - new_addr["node"] = "/dev/usrp_e0"; - return usrp_e_find(new_addr); - } - - //use the given device node name - if (fs::exists(hint["node"])){ - device_addr_t new_addr; - new_addr["type"] = "usrp-e"; - new_addr["node"] = abs_path(hint["node"]); - usrp_e_addrs.push_back(new_addr); - } - - return usrp_e_addrs; -} - -/*********************************************************************** - * Make - **********************************************************************/ -static device::sptr usrp_e_make(const device_addr_t &device_addr){ - - //setup the main interface into fpga - std::string node = device_addr["node"]; - std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; - usrp_e_iface::sptr iface = usrp_e_iface::make(node); - - //------------------------------------------------------------------ - //-- Handle the FPGA loading... - //-- The image can be confimed as already loaded when: - //-- 1) The compatibility number matches. - //-- 2) The hash in the hash-file matches. - //------------------------------------------------------------------ - static const char *hash_file_path = "/tmp/usrp_e100_hash"; - - //extract the fpga path for usrp-e - std::string usrp_e_fpga_image = find_image_path( - device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" - ); - - //calculate a hash of the fpga file - size_t fpga_hash = 0; - { - std::ifstream file(usrp_e_fpga_image.c_str()); - if (not file.good()) throw std::runtime_error( - "cannot open fpga file for read: " + usrp_e_fpga_image - ); - do{ - boost::hash_combine(fpga_hash, file.get()); - } while (file.good()); - file.close(); - } - - //read the compatibility number - boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); - - //read the hash in the hash-file - size_t loaded_hash = 0; - try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} - - //if not loaded: load the fpga image and write the hash-file - if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ - iface.reset(); - usrp_e_load_fpga(usrp_e_fpga_image); - std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl; - iface = usrp_e_iface::make(node); - try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} - } - - //check that the compatibility is correct - fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); - if (fpga_compat_num != USRP_E_COMPAT_NUM){ - throw std::runtime_error(str(boost::format( - "Expected fpga compatibility number 0x%x, but got 0x%x:\n" - "The fpga build is not compatible with the host code build." - ) % USRP_E_COMPAT_NUM % fpga_compat_num)); - } - - return device::sptr(new usrp_e_impl(iface)); -} - -UHD_STATIC_BLOCK(register_usrp_e_device){ - device::register_device(&usrp_e_find, &usrp_e_make); -} - -/*********************************************************************** - * Structors - **********************************************************************/ -usrp_e_impl::usrp_e_impl(usrp_e_iface::sptr iface): _iface(iface){ - - //setup interfaces into hardware - _clock_ctrl = usrp_e_clock_ctrl::make(_iface); - _codec_ctrl = usrp_e_codec_ctrl::make(_iface); - - //initialize the mboard - mboard_init(); - - //initialize the dboards - dboard_init(); - - //initialize the dsps - rx_ddc_init(); - tx_duc_init(); - - //init the codec properties - codec_init(); - - //init the io send/recv - io_init(); - - //set default subdev specs - this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t()); - this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t()); -} - -usrp_e_impl::~usrp_e_impl(void){ - /* NOP */ -} - -/*********************************************************************** - * Device Get - **********************************************************************/ -void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case DEVICE_PROP_NAME: - val = std::string("usrp-e device"); - return; - - case DEVICE_PROP_MBOARD: - UHD_ASSERT_THROW(key.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; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -/*********************************************************************** - * Device Set - **********************************************************************/ -void usrp_e_impl::set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); -} diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp deleted file mode 100644 index b5f21810d..000000000 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_iface.hpp" -#include "clock_ctrl.hpp" -#include "codec_ctrl.hpp" -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef INCLUDED_USRP_E_IMPL_HPP -#define INCLUDED_USRP_E_IMPL_HPP - -static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; - -//! load an fpga image from a bin file into the usrp-e fpga -extern void usrp_e_load_fpga(const std::string &bin_file); - -/*! - * Make a usrp-e dboard interface. - * \param iface the usrp-e interface object - * \param clock the clock control interface - * \param codec the codec control interface - * \return a sptr to a new dboard interface - */ -uhd::usrp::dboard_iface::sptr make_usrp_e_dboard_iface( - usrp_e_iface::sptr iface, - usrp_e_clock_ctrl::sptr clock, - usrp_e_codec_ctrl::sptr codec -); - -/*! - * 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 get_t; - typedef boost::function set_t; - typedef boost::shared_ptr sptr; - - static sptr make(const get_t &get, const set_t &set){ - return sptr(new wax_obj_proxy(get, set)); - } - -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(usrp_e_iface::sptr); - ~usrp_e_impl(void); - - //the io interface - size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); - size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); - bool recv_async_msg(uhd::async_metadata_t &, double); - size_t get_max_send_samps_per_packet(void) const; - size_t get_max_recv_samps_per_packet(void) const; - -private: - //interface to ioctls and file descriptor - usrp_e_iface::sptr _iface; - - //handle io stuff - UHD_PIMPL_DECL(io_impl) _io_impl; - uhd::otw_type_t _send_otw_type, _recv_otw_type; - void io_init(void); - void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); - void handle_overrun(size_t); - - //configuration shadows - uhd::clock_config_t _clock_config; - //TODO otw type recv/send - - //ad9522 clock control - usrp_e_clock_ctrl::sptr _clock_ctrl; - - //ad9862 codec control - usrp_e_codec_ctrl::sptr _codec_ctrl; - - //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; - uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; - - //xx dboard functions and settings - void dboard_init(void); - uhd::usrp::dboard_manager::sptr _dboard_manager; - uhd::usrp::dboard_iface::sptr _dboard_iface; - - //rx dboard functions and settings - uhd::usrp::dboard_eeprom_t _rx_db_eeprom; - 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 - uhd::usrp::dboard_eeprom_t _tx_db_eeprom; - 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 &); - double _ddc_freq; size_t _ddc_decim; - 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 &); - double _duc_freq; size_t _duc_interp; - wax_obj_proxy::sptr _tx_duc_proxy; - - //codec functions and settings - void codec_init(void); - void rx_codec_get(const wax::obj &, wax::obj &); - void rx_codec_set(const wax::obj &, const wax::obj &); - void tx_codec_get(const wax::obj &, wax::obj &); - void tx_codec_set(const wax::obj &, const wax::obj &); - wax_obj_proxy::sptr _rx_codec_proxy, _tx_codec_proxy; -}; - -#endif /* INCLUDED_USRP_E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp deleted file mode 100644 index 274bb043e..000000000 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_iface.hpp" -#include -#include -#include -#include //mmap -#include //getpagesize -#include //poll -#include -#include -#include - -using namespace uhd; -using namespace uhd::transport; - -static const bool fp_verbose = false; //fast-path verbose -static const bool sp_verbose = false; //slow-path verbose -static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout - -/*********************************************************************** - * The zero copy interface implementation - **********************************************************************/ -class usrp_e_mmap_zero_copy_impl : public zero_copy_if, public boost::enable_shared_from_this { -public: - usrp_e_mmap_zero_copy_impl(usrp_e_iface::sptr iface): - _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) - { - //get system sizes - iface->ioctl(USRP_E_GET_RB_INFO, &_rb_size); - size_t page_size = getpagesize(); - _frame_size = page_size/2; - - //calculate the memory size - _map_size = - (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + - (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; - - //print sizes summary - if (sp_verbose){ - std::cout << "page_size: " << page_size << std::endl; - std::cout << "frame_size: " << _frame_size << std::endl; - std::cout << "num_pages_rx_flags: " << _rb_size.num_pages_rx_flags << std::endl; - std::cout << "num_rx_frames: " << _rb_size.num_rx_frames << std::endl; - std::cout << "num_pages_tx_flags: " << _rb_size.num_pages_tx_flags << std::endl; - std::cout << "num_tx_frames: " << _rb_size.num_tx_frames << std::endl; - std::cout << "map_size: " << _map_size << std::endl; - } - - //call mmap to get the memory - _mapped_mem = ::mmap( - NULL, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 - ); - UHD_ASSERT_THROW(_mapped_mem != MAP_FAILED); - - //calculate the memory offsets for info and buffers - size_t recv_info_off = 0; - size_t recv_buff_off = recv_info_off + (_rb_size.num_pages_rx_flags * page_size); - size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); - size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); - - //print offset summary - if (sp_verbose){ - std::cout << "recv_info_off: " << recv_info_off << std::endl; - std::cout << "recv_buff_off: " << recv_buff_off << std::endl; - std::cout << "send_info_off: " << send_info_off << std::endl; - std::cout << "send_buff_off: " << send_buff_off << std::endl; - } - - //set the internal pointers for info and buffers - typedef ring_buffer_info (*rbi_pta)[]; - char *rb_ptr = reinterpret_cast(_mapped_mem); - _recv_info = reinterpret_cast(rb_ptr + recv_info_off); - _recv_buff = rb_ptr + recv_buff_off; - _send_info = reinterpret_cast(rb_ptr + send_info_off); - _send_buff = rb_ptr + send_buff_off; - } - - ~usrp_e_mmap_zero_copy_impl(void){ - if (sp_verbose) std::cout << "cleanup: munmap" << std::endl; - ::munmap(_mapped_mem, _map_size); - } - - managed_recv_buffer::sptr get_recv_buff(double timeout){ - if (fp_verbose) std::cout << "get_recv_buff: " << _recv_index << std::endl; - - //grab pointers to the info and buffer - ring_buffer_info *info = (*_recv_info) + _recv_index; - void *mem = _recv_buff + _frame_size*_recv_index; - - //poll/wait for a ready frame - if (not (info->flags & RB_USER)){ - for (size_t i = 0; i < poll_breakout; i++){ - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLIN; - ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3/poll_breakout)); - if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; - if (poll_ret > 0) goto found_user_frame; //good poll, continue on - } - return managed_recv_buffer::sptr(); //timed-out for real - } found_user_frame: - - //the process has claimed the frame - info->flags = RB_USER_PROCESS; - - //increment the index for the next call - if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; - - //return the managed buffer for this frame - if (fp_verbose) std::cout << " make_recv_buff: " << info->len << std::endl; - return managed_recv_buffer::make_safe( - boost::asio::const_buffer(mem, info->len), - boost::bind(&usrp_e_mmap_zero_copy_impl::release, shared_from_this(), info) - ); - } - - size_t get_num_recv_frames(void) const{ - return _rb_size.num_rx_frames; - } - - size_t get_recv_frame_size(void) const{ - return _frame_size; - } - - managed_send_buffer::sptr get_send_buff(double timeout){ - if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; - - //grab pointers to the info and buffer - ring_buffer_info *info = (*_send_info) + _send_index; - void *mem = _send_buff + _frame_size*_send_index; - - //poll/wait for a ready frame - if (not (info->flags & RB_KERNEL)){ - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLOUT; - ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); - if (fp_verbose) std::cout << " POLLOUT: " << poll_ret << std::endl; - if (poll_ret <= 0) return managed_send_buffer::sptr(); - } - - //increment the index for the next call - if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; - - //return the managed buffer for this frame - if (fp_verbose) std::cout << " make_send_buff: " << _frame_size << std::endl; - return managed_send_buffer::make_safe( - boost::asio::mutable_buffer(mem, _frame_size), - boost::bind(&usrp_e_mmap_zero_copy_impl::commit, shared_from_this(), info, _1) - ); - } - - size_t get_num_send_frames(void) const{ - return _rb_size.num_tx_frames; - } - - size_t get_send_frame_size(void) const{ - return _frame_size; - } - -private: - - void release(ring_buffer_info *info){ - if (fp_verbose) std::cout << "recv buff: release" << std::endl; - info->flags = RB_KERNEL; - } - - void commit(ring_buffer_info *info, size_t len){ - if (fp_verbose) std::cout << "send buff: commit " << len << std::endl; - info->len = len; - info->flags = RB_USER; - if (::write(_fd, NULL, 0) < 0){ - std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl; - } - } - - int _fd; - - //the mapped memory itself - void *_mapped_mem; - - //mapped memory sizes - usrp_e_ring_buffer_size_t _rb_size; - size_t _frame_size, _map_size; - - //pointers to sections in the mapped memory - ring_buffer_info (*_recv_info)[], (*_send_info)[]; - char *_recv_buff, *_send_buff; - - //indexes into sub-sections of mapped memory - size_t _recv_index, _send_index; -}; - -/*********************************************************************** - * The zero copy interface make function - **********************************************************************/ -zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface){ - return zero_copy_if::sptr(new usrp_e_mmap_zero_copy_impl(iface)); -} diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp deleted file mode 100644 index 8bfb08b6f..000000000 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ /dev/null @@ -1,198 +0,0 @@ - - -//////////////////////////////////////////////////////////////// -// -// 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) -#define UE_REG_SR_ADDR(n) ((UE_REG_SLAVE(5)) + (4*(n))) - -///////////////////////////////////////////////////// -// 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 -#define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 -#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 -#define UE_REG_MISC_XFER_RATE UE_REG_MISC_BASE + 14 -#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 16 - -///////////////////////////////////////////////////// -// 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) - -//spi slave constants -#define UE_SPI_SS_AD9522 (1 << 3) -#define UE_SPI_SS_AD9862 (1 << 2) -#define UE_SPI_SS_TX_DB (1 << 1) -#define UE_SPI_SS_RX_DB (1 << 0) - -//////////////////////////////////////////////// -// 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 - -//possible bit values for sel when dbg is 0: -#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 - -//possible bit values for sel when dbg is 1: -#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 - -///////////////////////////////////////////////// -// DSP RX Regs -//////////////////////////////////////////////// -#define UE_REG_DSP_RX_FREQ UE_REG_SR_ADDR(0) -#define UE_REG_DSP_RX_SCALE_IQ UE_REG_SR_ADDR(1) // {scale_i,scale_q} -#define UE_REG_DSP_RX_DECIM_RATE UE_REG_SR_ADDR(2) // hb and decim rate -#define UE_REG_DSP_RX_DCOFFSET_I UE_REG_SR_ADDR(3) // Bit 31 high sets fixed offset mode, using lower 14 bits, // otherwise it is automatic -#define UE_REG_DSP_RX_DCOFFSET_Q UE_REG_SR_ADDR(4) // Bit 31 high sets fixed offset mode, using lower 14 bits -#define UE_REG_DSP_RX_MUX UE_REG_SR_ADDR(5) - -/////////////////////////////////////////////////// -// VITA RX CTRL regs -/////////////////////////////////////////////////// -// The following 3 are logically a single command register. -// They are clocked into the underlying fifo when time_ticks is written. -#define UE_REG_CTRL_RX_STREAM_CMD UE_REG_SR_ADDR(8) // {now, chain, num_samples(30) -#define UE_REG_CTRL_RX_TIME_SECS UE_REG_SR_ADDR(9) -#define UE_REG_CTRL_RX_TIME_TICKS UE_REG_SR_ADDR(10) -#define UE_REG_CTRL_RX_CLEAR_OVERRUN UE_REG_SR_ADDR(11) // write anything to clear overrun -#define UE_REG_CTRL_RX_VRT_HEADER UE_REG_SR_ADDR(12) // word 0 of packet. FPGA fills in packet counter -#define UE_REG_CTRL_RX_VRT_STREAM_ID UE_REG_SR_ADDR(13) // word 1 of packet. -#define UE_REG_CTRL_RX_VRT_TRAILER UE_REG_SR_ADDR(14) -#define UE_REG_CTRL_RX_NSAMPS_PER_PKT UE_REG_SR_ADDR(15) -#define UE_REG_CTRL_RX_NCHANNELS UE_REG_SR_ADDR(16) // 1 in basic case, up to 4 for vector sources - -///////////////////////////////////////////////// -// DSP TX Regs -//////////////////////////////////////////////// -#define UE_REG_DSP_TX_FREQ UE_REG_SR_ADDR(17) -#define UE_REG_DSP_TX_SCALE_IQ UE_REG_SR_ADDR(18) // {scale_i,scale_q} -#define UE_REG_DSP_TX_INTERP_RATE UE_REG_SR_ADDR(19) -#define UE_REG_DSP_TX_UNUSED UE_REG_SR_ADDR(20) -#define UE_REG_DSP_TX_MUX UE_REG_SR_ADDR(21) - -///////////////////////////////////////////////// -// VITA TX CTRL regs -//////////////////////////////////////////////// -#define UE_REG_CTRL_TX_NCHANNELS UE_REG_SR_ADDR(24) -#define UE_REG_CTRL_TX_CLEAR_UNDERRUN UE_REG_SR_ADDR(25) -#define UE_REG_CTRL_TX_REPORT_SID UE_REG_SR_ADDR(26) -#define UE_REG_CTRL_TX_POLICY UE_REG_SR_ADDR(27) - -#define UE_FLAG_CTRL_TX_POLICY_WAIT (0x1 << 0) -#define UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET (0x1 << 1) -#define UE_FLAG_CTRL_TX_POLICY_NEXT_BURST (0x1 << 2) - -///////////////////////////////////////////////// -// VITA49 64 bit time (write only) -//////////////////////////////////////////////// - /*! - * \brief Time 64 flags - * - *
-   *
-   *    3                   2                   1
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-----------------------------------------------------------+-+-+
-   * |                                                           |S|P|
-   * +-----------------------------------------------------------+-+-+
-   *
-   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
-   * S - Source (0=sma, 1=mimo, 0=default)
-   *
-   * 
- */ -#define UE_REG_TIME64_SECS UE_REG_SR_ADDR(28) // value to set absolute secs to on next PPS -#define UE_REG_TIME64_TICKS UE_REG_SR_ADDR(29) // value to set absolute ticks to on next PPS -#define UE_REG_TIME64_FLAGS UE_REG_SR_ADDR(30) // flags - see chart above -#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0) -#define UE_REG_TIME64_TPS UE_REG_SR_ADDR(31) // clock ticks per second (counter rollover) - -//pps flags (see above) -#define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0) -#define UE_FLAG_TIME64_PPS_POSEDGE (1 << 0) -#define UE_FLAG_TIME64_PPS_SMA (0 << 1) -#define UE_FLAG_TIME64_PPS_MIMO (1 << 1) - -#define UE_FLAG_TIME64_LATCH_NOW 1 -#define UE_FLAG_TIME64_LATCH_NEXT_PPS 0 - -#endif - diff --git a/host/lib/usrp/usrp_e100/CMakeLists.txt b/host/lib/usrp/usrp_e100/CMakeLists.txt new file mode 100644 index 000000000..17ef53152 --- /dev/null +++ b/host/lib/usrp/usrp_e100/CMakeLists.txt @@ -0,0 +1,64 @@ +# +# 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 . +# + +#This file will be included by cmake, use absolute paths! + +######################################################################## +# Conditionally configure the USRP-E100 support +######################################################################## +MESSAGE(STATUS "Configuring USRP-E100 support...") + +INCLUDE(CheckIncludeFileCXX) +CHECK_INCLUDE_FILE_CXX(linux/usrp_e.h HAVE_LINUX_USRP_E_H) + +SET(ENABLE_USRP_E TRUE) + +IF(DEFINED ENABLE_USRP_E100) + IF(ENABLE_USRP_E100) + MESSAGE(STATUS "USRP-E100 support enabled by configure flag") + ELSE(ENABLE_USRP_E100) + MESSAGE(STATUS "USRP-E100 support disabled by configure flag") + ENDIF(ENABLE_USRP_E100) +ELSE(DEFINED ENABLE_USRP_E100) #not defined: automatic enabling of component + SET(ENABLE_USRP_E100 ${HAVE_LINUX_USRP_E_H}) +ENDIF(DEFINED ENABLE_USRP_E100) +SET(ENABLE_USRP_E100 ${ENABLE_USRP_E100} CACHE BOOL "enable USRP-E100 support") + +IF(ENABLE_USRP_E100) + MESSAGE(STATUS " Building USRP-E100 support.") + LIBUHD_APPEND_SOURCES( + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/clock_ctrl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/clock_ctrl.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/codec_ctrl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/codec_ctrl.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/codec_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/dboard_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/dboard_iface.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/dsp_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/fpga-downloader.cc + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/io_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/mboard_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_impl.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_iface.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_iface.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_regs.hpp + ) +ELSE(ENABLE_USRP_E100) + MESSAGE(STATUS " Skipping USRP-E100 support.") +ENDIF(ENABLE_USRP_E100) diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp new file mode 100644 index 000000000..9d4625305 --- /dev/null +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -0,0 +1,237 @@ +// +// 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 . +// + +#include "clock_ctrl.hpp" +#include "ad9522_regs.hpp" +#include +#include +#include "usrp_e_regs.hpp" //spi slave constants +#include +#include +#include +#include + +using namespace uhd; + +template static void set_clock_divider( + size_t divider, div_type &low, div_type &high, bypass_type &bypass +){ + high = divider/2 - 1; + low = divider - high - 2; + bypass = (divider == 1)? 1 : 0; +} + +/*********************************************************************** + * Constants + **********************************************************************/ +static const bool enable_test_clock = false; +static const size_t ref_clock_doubler = 2; //enabled below +static const double ref_clock_rate = 10e6 * ref_clock_doubler; + +static const size_t r_counter = 1; +static const size_t a_counter = 0; +static const size_t b_counter = 20 / ref_clock_doubler; +static const size_t prescaler = 8; //set below with enum, set to 8 when input is under 2400 MHz +static const size_t vco_divider = 5; //set below with enum + +static const size_t n_counter = prescaler * b_counter + a_counter; +static const size_t vco_clock_rate = ref_clock_rate/r_counter * n_counter; //between 1400 and 1800 MHz +static const double master_clock_rate = vco_clock_rate/vco_divider; + +static const size_t fpga_clock_divider = size_t(master_clock_rate/64e6); +static const size_t codec_clock_divider = size_t(master_clock_rate/64e6); + +/*********************************************************************** + * Clock Control Implementation + **********************************************************************/ +class usrp_e_clock_ctrl_impl : public usrp_e_clock_ctrl{ +public: + usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ + _iface = iface; + + //init the clock gen registers + //Note: out0 should already be clocking the FPGA or this isnt going to work + _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; + _ad9522_regs.enable_clock_doubler = 1; //enable ref clock doubler + _ad9522_regs.enb_stat_eeprom_at_stat_pin = 0; //use status pin + _ad9522_regs.status_pin_control = 0x1; //n divider + _ad9522_regs.ld_pin_control = 0x00; //dld + _ad9522_regs.refmon_pin_control = 0x12; //show ref2 + + _ad9522_regs.enable_ref2 = 1; + _ad9522_regs.enable_ref1 = 0; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; + + _ad9522_regs.set_r_counter(r_counter); + _ad9522_regs.a_counter = a_counter; + _ad9522_regs.set_b_counter(b_counter); + _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; + + _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; + _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; + + _ad9522_regs.vco_calibration_now = 1; //calibrate it! + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; + _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; + + //setup fpga master clock + _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; + set_clock_divider(fpga_clock_divider, + _ad9522_regs.divider0_low_cycles, + _ad9522_regs.divider0_high_cycles, + _ad9522_regs.divider0_bypass + ); + + //setup codec clock + _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; + set_clock_divider(codec_clock_divider, + _ad9522_regs.divider1_low_cycles, + _ad9522_regs.divider1_high_cycles, + _ad9522_regs.divider1_bypass + ); + + //setup test clock (same divider as codec clock) + _ad9522_regs.out4_format = ad9522_regs_t::OUT4_FORMAT_CMOS; + _ad9522_regs.out4_cmos_configuration = (enable_test_clock)? + ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : + ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; + + //setup a list of register ranges to write + typedef std::pair range_t; + static const std::vector ranges = boost::assign::list_of + (range_t(0x000, 0x000)) (range_t(0x010, 0x01F)) + (range_t(0x0F0, 0x0FD)) (range_t(0x190, 0x19B)) + (range_t(0x1E0, 0x1E1)) (range_t(0x230, 0x230)) + ; + + //write initial register values and latch/update + BOOST_FOREACH(const range_t &range, ranges){ + for(boost::uint16_t addr = range.first; addr <= range.second; addr++){ + this->send_reg(addr); + } + } + this->latch_regs(); + //test read: + //boost::uint32_t reg = _ad9522_regs.get_read_reg(0x01b); + //boost::uint32_t result = _iface->transact_spi( + // UE_SPI_SS_AD9522, + // spi_config_t::EDGE_RISE, + // reg, 24, true /*no*/ + //); + //std::cout << "result " << std::hex << result << std::endl; + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + } + + ~usrp_e_clock_ctrl_impl(void){ + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + } + + double get_fpga_clock_rate(void){ + return master_clock_rate/fpga_clock_divider; + } + + /*********************************************************************** + * RX Dboard Clock Control (output 9, divider 3) + **********************************************************************/ + void enable_rx_dboard_clock(bool enb){ + _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_CMOS; + _ad9522_regs.out9_cmos_configuration = (enb)? + ad9522_regs_t::OUT9_CMOS_CONFIGURATION_B_ON : + ad9522_regs_t::OUT9_CMOS_CONFIGURATION_OFF; + this->send_reg(0x0F9); + this->latch_regs(); + } + + std::vector get_rx_dboard_clock_rates(void){ + std::vector rates; + for(size_t div = 1; div <= 16+16; div++) + rates.push_back(master_clock_rate/div); + return rates; + } + + void set_rx_dboard_clock_rate(double rate){ + assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); + size_t divider = size_t(master_clock_rate/rate); + //set the divider registers + set_clock_divider(divider, + _ad9522_regs.divider3_low_cycles, + _ad9522_regs.divider3_high_cycles, + _ad9522_regs.divider3_bypass + ); + this->send_reg(0x199); + this->send_reg(0x19a); + this->latch_regs(); + } + + /*********************************************************************** + * TX Dboard Clock Control (output 6, divider 2) + **********************************************************************/ + void enable_tx_dboard_clock(bool enb){ + _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_CMOS; + _ad9522_regs.out6_cmos_configuration = (enb)? + ad9522_regs_t::OUT6_CMOS_CONFIGURATION_B_ON : + ad9522_regs_t::OUT6_CMOS_CONFIGURATION_OFF; + this->send_reg(0x0F6); + this->latch_regs(); + } + + std::vector get_tx_dboard_clock_rates(void){ + return get_rx_dboard_clock_rates(); //same master clock, same dividers... + } + + void set_tx_dboard_clock_rate(double rate){ + assert_has(get_tx_dboard_clock_rates(), rate, "tx dboard clock rate"); + size_t divider = size_t(master_clock_rate/rate); + //set the divider registers + set_clock_divider(divider, + _ad9522_regs.divider2_low_cycles, + _ad9522_regs.divider2_high_cycles, + _ad9522_regs.divider2_bypass + ); + this->send_reg(0x196); + this->send_reg(0x197); + this->latch_regs(); + } + +private: + usrp_e_iface::sptr _iface; + ad9522_regs_t _ad9522_regs; + + void latch_regs(void){ + _ad9522_regs.io_update = 1; + this->send_reg(0x232); + } + + void send_reg(boost::uint16_t addr){ + boost::uint32_t reg = _ad9522_regs.get_write_reg(addr); + //std::cout << "clock control write reg: " << std::hex << reg << std::endl; + _iface->transact_spi( + UE_SPI_SS_AD9522, + spi_config_t::EDGE_RISE, + reg, 24, false /*no rb*/ + ); + } +}; + +/*********************************************************************** + * Clock Control Make + **********************************************************************/ +usrp_e_clock_ctrl::sptr usrp_e_clock_ctrl::make(usrp_e_iface::sptr iface){ + return sptr(new usrp_e_clock_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.hpp b/host/lib/usrp/usrp_e100/clock_ctrl.hpp new file mode 100644 index 000000000..3b5103ed1 --- /dev/null +++ b/host/lib/usrp/usrp_e100/clock_ctrl.hpp @@ -0,0 +1,88 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E_CLOCK_CTRL_HPP +#define INCLUDED_USRP_E_CLOCK_CTRL_HPP + +#include "usrp_e_iface.hpp" +#include +#include +#include + +/*! + * The usrp-e clock control: + * - Setup system clocks. + * - Disable/enable clock lines. + */ +class usrp_e_clock_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new clock control object. + * \param iface the usrp_e iface object + * \return the clock control object + */ + static sptr make(usrp_e_iface::sptr iface); + + /*! + * Get the rate of the fpga clock line. + * \return the fpga clock rate in Hz + */ + virtual double get_fpga_clock_rate(void) = 0; + + /*! + * Get the possible rates of the rx dboard clock. + * \return a vector of clock rates in Hz + */ + virtual std::vector get_rx_dboard_clock_rates(void) = 0; + + /*! + * Get the possible rates of the tx dboard clock. + * \return a vector of clock rates in Hz + */ + virtual std::vector get_tx_dboard_clock_rates(void) = 0; + + /*! + * Set the rx dboard clock rate to a possible rate. + * \param rate the new clock rate in Hz + * \throw exception when rate cannot be achieved + */ + virtual void set_rx_dboard_clock_rate(double rate) = 0; + + /*! + * Set the tx dboard clock rate to a possible rate. + * \param rate the new clock rate in Hz + * \throw exception when rate cannot be achieved + */ + virtual void set_tx_dboard_clock_rate(double rate) = 0; + + /*! + * Enable/disable the rx dboard clock. + * \param enb true to enable + */ + virtual void enable_rx_dboard_clock(bool enb) = 0; + + /*! + * Enable/disable the tx dboard clock. + * \param enb true to enable + */ + virtual void enable_tx_dboard_clock(bool enb) = 0; + +}; + +#endif /* INCLUDED_USRP_E_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e100/codec_ctrl.cpp b/host/lib/usrp/usrp_e100/codec_ctrl.cpp new file mode 100644 index 000000000..a728d7e46 --- /dev/null +++ b/host/lib/usrp/usrp_e100/codec_ctrl.cpp @@ -0,0 +1,296 @@ +// +// 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 . +// + +#include "codec_ctrl.hpp" +#include "ad9862_regs.hpp" +#include +#include +#include +#include +#include +#include +#include "usrp_e_regs.hpp" //spi slave constants +#include +#include + +using namespace uhd; + +static const bool codec_debug = false; + +const gain_range_t usrp_e_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); +const gain_range_t usrp_e_codec_ctrl::rx_pga_gain_range(0, 20, 1); + +/*********************************************************************** + * Codec Control Implementation + **********************************************************************/ +class usrp_e_codec_ctrl_impl : public usrp_e_codec_ctrl{ +public: + //structors + usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface); + ~usrp_e_codec_ctrl_impl(void); + + //aux adc and dac control + float read_aux_adc(aux_adc_t which); + void write_aux_dac(aux_dac_t which, float volts); + + //pga gain control + void set_tx_pga_gain(float); + float get_tx_pga_gain(void); + void set_rx_pga_gain(float, char); + float get_rx_pga_gain(char); + +private: + usrp_e_iface::sptr _iface; + ad9862_regs_t _ad9862_regs; + aux_adc_t _last_aux_adc_a, _last_aux_adc_b; + void send_reg(boost::uint8_t addr); + void recv_reg(boost::uint8_t addr); +}; + +/*********************************************************************** + * Codec Control Structors + **********************************************************************/ +usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ + _iface = iface; + + //soft reset + _ad9862_regs.soft_reset = 1; + this->send_reg(0); + + //initialize the codec register settings + _ad9862_regs.sdio_bidir = ad9862_regs_t::SDIO_BIDIR_SDIO_SDO; + _ad9862_regs.lsb_first = ad9862_regs_t::LSB_FIRST_MSB; + _ad9862_regs.soft_reset = 0; + + //setup rx side of codec + _ad9862_regs.byp_buffer_a = 1; + _ad9862_regs.byp_buffer_b = 1; + _ad9862_regs.buffer_a_pd = 1; + _ad9862_regs.buffer_b_pd = 1; + _ad9862_regs.rx_pga_a = 0;//0x1f; //TODO bring under api control + _ad9862_regs.rx_pga_b = 0;//0x1f; //TODO bring under api control + _ad9862_regs.rx_twos_comp = 1; + _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS; + + //setup tx side of codec + _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH; + _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; + _ad9862_regs.tx_retime = ad9862_regs_t::TX_RETIME_CLKOUT2; + _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control + _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; + _ad9862_regs.interp = ad9862_regs_t::INTERP_2; + _ad9862_regs.tx_twos_comp = 1; + _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_BYPASS; + _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; + _ad9862_regs.dac_a_coarse_gain = 0x3; + _ad9862_regs.dac_b_coarse_gain = 0x3; + _ad9862_regs.edges = ad9862_regs_t::EDGES_NORMAL; + + //setup the dll + _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL; + _ad9862_regs.dll_mult = ad9862_regs_t::DLL_MULT_2; + _ad9862_regs.dll_mode = ad9862_regs_t::DLL_MODE_FAST; + + //write the register settings to the codec + for (uint8_t addr = 0; addr <= 25; addr++){ + this->send_reg(addr); + } + + //aux adc clock + _ad9862_regs.clk_4 = ad9862_regs_t::CLK_4_1_4; + this->send_reg(34); +} + +usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ + //set aux dacs to zero + this->write_aux_dac(AUX_DAC_A, 0); + this->write_aux_dac(AUX_DAC_B, 0); + this->write_aux_dac(AUX_DAC_C, 0); + this->write_aux_dac(AUX_DAC_D, 0); + + //power down + _ad9862_regs.all_rx_pd = 1; + this->send_reg(1); + _ad9862_regs.tx_digital_pd = 1; + _ad9862_regs.tx_analog_pd = ad9862_regs_t::TX_ANALOG_PD_BOTH; + this->send_reg(8); +} + +/*********************************************************************** + * Codec Control Gain Control Methods + **********************************************************************/ +static const int mtpgw = 255; //maximum tx pga gain word + +void usrp_e_codec_ctrl_impl::set_tx_pga_gain(float gain){ + int gain_word = int(mtpgw*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); + _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw); + this->send_reg(16); +} + +float usrp_e_codec_ctrl_impl::get_tx_pga_gain(void){ + return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/mtpgw) + tx_pga_gain_range.min; +} + +static const int mrpgw = 0x14; //maximum rx pga gain word + +void usrp_e_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){ + int gain_word = int(mrpgw*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min)); + gain_word = std::clip(gain_word, 0, mrpgw); + switch(which){ + case 'A': + _ad9862_regs.rx_pga_a = gain_word; + this->send_reg(2); + return; + case 'B': + _ad9862_regs.rx_pga_b = gain_word; + this->send_reg(3); + return; + default: UHD_THROW_INVALID_CODE_PATH(); + } +} + +float usrp_e_codec_ctrl_impl::get_rx_pga_gain(char which){ + int gain_word; + switch(which){ + case 'A': gain_word = _ad9862_regs.rx_pga_a; break; + case 'B': gain_word = _ad9862_regs.rx_pga_b; break; + default: UHD_THROW_INVALID_CODE_PATH(); + } + return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/mrpgw) + rx_pga_gain_range.min; +} + +/*********************************************************************** + * Codec Control AUX ADC Methods + **********************************************************************/ +static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){ + return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; +} + +float usrp_e_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ + //check to see if the switch needs to be set + bool write_switch = false; + switch(which){ + + case AUX_ADC_A1: + case AUX_ADC_A2: + if (which != _last_aux_adc_a){ + _ad9862_regs.select_a = (which == AUX_ADC_A1)? + ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2; + _last_aux_adc_a = which; + write_switch = true; + } + break; + + case AUX_ADC_B1: + case AUX_ADC_B2: + if (which != _last_aux_adc_b){ + _ad9862_regs.select_b = (which == AUX_ADC_B1)? + ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2; + _last_aux_adc_b = which; + write_switch = true; + } + break; + + } + + //write the switch if it changed + if(write_switch) this->send_reg(34); + + //map aux adcs to register values to read + static const uhd::dict aux_dac_to_addr = boost::assign::map_list_of + (AUX_ADC_A2, 26) (AUX_ADC_A1, 28) + (AUX_ADC_B2, 30) (AUX_ADC_B1, 32) + ; + + //read the value + this->recv_reg(aux_dac_to_addr[which]+0); + this->recv_reg(aux_dac_to_addr[which]+1); + + //return the value scaled to volts + switch(which){ + case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0); + case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0); + case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0); + case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0); + } + UHD_ASSERT_THROW(false); +} + +/*********************************************************************** + * Codec Control AUX DAC Methods + **********************************************************************/ +void usrp_e_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ + //special case for aux dac d (aka sigma delta word) + if (which == AUX_DAC_D){ + boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff); + _ad9862_regs.sig_delt_11_4 = boost::uint8_t(dac_word >> 4); + _ad9862_regs.sig_delt_3_0 = boost::uint8_t(dac_word & 0xf); + this->send_reg(42); + this->send_reg(43); + return; + } + + //calculate the dac word for aux dac a, b, c + boost::uint8_t dac_word = std::clip(boost::math::iround(volts*0xff/3.3), 0, 0xff); + + //setup a lookup table for the aux dac params (reg ref, reg addr) + typedef boost::tuple dac_params_t; + uhd::dict aux_dac_to_params = boost::assign::map_list_of + (AUX_DAC_A, dac_params_t(&_ad9862_regs.aux_dac_a, 36)) + (AUX_DAC_B, dac_params_t(&_ad9862_regs.aux_dac_b, 37)) + (AUX_DAC_C, dac_params_t(&_ad9862_regs.aux_dac_c, 38)) + ; + + //set the aux dac register + UHD_ASSERT_THROW(aux_dac_to_params.has_key(which)); + boost::uint8_t *reg_ref, reg_addr; + boost::tie(reg_ref, reg_addr) = aux_dac_to_params[which]; + *reg_ref = dac_word; + this->send_reg(reg_addr); +} + +/*********************************************************************** + * Codec Control SPI Methods + **********************************************************************/ +void usrp_e_codec_ctrl_impl::send_reg(boost::uint8_t addr){ + boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); + if (codec_debug) std::cout << "codec control write reg: " << std::hex << reg << std::endl; + _iface->transact_spi( + UE_SPI_SS_AD9862, + spi_config_t::EDGE_RISE, + reg, 16, false /*no rb*/ + ); +} + +void usrp_e_codec_ctrl_impl::recv_reg(boost::uint8_t addr){ + boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); + if (codec_debug) std::cout << "codec control read reg: " << std::hex << reg << std::endl; + boost::uint32_t ret = _iface->transact_spi( + UE_SPI_SS_AD9862, + spi_config_t::EDGE_RISE, + reg, 16, true /*rb*/ + ); + if (codec_debug) std::cout << "codec control read ret: " << std::hex << ret << std::endl; + _ad9862_regs.set_reg(addr, boost::uint16_t(ret)); +} + +/*********************************************************************** + * Codec Control Make + **********************************************************************/ +usrp_e_codec_ctrl::sptr usrp_e_codec_ctrl::make(usrp_e_iface::sptr iface){ + return sptr(new usrp_e_codec_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/usrp_e100/codec_ctrl.hpp b/host/lib/usrp/usrp_e100/codec_ctrl.hpp new file mode 100644 index 000000000..87b6ff951 --- /dev/null +++ b/host/lib/usrp/usrp_e100/codec_ctrl.hpp @@ -0,0 +1,90 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E_CODEC_CTRL_HPP +#define INCLUDED_USRP_E_CODEC_CTRL_HPP + +#include "usrp_e_iface.hpp" +#include +#include +#include + +/*! + * The usrp-e codec control: + * - Init/power down codec. + * - Read aux adc, write aux dac. + */ +class usrp_e_codec_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + static const uhd::gain_range_t tx_pga_gain_range; + static const uhd::gain_range_t rx_pga_gain_range; + + /*! + * Make a new codec control object. + * \param iface the usrp_e iface object + * \return the codec control object + */ + static sptr make(usrp_e_iface::sptr iface); + + //! aux adc identifier constants + enum aux_adc_t{ + AUX_ADC_A2 = 0xA2, + AUX_ADC_A1 = 0xA1, + AUX_ADC_B2 = 0xB2, + AUX_ADC_B1 = 0xB1 + }; + + /*! + * Read an auxiliary adc: + * The internals remember which aux adc was read last. + * Therefore, the aux adc switch is only changed as needed. + * \param which which of the 4 adcs + * \return a value in volts + */ + virtual float read_aux_adc(aux_adc_t which) = 0; + + //! aux dac identifier constants + enum aux_dac_t{ + AUX_DAC_A = 0xA, + AUX_DAC_B = 0xB, + AUX_DAC_C = 0xC, + AUX_DAC_D = 0xD //really the sigma delta output + }; + + /*! + * Write an auxiliary dac. + * \param which which of the 4 dacs + * \param volts the level in in volts + */ + virtual void write_aux_dac(aux_dac_t which, float volts) = 0; + + //! Set the TX PGA gain + virtual void set_tx_pga_gain(float gain) = 0; + + //! Get the TX PGA gain + virtual float get_tx_pga_gain(void) = 0; + + //! Set the RX PGA gain ('A' or 'B') + virtual void set_rx_pga_gain(float gain, char which) = 0; + + //! Get the RX PGA gain ('A' or 'B') + virtual float get_rx_pga_gain(char which) = 0; +}; + +#endif /* INCLUDED_USRP_E_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e100/codec_impl.cpp b/host/lib/usrp/usrp_e100/codec_impl.cpp new file mode 100644 index 000000000..696fb37ec --- /dev/null +++ b/host/lib/usrp/usrp_e100/codec_impl.cpp @@ -0,0 +1,149 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Helper Methods + **********************************************************************/ +void usrp_e_impl::codec_init(void){ + //make proxies + _rx_codec_proxy = wax_obj_proxy::make( + boost::bind(&usrp_e_impl::rx_codec_get, this, _1, _2), + boost::bind(&usrp_e_impl::rx_codec_set, this, _1, _2) + ); + _tx_codec_proxy = wax_obj_proxy::make( + boost::bind(&usrp_e_impl::tx_codec_get, this, _1, _2), + boost::bind(&usrp_e_impl::tx_codec_set, this, _1, _2) + ); +} + +/*********************************************************************** + * RX Codec Properties + **********************************************************************/ +static const std::string ad9862_pga_gain_name = "ad9862 pga"; + +void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case CODEC_PROP_NAME: + val = std::string("usrp-e adc - ad9522"); + return; + + case CODEC_PROP_OTHERS: + val = prop_names_t(); + return; + + case CODEC_PROP_GAIN_NAMES: + val = prop_names_t(1, ad9862_pga_gain_name); + return; + + case CODEC_PROP_GAIN_RANGE: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + val = usrp_e_codec_ctrl::rx_pga_gain_range; + return; + + case CODEC_PROP_GAIN_I: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + val = _codec_ctrl->get_rx_pga_gain('A'); + return; + + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + val = _codec_ctrl->get_rx_pga_gain('B'); + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void usrp_e_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the set request conditioned on the key + switch(key.as()){ + case CODEC_PROP_GAIN_I: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + _codec_ctrl->set_rx_pga_gain(val.as(), 'A'); + return; + + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + _codec_ctrl->set_rx_pga_gain(val.as(), 'B'); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + +/*********************************************************************** + * TX Codec Properties + **********************************************************************/ +void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case CODEC_PROP_NAME: + val = std::string("usrp-e dac - ad9522"); + return; + + case CODEC_PROP_OTHERS: + val = prop_names_t(); + return; + + case CODEC_PROP_GAIN_NAMES: + val = prop_names_t(1, ad9862_pga_gain_name); + return; + + case CODEC_PROP_GAIN_RANGE: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + val = usrp_e_codec_ctrl::tx_pga_gain_range; + return; + + case CODEC_PROP_GAIN_I: //only one gain for I and Q + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + val = _codec_ctrl->get_tx_pga_gain(); + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void usrp_e_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the set request conditioned on the key + switch(key.as()){ + case CODEC_PROP_GAIN_I: //only one gain for I and Q + case CODEC_PROP_GAIN_Q: + UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + _codec_ctrl->set_tx_pga_gain(val.as()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} diff --git a/host/lib/usrp/usrp_e100/dboard_iface.cpp b/host/lib/usrp/usrp_e100/dboard_iface.cpp new file mode 100644 index 000000000..6898df8df --- /dev/null +++ b/host/lib/usrp/usrp_e100/dboard_iface.cpp @@ -0,0 +1,298 @@ +// +// 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 . +// + +#include "usrp_e_iface.hpp" +#include "usrp_e_regs.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" +#include +#include +#include +#include +#include //i2c and spi constants + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +class usrp_e_dboard_iface : public dboard_iface{ +public: + + usrp_e_dboard_iface( + usrp_e_iface::sptr iface, + usrp_e_clock_ctrl::sptr clock, + usrp_e_codec_ctrl::sptr codec + ){ + _iface = iface; + _clock = clock; + _codec = codec; + + //init the clock rate shadows + this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); + this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); + + _iface->poke16(UE_REG_GPIO_RX_DBG, 0); + _iface->poke16(UE_REG_GPIO_TX_DBG, 0); + } + + ~usrp_e_dboard_iface(void){ + /* NOP */ + } + + special_props_t get_special_props(void){ + special_props_t props; + props.soft_clock_divider = false; + props.mangle_i2c_addrs = false; + return props; + } + + void write_aux_dac(unit_t, aux_dac_t, float); + float read_aux_adc(unit_t, aux_adc_t); + + void set_pin_ctrl(unit_t, boost::uint16_t); + void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); + void set_gpio_ddr(unit_t, boost::uint16_t); + void write_gpio(unit_t, boost::uint16_t); + void set_gpio_debug(unit_t, int); + boost::uint16_t read_gpio(unit_t); + + void write_i2c(boost::uint8_t, const byte_vector_t &); + byte_vector_t read_i2c(boost::uint8_t, size_t); + + void write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + + boost::uint32_t read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + + void set_clock_rate(unit_t, double); + std::vector get_clock_rates(unit_t); + double get_clock_rate(unit_t); + void set_clock_enabled(unit_t, bool); + double get_codec_rate(unit_t); + +private: + usrp_e_iface::sptr _iface; + usrp_e_clock_ctrl::sptr _clock; + usrp_e_codec_ctrl::sptr _codec; + uhd::dict _clock_rates; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +dboard_iface::sptr make_usrp_e_dboard_iface( + usrp_e_iface::sptr iface, + usrp_e_clock_ctrl::sptr clock, + usrp_e_codec_ctrl::sptr codec +){ + return dboard_iface::sptr(new usrp_e_dboard_iface(iface, clock, codec)); +} + +/*********************************************************************** + * Clock Rates + **********************************************************************/ +void usrp_e_dboard_iface::set_clock_rate(unit_t unit, double rate){ + _clock_rates[unit] = rate; + switch(unit){ + case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate); + case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate); + } +} + +std::vector usrp_e_dboard_iface::get_clock_rates(unit_t unit){ + switch(unit){ + case UNIT_RX: return _clock->get_rx_dboard_clock_rates(); + case UNIT_TX: return _clock->get_tx_dboard_clock_rates(); + default: UHD_THROW_INVALID_CODE_PATH(); + } +} + +double usrp_e_dboard_iface::get_clock_rate(unit_t unit){ + return _clock_rates[unit]; +} + +void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ + switch(unit){ + case UNIT_RX: return _clock->enable_rx_dboard_clock(enb); + case UNIT_TX: return _clock->enable_tx_dboard_clock(enb); + } +} + +double usrp_e_dboard_iface::get_codec_rate(unit_t){ + return _clock->get_fpga_clock_rate(); +} + +/*********************************************************************** + * GPIO + **********************************************************************/ +void usrp_e_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){ + UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption + switch(unit){ + case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_SEL, value); return; + case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_SEL, value); return; + } +} + +void usrp_e_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ + switch(unit){ + case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_DDR, value); return; + case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_DDR, value); return; + } +} + +void usrp_e_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){ + switch(unit){ + case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_IO, value); return; + case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_IO, value); return; + } +} + +boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t unit){ + switch(unit){ + case UNIT_RX: return _iface->peek16(UE_REG_GPIO_RX_IO); + case UNIT_TX: return _iface->peek16(UE_REG_GPIO_TX_IO); + default: UHD_THROW_INVALID_CODE_PATH(); + } +} + +void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ + //define mapping of unit to atr regs to register address + static const uhd::dict< + unit_t, uhd::dict + > unit_to_atr_to_addr = map_list_of + (UNIT_RX, 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) + ) + (UNIT_TX, 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) + ) + ; + _iface->poke16(unit_to_atr_to_addr[unit][atr], value); +} + +void usrp_e_dboard_iface::set_gpio_debug(unit_t unit, int which){ + //set this unit to all outputs + this->set_gpio_ddr(unit, 0xffff); + + //calculate the debug selections + boost::uint32_t dbg_sels = 0x0; + int sel = (which == 0)? GPIO_SEL_DEBUG_0 : GPIO_SEL_DEBUG_1; + for(size_t i = 0; i < 16; i++) dbg_sels |= sel << i; + + //set the debug on and which debug selection + switch(unit){ + case UNIT_RX: + _iface->poke16(UE_REG_GPIO_RX_DBG, 0xffff); + _iface->poke16(UE_REG_GPIO_RX_SEL, dbg_sels); + return; + + case UNIT_TX: + _iface->poke16(UE_REG_GPIO_TX_DBG, 0xffff); + _iface->poke16(UE_REG_GPIO_TX_SEL, dbg_sels); + return; + } +} + +/*********************************************************************** + * SPI + **********************************************************************/ +/*! + * Static function to convert a unit type to a spi slave device number. + * \param unit the dboard interface unit type enum + * \return the slave device number + */ +static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit){ + switch(unit){ + case dboard_iface::UNIT_TX: return UE_SPI_SS_TX_DB; + case dboard_iface::UNIT_RX: return UE_SPI_SS_RX_DB; + } + throw std::invalid_argument("unknown unit type"); +} + +void usrp_e_dboard_iface::write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); +} + +boost::uint32_t usrp_e_dboard_iface::read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); +} + +/*********************************************************************** + * I2C + **********************************************************************/ +void usrp_e_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ + return _iface->write_i2c(addr, bytes); +} + +byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ + return _iface->read_i2c(addr, num_bytes); +} + +/*********************************************************************** + * Aux DAX/ADC + **********************************************************************/ +void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which, float value){ + //same aux dacs for each unit + static const uhd::dict which_to_aux_dac = map_list_of + (AUX_DAC_A, usrp_e_codec_ctrl::AUX_DAC_A) + (AUX_DAC_B, usrp_e_codec_ctrl::AUX_DAC_B) + (AUX_DAC_C, usrp_e_codec_ctrl::AUX_DAC_C) + (AUX_DAC_D, usrp_e_codec_ctrl::AUX_DAC_D) + ; + _codec->write_aux_dac(which_to_aux_dac[which], value); +} + +float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, aux_adc_t which){ + static const uhd::dict< + unit_t, uhd::dict + > unit_to_which_to_aux_adc = map_list_of + (UNIT_RX, map_list_of + (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A1) + (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B1) + ) + (UNIT_TX, map_list_of + (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A2) + (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B2) + ) + ; + return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]); +} diff --git a/host/lib/usrp/usrp_e100/dboard_impl.cpp b/host/lib/usrp/usrp_e100/dboard_impl.cpp new file mode 100644 index 000000000..f2840dcfc --- /dev/null +++ b/host/lib/usrp/usrp_e100/dboard_impl.cpp @@ -0,0 +1,172 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Dboard Initialization + **********************************************************************/ +void usrp_e_impl::dboard_init(void){ + _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); + _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); + + //create a new dboard interface and manager + _dboard_iface = make_usrp_e_dboard_iface( + _iface, _clock_ctrl, _codec_ctrl + ); + _dboard_manager = dboard_manager::make( + _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface + ); + + //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 &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case DBOARD_PROP_NAME: + val = std::string("usrp-e dboard (rx unit)"); + return; + + case DBOARD_PROP_SUBDEV: + val = _dboard_manager->get_rx_subdev(key.name); + return; + + case DBOARD_PROP_SUBDEV_NAMES: + val = _dboard_manager->get_rx_subdev_names(); + return; + + case DBOARD_PROP_DBOARD_ID: + val = _rx_db_eeprom.id; + return; + + case DBOARD_PROP_DBOARD_IFACE: + val = _dboard_iface; + return; + + case DBOARD_PROP_CODEC: + val = _rx_codec_proxy->get_link(); + return; + + case DBOARD_PROP_GAIN_GROUP: + val = make_gain_group( + _rx_db_eeprom.id, + _dboard_manager->get_rx_subdev(key.name), + _rx_codec_proxy->get_link(), + GAIN_GROUP_POLICY_RX + ); + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +/*********************************************************************** + * RX Dboard Set + **********************************************************************/ +void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + case DBOARD_PROP_DBOARD_ID: + _rx_db_eeprom.id = val.as(); + _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + +/*********************************************************************** + * TX Dboard Get + **********************************************************************/ +void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case DBOARD_PROP_NAME: + val = std::string("usrp-e dboard (tx unit)"); + return; + + case DBOARD_PROP_SUBDEV: + val = _dboard_manager->get_tx_subdev(key.name); + return; + + case DBOARD_PROP_SUBDEV_NAMES: + val = _dboard_manager->get_tx_subdev_names(); + return; + + case DBOARD_PROP_DBOARD_ID: + val = _tx_db_eeprom.id; + return; + + case DBOARD_PROP_DBOARD_IFACE: + val = _dboard_iface; + return; + + case DBOARD_PROP_CODEC: + val = _tx_codec_proxy->get_link(); + return; + + case DBOARD_PROP_GAIN_GROUP: + val = make_gain_group( + _tx_db_eeprom.id, + _dboard_manager->get_tx_subdev(key.name), + _tx_codec_proxy->get_link(), + GAIN_GROUP_POLICY_TX + ); + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +/*********************************************************************** + * TX Dboard Set + **********************************************************************/ +void usrp_e_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + case DBOARD_PROP_DBOARD_ID: + _tx_db_eeprom.id = val.as(); + _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} diff --git a/host/lib/usrp/usrp_e100/dsp_impl.cpp b/host/lib/usrp/usrp_e100/dsp_impl.cpp new file mode 100644 index 000000000..97f173c1a --- /dev/null +++ b/host/lib/usrp/usrp_e100/dsp_impl.cpp @@ -0,0 +1,192 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include +#include +#include +#include + +#define rint boost::math::iround + +using namespace uhd; +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) + ); + + //initial config and update + rx_ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); + rx_ddc_set(DSP_PROP_HOST_RATE, double(64e6/10)); +} + +/*********************************************************************** + * RX DDC Get + **********************************************************************/ +void usrp_e_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + switch(key.as()){ + case DSP_PROP_NAME: + val = std::string("usrp-e ddc0"); + return; + + case DSP_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case DSP_PROP_FREQ_SHIFT: + val = _ddc_freq; + return; + + case DSP_PROP_FREQ_SHIFT_NAMES: + val = prop_names_t(1, ""); + return; + + case DSP_PROP_CODEC_RATE: + val = _clock_ctrl->get_fpga_clock_rate(); + return; + + case DSP_PROP_HOST_RATE: + val = _clock_ctrl->get_fpga_clock_rate()/_ddc_decim; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +/*********************************************************************** + * RX DDC Set + **********************************************************************/ +void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + switch(key.as()){ + + case DSP_PROP_FREQ_SHIFT:{ + double new_freq = val.as(); + _iface->poke32(UE_REG_DSP_RX_FREQ, + dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) + ); + _ddc_freq = new_freq; //shadow + } + return; + + case DSP_PROP_HOST_RATE:{ + //set the decimation + _ddc_decim = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); + _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); + + //set the scaling + static const boost::int16_t default_rx_scale_iq = 1024; + _iface->poke32(UE_REG_DSP_RX_SCALE_IQ, + dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) + ); + } + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + +/*********************************************************************** + * 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) + ); + + //initial config and update + tx_duc_set(DSP_PROP_FREQ_SHIFT, double(0)); + tx_duc_set(DSP_PROP_HOST_RATE, double(64e6/10)); +} + +/*********************************************************************** + * TX DUC Get + **********************************************************************/ +void usrp_e_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + switch(key.as()){ + case DSP_PROP_NAME: + val = std::string("usrp-e duc0"); + return; + + case DSP_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case DSP_PROP_FREQ_SHIFT: + val = _duc_freq; + return; + + case DSP_PROP_FREQ_SHIFT_NAMES: + val = prop_names_t(1, ""); + return; + + case DSP_PROP_CODEC_RATE: + val = _clock_ctrl->get_fpga_clock_rate(); + return; + + case DSP_PROP_HOST_RATE: + val = _clock_ctrl->get_fpga_clock_rate()/_duc_interp; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +/*********************************************************************** + * TX DUC Set + **********************************************************************/ +void usrp_e_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + switch(key.as()){ + + case DSP_PROP_FREQ_SHIFT:{ + double new_freq = val.as(); + _iface->poke32(UE_REG_DSP_TX_FREQ, + dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) + ); + _duc_freq = new_freq; //shadow + } + return; + + case DSP_PROP_HOST_RATE:{ + _duc_interp = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); + + //set the interpolation + _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp)); + + //set the scaling + _iface->poke32(UE_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_duc_interp)); + } + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} diff --git a/host/lib/usrp/usrp_e100/fpga-downloader.cc b/host/lib/usrp/usrp_e100/fpga-downloader.cc new file mode 100644 index 000000000..4dc537919 --- /dev/null +++ b/host/lib/usrp/usrp_e100/fpga-downloader.cc @@ -0,0 +1,274 @@ +// +// 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 . +// + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * 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 (not export_file.is_open()) throw std::runtime_error( + "Failed to open gpio export file." + ); + + 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; + + if (gpio_num != 114) { + 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); +} +*/ + +void 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 << "Loading FPGA image: " << bin_file << "... " << std::flush; + + UHD_ASSERT_THROW(std::system("/sbin/rmmod usrp_e") == 0); + + 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); + + UHD_ASSERT_THROW(std::system("/sbin/modprobe usrp_e") == 0); + +} + diff --git a/host/lib/usrp/usrp_e100/io_impl.cpp b/host/lib/usrp/usrp_e100/io_impl.cpp new file mode 100644 index 000000000..e863944e8 --- /dev/null +++ b/host/lib/usrp/usrp_e100/io_impl.cpp @@ -0,0 +1,272 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include +#include +#include +#include "../../transport/vrt_packet_handler.hpp" +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace uhd::transport; + +zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); + +/*********************************************************************** + * Constants + **********************************************************************/ +static const size_t tx_async_report_sid = 1; +static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; +static const bool recv_debug = false; + +/*********************************************************************** + * io impl details (internal to this file) + * - pirate crew of 1 + * - bounded buffer + * - thread loop + * - vrt packet handler states + **********************************************************************/ +struct usrp_e_impl::io_impl{ + //state management for the vrt packet handler code + vrt_packet_handler::recv_state packet_handler_recv_state; + vrt_packet_handler::send_state packet_handler_send_state; + zero_copy_if::sptr data_xport; + bool continuous_streaming; + io_impl(usrp_e_iface::sptr iface): + data_xport(usrp_e_make_mmap_zero_copy(iface)), + recv_pirate_booty(recv_booty_type::make(data_xport->get_num_recv_frames())), + async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) + { + /* NOP */ + } + + ~io_impl(void){ + recv_pirate_crew_raiding = false; + recv_pirate_crew.interrupt_all(); + recv_pirate_crew.join_all(); + } + + bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){ + UHD_ASSERT_THROW(buffs.size() == 1); + boost::this_thread::disable_interruption di; //disable because the wait can throw + return recv_pirate_booty->pop_with_timed_wait(buffs.front(), timeout); + } + + //a pirate's life is the life for me! + void recv_pirate_loop(usrp_e_clock_ctrl::sptr); + typedef bounded_buffer recv_booty_type; + recv_booty_type::sptr recv_pirate_booty; + bounded_buffer::sptr async_msg_fifo; + boost::thread_group recv_pirate_crew; + bool recv_pirate_crew_raiding; +}; + +/*********************************************************************** + * Receive Pirate Loop + * - while raiding, loot for recv buffers + * - put booty into the alignment buffer + **********************************************************************/ +void usrp_e_impl::io_impl::recv_pirate_loop(usrp_e_clock_ctrl::sptr clock_ctrl) +{ + set_thread_priority_safe(); + recv_pirate_crew_raiding = true; + + while(recv_pirate_crew_raiding){ + managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(); + if (not buff.get()) continue; //ignore timeout/error buffers + + if (recv_debug){ + std::cout << "len " << buff->size() << std::endl; + for (size_t i = 0; i < 9; i++){ + std::cout << boost::format(" 0x%08x") % buff->cast()[i] << std::endl; + } + std::cout << std::endl << std::endl; + } + + try{ + //extract the vrt header packet info + vrt::if_packet_info_t if_packet_info; + if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); + const boost::uint32_t *vrt_hdr = buff->cast(); + vrt::if_hdr_unpack_le(vrt_hdr, if_packet_info); + + //handle a tx async report message + if (if_packet_info.sid == tx_async_report_sid and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ + + //fill in the async metadata + async_metadata_t metadata; + metadata.channel = 0; + metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; + metadata.time_spec = time_spec_t( + time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), clock_ctrl->get_fpga_clock_rate() + ); + metadata.event_code = vrt_packet_handler::get_context_code(vrt_hdr, if_packet_info); + + //print the famous U, and push the metadata into the message queue + if (metadata.event_code & underflow_flags) std::cerr << "U" << std::flush; + async_msg_fifo->push_with_pop_on_full(metadata); + continue; + } + + //same number of frames as the data transport -> always immediate + recv_pirate_booty->push_with_wait(buff); + + }catch(const std::exception &e){ + std::cerr << "Error (usrp-e recv pirate loop): " << e.what() << std::endl; + } + } +} + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +void usrp_e_impl::io_init(void){ + //setup otw types + _send_otw_type.width = 16; + _send_otw_type.shift = 0; + _send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + + _recv_otw_type.width = 16; + _recv_otw_type.shift = 0; + _recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + + //setup before the registers (transport called to calculate max spp) + _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface)); + + //setup rx data path + _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); + _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); + _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 1); //reset + _iface->poke32(UE_REG_CTRL_RX_VRT_HEADER, 0 + | (0x1 << 28) //if data with stream id + | (0x1 << 26) //has trailer + | (0x3 << 22) //integer time other + | (0x1 << 20) //fractional time sample count + ); + _iface->poke32(UE_REG_CTRL_RX_VRT_STREAM_ID, 0); + _iface->poke32(UE_REG_CTRL_RX_VRT_TRAILER, 0); + + //setup the tx policy + _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, tx_async_report_sid); + _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); + + //spawn a pirate, yarrr! + _io_impl->recv_pirate_crew.create_thread(boost::bind( + &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl + )); +} + +void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ + _io_impl->continuous_streaming = (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, dsp_type1::calc_stream_cmd_word( + stream_cmd, get_max_recv_samps_per_packet() + )); + _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); + _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); +} + +void usrp_e_impl::handle_overrun(size_t){ + std::cerr << "O"; //the famous OOOOOOOOOOO + _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 0); + if (_io_impl->continuous_streaming){ + this->issue_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + } +} + +/*********************************************************************** + * Data Send + **********************************************************************/ +bool get_send_buffs( + zero_copy_if::sptr trans, double timeout, + vrt_packet_handler::managed_send_buffs_t &buffs +){ + UHD_ASSERT_THROW(buffs.size() == 1); + buffs[0] = trans->get_send_buff(timeout); + return buffs[0].get() != NULL; +} + +size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + size_t bpp = _io_impl->data_xport->get_send_frame_size() - hdr_size; + return bpp/_send_otw_type.get_sample_size(); +} + +size_t usrp_e_impl::send( + const std::vector &buffs, size_t num_samps, + const tx_metadata_t &metadata, const io_type_t &io_type, + send_mode_t send_mode, double timeout +){ + return vrt_packet_handler::send( + _io_impl->packet_handler_send_state, //last state of the send handler + buffs, num_samps, //buffer to fill + metadata, send_mode, //samples metadata + io_type, _send_otw_type, //input and output types to convert + _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate + uhd::transport::vrt::if_hdr_pack_le, + boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), + get_max_send_samps_per_packet() + ); +} + +/*********************************************************************** + * Data Recv + **********************************************************************/ +size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + size_t bpp = _io_impl->data_xport->get_recv_frame_size() - hdr_size; + return bpp/_recv_otw_type.get_sample_size(); +} + +size_t usrp_e_impl::recv( + const std::vector &buffs, size_t num_samps, + rx_metadata_t &metadata, const io_type_t &io_type, + recv_mode_t recv_mode, double timeout +){ + return vrt_packet_handler::recv( + _io_impl->packet_handler_recv_state, //last state of the recv handler + buffs, num_samps, //buffer to fill + metadata, recv_mode, //samples metadata + io_type, _recv_otw_type, //input and output types to convert + _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate + uhd::transport::vrt::if_hdr_unpack_le, + boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), + boost::bind(&usrp_e_impl::handle_overrun, this, _1) + ); +} + +/*********************************************************************** + * Async Recv + **********************************************************************/ +bool usrp_e_impl::recv_async_msg( + async_metadata_t &async_metadata, double timeout +){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + return _io_impl->async_msg_fifo->pop_with_timed_wait(async_metadata, timeout); +} diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp new file mode 100644 index 000000000..f0118aa4b --- /dev/null +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -0,0 +1,159 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include +#include +#include +#include +#include +#include + +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){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + 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: + UHD_ASSERT_THROW(key.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: + UHD_ASSERT_THROW(key.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_RX_DSP: + UHD_ASSERT_THROW(key.name == ""); + val = _rx_ddc_proxy->get_link(); + return; + + case MBOARD_PROP_RX_DSP_NAMES: + val = prop_names_t(1, ""); + return; + + case MBOARD_PROP_TX_DSP: + UHD_ASSERT_THROW(key.name == ""); + val = _tx_duc_proxy->get_link(); + return; + + case MBOARD_PROP_TX_DSP_NAMES: + val = prop_names_t(1, ""); + return; + + case MBOARD_PROP_CLOCK_CONFIG: + val = _clock_config; + return; + + case MBOARD_PROP_RX_SUBDEV_SPEC: + val = _rx_subdev_spec; + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + val = _tx_subdev_spec; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +/*********************************************************************** + * Mboard Set + **********************************************************************/ +void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ + //handle the get request conditioned on the key + switch(key.as()){ + + case MBOARD_PROP_STREAM_CMD: + issue_stream_cmd(val.as()); + return; + + case MBOARD_PROP_TIME_NOW: + case MBOARD_PROP_TIME_NEXT_PPS:{ + time_spec_t time_spec = val.as(); + _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); + boost::uint32_t imm_flags = (key.as() == MBOARD_PROP_TIME_NOW)? 1 : 0; + _iface->poke32(UE_REG_TIME64_IMM, imm_flags); + _iface->poke32(UE_REG_TIME64_SECS, time_spec.get_full_secs()); + } + return; + + case MBOARD_PROP_RX_SUBDEV_SPEC: + _rx_subdev_spec = val.as(); + verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link()); + //sanity check + UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); + //set the mux + _iface->poke32(UE_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( + _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as() + )); + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + _tx_subdev_spec = val.as(); + verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link()); + //sanity check + UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); + //set the mux + _iface->poke32(UE_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( + _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as() + )); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} diff --git a/host/lib/usrp/usrp_e100/usrp_e_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e_iface.cpp new file mode 100644 index 000000000..f00e92946 --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e_iface.cpp @@ -0,0 +1,194 @@ +// +// 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 . +// + +#include "usrp_e_iface.hpp" +#include +#include //ioctl +#include //open, close +#include //ioctl structures and constants +#include +#include //mutex +#include + +using namespace uhd; + +class usrp_e_iface_impl : public usrp_e_iface{ +public: + + int get_file_descriptor(void){ + return _node_fd; + } + + /******************************************************************* + * Structors + ******************************************************************/ + usrp_e_iface_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 + )); + } + } + + ~usrp_e_iface_impl(void){ + //close the device node file descriptor + ::close(_node_fd); + } + + /******************************************************************* + * IOCTL: provides the communication base for all other calls + ******************************************************************/ + void ioctl(int request, void *mem){ + boost::mutex::scoped_lock lock(_ctrl_mutex); + + if (::ioctl(_node_fd, request, mem) < 0){ + throw std::runtime_error(str( + boost::format("ioctl failed with request %d") % request + )); + } + } + + /******************************************************************* + * Peek and Poke + ******************************************************************/ + void 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 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 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 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]; + } + + /******************************************************************* + * I2C + ******************************************************************/ + static const size_t max_i2c_data_bytes = 10; + + void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ + //allocate some memory for this transaction + UHD_ASSERT_THROW(bytes.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(mem); + data->addr = addr; + data->len = bytes.size(); + std::copy(bytes.begin(), bytes.end(), data->data); + + //call the spi ioctl + this->ioctl(USRP_E_I2C_WRITE, data); + } + + byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ + //allocate some memory for this transaction + UHD_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(mem); + data->addr = addr; + data->len = num_bytes; + + //call the spi ioctl + this->ioctl(USRP_E_I2C_READ, data); + + //unload the data + byte_vector_t bytes(data->len); + UHD_ASSERT_THROW(bytes.size() == num_bytes); + std::copy(data->data, data->data+bytes.size(), bytes.begin()); + return bytes; + } + + /******************************************************************* + * SPI + ******************************************************************/ + boost::uint32_t transact_spi( + int which_slave, + const spi_config_t &config, + boost::uint32_t bits, + size_t num_bits, + bool readback + ){ + //load data struct + usrp_e_spi data; + data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; + data.slave = which_slave; + data.length = num_bits; + data.data = bits; + + //load the flags + data.flags = 0; + data.flags |= (config.miso_edge == spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; + data.flags |= (config.mosi_edge == spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; + + //call the spi ioctl + this->ioctl(USRP_E_SPI, &data); + + //unload the data + return data.data; + } + +private: + int _node_fd; + boost::mutex _ctrl_mutex; +}; + +/*********************************************************************** + * Public Make Function + **********************************************************************/ +usrp_e_iface::sptr usrp_e_iface::make(const std::string &node){ + return sptr(new usrp_e_iface_impl(node)); +} diff --git a/host/lib/usrp/usrp_e100/usrp_e_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e_iface.hpp new file mode 100644 index 000000000..59aac43d9 --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e_iface.hpp @@ -0,0 +1,112 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E_IFACE_HPP +#define INCLUDED_USRP_E_IFACE_HPP + +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////// +// I2C addresses +//////////////////////////////////////////////////////////////////////// +#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx +#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) +#define I2C_ADDR_TX_DB (I2C_DEV_EEPROM | 0x4) +#define I2C_ADDR_RX_DB (I2C_DEV_EEPROM | 0x5) +//////////////////////////////////////////////////////////////////////// + +/*! + * The usrp-e interface class: + * Provides a set of functions to implementation layer. + * Including spi, peek, poke, control... + */ +class usrp_e_iface : boost::noncopyable, public uhd::i2c_iface{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new usrp-e interface with the control transport. + * \param node the device node name + * \return a new usrp-e interface object + */ + static sptr make(const std::string &node); + + /*! + * Get the underlying file descriptor. + * \return the file descriptor + */ + virtual int get_file_descriptor(void) = 0; + + /*! + * 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 + */ + virtual void ioctl(int request, void *mem) = 0; + + /*! + * Write a register (32 bits) + * \param addr the address + * \param data the 32bit data + */ + virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; + + /*! + * Read a register (32 bits) + * \param addr the address + * \return the 32bit data + */ + virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; + + /*! + * Write a register (16 bits) + * \param addr the address + * \param data the 16bit data + */ + virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; + + /*! + * Read a register (16 bits) + * \param addr the address + * \return the 16bit data + */ + virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; + + /*! + * Perform an spi transaction. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write + * \param num_bits how many bits in data + * \param readback true to readback a value + * \return spi data if readback set + */ + virtual boost::uint32_t transact_spi( + int which_slave, + const uhd::spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ) = 0; +}; + +#endif /* INCLUDED_USRP_E_IFACE_HPP */ diff --git a/host/lib/usrp/usrp_e100/usrp_e_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e_impl.cpp new file mode 100644 index 000000000..70cc399fb --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e_impl.cpp @@ -0,0 +1,201 @@ +// +// 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 . +// + +#include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +namespace fs = boost::filesystem; + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static std::string abs_path(const std::string &file_path){ + return fs::system_complete(fs::path(file_path)).file_string(); +} + +/*********************************************************************** + * Discovery + **********************************************************************/ +static device_addrs_t usrp_e_find(const device_addr_t &hint){ + device_addrs_t usrp_e_addrs; + + //return an empty list of addresses when type is set to non-usrp-e + if (hint.has_key("type") and hint["type"] != "usrp-e") return usrp_e_addrs; + + //device node not provided, assume its 0 + if (not hint.has_key("node")){ + device_addr_t new_addr = hint; + new_addr["node"] = "/dev/usrp_e0"; + return usrp_e_find(new_addr); + } + + //use the given device node name + if (fs::exists(hint["node"])){ + device_addr_t new_addr; + new_addr["type"] = "usrp-e"; + new_addr["node"] = abs_path(hint["node"]); + usrp_e_addrs.push_back(new_addr); + } + + return usrp_e_addrs; +} + +/*********************************************************************** + * Make + **********************************************************************/ +static device::sptr usrp_e_make(const device_addr_t &device_addr){ + + //setup the main interface into fpga + std::string node = device_addr["node"]; + std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; + usrp_e_iface::sptr iface = usrp_e_iface::make(node); + + //------------------------------------------------------------------ + //-- Handle the FPGA loading... + //-- The image can be confimed as already loaded when: + //-- 1) The compatibility number matches. + //-- 2) The hash in the hash-file matches. + //------------------------------------------------------------------ + static const char *hash_file_path = "/tmp/usrp_e100_hash"; + + //extract the fpga path for usrp-e + std::string usrp_e_fpga_image = find_image_path( + device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" + ); + + //calculate a hash of the fpga file + size_t fpga_hash = 0; + { + std::ifstream file(usrp_e_fpga_image.c_str()); + if (not file.good()) throw std::runtime_error( + "cannot open fpga file for read: " + usrp_e_fpga_image + ); + do{ + boost::hash_combine(fpga_hash, file.get()); + } while (file.good()); + file.close(); + } + + //read the compatibility number + boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + + //read the hash in the hash-file + size_t loaded_hash = 0; + try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} + + //if not loaded: load the fpga image and write the hash-file + if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ + iface.reset(); + usrp_e_load_fpga(usrp_e_fpga_image); + std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl; + iface = usrp_e_iface::make(node); + try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} + } + + //check that the compatibility is correct + fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + if (fpga_compat_num != USRP_E_COMPAT_NUM){ + throw std::runtime_error(str(boost::format( + "Expected fpga compatibility number 0x%x, but got 0x%x:\n" + "The fpga build is not compatible with the host code build." + ) % USRP_E_COMPAT_NUM % fpga_compat_num)); + } + + return device::sptr(new usrp_e_impl(iface)); +} + +UHD_STATIC_BLOCK(register_usrp_e_device){ + device::register_device(&usrp_e_find, &usrp_e_make); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp_e_impl::usrp_e_impl(usrp_e_iface::sptr iface): _iface(iface){ + + //setup interfaces into hardware + _clock_ctrl = usrp_e_clock_ctrl::make(_iface); + _codec_ctrl = usrp_e_codec_ctrl::make(_iface); + + //initialize the mboard + mboard_init(); + + //initialize the dboards + dboard_init(); + + //initialize the dsps + rx_ddc_init(); + tx_duc_init(); + + //init the codec properties + codec_init(); + + //init the io send/recv + io_init(); + + //set default subdev specs + this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t()); + this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t()); +} + +usrp_e_impl::~usrp_e_impl(void){ + /* NOP */ +} + +/*********************************************************************** + * Device Get + **********************************************************************/ +void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case DEVICE_PROP_NAME: + val = std::string("usrp-e device"); + return; + + case DEVICE_PROP_MBOARD: + UHD_ASSERT_THROW(key.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; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +/*********************************************************************** + * Device Set + **********************************************************************/ +void usrp_e_impl::set(const wax::obj &, const wax::obj &){ + UHD_THROW_PROP_SET_ERROR(); +} diff --git a/host/lib/usrp/usrp_e100/usrp_e_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e_impl.hpp new file mode 100644 index 000000000..b5f21810d --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e_impl.hpp @@ -0,0 +1,164 @@ +// +// 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 . +// + +#include "usrp_e_iface.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef INCLUDED_USRP_E_IMPL_HPP +#define INCLUDED_USRP_E_IMPL_HPP + +static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; + +//! load an fpga image from a bin file into the usrp-e fpga +extern void usrp_e_load_fpga(const std::string &bin_file); + +/*! + * Make a usrp-e dboard interface. + * \param iface the usrp-e interface object + * \param clock the clock control interface + * \param codec the codec control interface + * \return a sptr to a new dboard interface + */ +uhd::usrp::dboard_iface::sptr make_usrp_e_dboard_iface( + usrp_e_iface::sptr iface, + usrp_e_clock_ctrl::sptr clock, + usrp_e_codec_ctrl::sptr codec +); + +/*! + * 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 get_t; + typedef boost::function set_t; + typedef boost::shared_ptr sptr; + + static sptr make(const get_t &get, const set_t &set){ + return sptr(new wax_obj_proxy(get, set)); + } + +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(usrp_e_iface::sptr); + ~usrp_e_impl(void); + + //the io interface + size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); + size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); + bool recv_async_msg(uhd::async_metadata_t &, double); + size_t get_max_send_samps_per_packet(void) const; + size_t get_max_recv_samps_per_packet(void) const; + +private: + //interface to ioctls and file descriptor + usrp_e_iface::sptr _iface; + + //handle io stuff + UHD_PIMPL_DECL(io_impl) _io_impl; + uhd::otw_type_t _send_otw_type, _recv_otw_type; + void io_init(void); + void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); + void handle_overrun(size_t); + + //configuration shadows + uhd::clock_config_t _clock_config; + //TODO otw type recv/send + + //ad9522 clock control + usrp_e_clock_ctrl::sptr _clock_ctrl; + + //ad9862 codec control + usrp_e_codec_ctrl::sptr _codec_ctrl; + + //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; + uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; + + //xx dboard functions and settings + void dboard_init(void); + uhd::usrp::dboard_manager::sptr _dboard_manager; + uhd::usrp::dboard_iface::sptr _dboard_iface; + + //rx dboard functions and settings + uhd::usrp::dboard_eeprom_t _rx_db_eeprom; + 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 + uhd::usrp::dboard_eeprom_t _tx_db_eeprom; + 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 &); + double _ddc_freq; size_t _ddc_decim; + 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 &); + double _duc_freq; size_t _duc_interp; + wax_obj_proxy::sptr _tx_duc_proxy; + + //codec functions and settings + void codec_init(void); + void rx_codec_get(const wax::obj &, wax::obj &); + void rx_codec_set(const wax::obj &, const wax::obj &); + void tx_codec_get(const wax::obj &, wax::obj &); + void tx_codec_set(const wax::obj &, const wax::obj &); + wax_obj_proxy::sptr _rx_codec_proxy, _tx_codec_proxy; +}; + +#endif /* INCLUDED_USRP_E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp new file mode 100644 index 000000000..274bb043e --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp @@ -0,0 +1,215 @@ +// +// 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 . +// + +#include "usrp_e_iface.hpp" +#include +#include +#include +#include //mmap +#include //getpagesize +#include //poll +#include +#include +#include + +using namespace uhd; +using namespace uhd::transport; + +static const bool fp_verbose = false; //fast-path verbose +static const bool sp_verbose = false; //slow-path verbose +static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout + +/*********************************************************************** + * The zero copy interface implementation + **********************************************************************/ +class usrp_e_mmap_zero_copy_impl : public zero_copy_if, public boost::enable_shared_from_this { +public: + usrp_e_mmap_zero_copy_impl(usrp_e_iface::sptr iface): + _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) + { + //get system sizes + iface->ioctl(USRP_E_GET_RB_INFO, &_rb_size); + size_t page_size = getpagesize(); + _frame_size = page_size/2; + + //calculate the memory size + _map_size = + (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + + (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; + + //print sizes summary + if (sp_verbose){ + std::cout << "page_size: " << page_size << std::endl; + std::cout << "frame_size: " << _frame_size << std::endl; + std::cout << "num_pages_rx_flags: " << _rb_size.num_pages_rx_flags << std::endl; + std::cout << "num_rx_frames: " << _rb_size.num_rx_frames << std::endl; + std::cout << "num_pages_tx_flags: " << _rb_size.num_pages_tx_flags << std::endl; + std::cout << "num_tx_frames: " << _rb_size.num_tx_frames << std::endl; + std::cout << "map_size: " << _map_size << std::endl; + } + + //call mmap to get the memory + _mapped_mem = ::mmap( + NULL, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 + ); + UHD_ASSERT_THROW(_mapped_mem != MAP_FAILED); + + //calculate the memory offsets for info and buffers + size_t recv_info_off = 0; + size_t recv_buff_off = recv_info_off + (_rb_size.num_pages_rx_flags * page_size); + size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); + size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); + + //print offset summary + if (sp_verbose){ + std::cout << "recv_info_off: " << recv_info_off << std::endl; + std::cout << "recv_buff_off: " << recv_buff_off << std::endl; + std::cout << "send_info_off: " << send_info_off << std::endl; + std::cout << "send_buff_off: " << send_buff_off << std::endl; + } + + //set the internal pointers for info and buffers + typedef ring_buffer_info (*rbi_pta)[]; + char *rb_ptr = reinterpret_cast(_mapped_mem); + _recv_info = reinterpret_cast(rb_ptr + recv_info_off); + _recv_buff = rb_ptr + recv_buff_off; + _send_info = reinterpret_cast(rb_ptr + send_info_off); + _send_buff = rb_ptr + send_buff_off; + } + + ~usrp_e_mmap_zero_copy_impl(void){ + if (sp_verbose) std::cout << "cleanup: munmap" << std::endl; + ::munmap(_mapped_mem, _map_size); + } + + managed_recv_buffer::sptr get_recv_buff(double timeout){ + if (fp_verbose) std::cout << "get_recv_buff: " << _recv_index << std::endl; + + //grab pointers to the info and buffer + ring_buffer_info *info = (*_recv_info) + _recv_index; + void *mem = _recv_buff + _frame_size*_recv_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_USER)){ + for (size_t i = 0; i < poll_breakout; i++){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLIN; + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3/poll_breakout)); + if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; + if (poll_ret > 0) goto found_user_frame; //good poll, continue on + } + return managed_recv_buffer::sptr(); //timed-out for real + } found_user_frame: + + //the process has claimed the frame + info->flags = RB_USER_PROCESS; + + //increment the index for the next call + if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; + + //return the managed buffer for this frame + if (fp_verbose) std::cout << " make_recv_buff: " << info->len << std::endl; + return managed_recv_buffer::make_safe( + boost::asio::const_buffer(mem, info->len), + boost::bind(&usrp_e_mmap_zero_copy_impl::release, shared_from_this(), info) + ); + } + + size_t get_num_recv_frames(void) const{ + return _rb_size.num_rx_frames; + } + + size_t get_recv_frame_size(void) const{ + return _frame_size; + } + + managed_send_buffer::sptr get_send_buff(double timeout){ + if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; + + //grab pointers to the info and buffer + ring_buffer_info *info = (*_send_info) + _send_index; + void *mem = _send_buff + _frame_size*_send_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_KERNEL)){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLOUT; + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); + if (fp_verbose) std::cout << " POLLOUT: " << poll_ret << std::endl; + if (poll_ret <= 0) return managed_send_buffer::sptr(); + } + + //increment the index for the next call + if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; + + //return the managed buffer for this frame + if (fp_verbose) std::cout << " make_send_buff: " << _frame_size << std::endl; + return managed_send_buffer::make_safe( + boost::asio::mutable_buffer(mem, _frame_size), + boost::bind(&usrp_e_mmap_zero_copy_impl::commit, shared_from_this(), info, _1) + ); + } + + size_t get_num_send_frames(void) const{ + return _rb_size.num_tx_frames; + } + + size_t get_send_frame_size(void) const{ + return _frame_size; + } + +private: + + void release(ring_buffer_info *info){ + if (fp_verbose) std::cout << "recv buff: release" << std::endl; + info->flags = RB_KERNEL; + } + + void commit(ring_buffer_info *info, size_t len){ + if (fp_verbose) std::cout << "send buff: commit " << len << std::endl; + info->len = len; + info->flags = RB_USER; + if (::write(_fd, NULL, 0) < 0){ + std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl; + } + } + + int _fd; + + //the mapped memory itself + void *_mapped_mem; + + //mapped memory sizes + usrp_e_ring_buffer_size_t _rb_size; + size_t _frame_size, _map_size; + + //pointers to sections in the mapped memory + ring_buffer_info (*_recv_info)[], (*_send_info)[]; + char *_recv_buff, *_send_buff; + + //indexes into sub-sections of mapped memory + size_t _recv_index, _send_index; +}; + +/*********************************************************************** + * The zero copy interface make function + **********************************************************************/ +zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface){ + return zero_copy_if::sptr(new usrp_e_mmap_zero_copy_impl(iface)); +} diff --git a/host/lib/usrp/usrp_e100/usrp_e_regs.hpp b/host/lib/usrp/usrp_e100/usrp_e_regs.hpp new file mode 100644 index 000000000..8bfb08b6f --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e_regs.hpp @@ -0,0 +1,198 @@ + + +//////////////////////////////////////////////////////////////// +// +// 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) +#define UE_REG_SR_ADDR(n) ((UE_REG_SLAVE(5)) + (4*(n))) + +///////////////////////////////////////////////////// +// 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 +#define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 +#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 +#define UE_REG_MISC_XFER_RATE UE_REG_MISC_BASE + 14 +#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 16 + +///////////////////////////////////////////////////// +// 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) + +//spi slave constants +#define UE_SPI_SS_AD9522 (1 << 3) +#define UE_SPI_SS_AD9862 (1 << 2) +#define UE_SPI_SS_TX_DB (1 << 1) +#define UE_SPI_SS_RX_DB (1 << 0) + +//////////////////////////////////////////////// +// 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 + +//possible bit values for sel when dbg is 0: +#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 + +//possible bit values for sel when dbg is 1: +#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 + +///////////////////////////////////////////////// +// DSP RX Regs +//////////////////////////////////////////////// +#define UE_REG_DSP_RX_FREQ UE_REG_SR_ADDR(0) +#define UE_REG_DSP_RX_SCALE_IQ UE_REG_SR_ADDR(1) // {scale_i,scale_q} +#define UE_REG_DSP_RX_DECIM_RATE UE_REG_SR_ADDR(2) // hb and decim rate +#define UE_REG_DSP_RX_DCOFFSET_I UE_REG_SR_ADDR(3) // Bit 31 high sets fixed offset mode, using lower 14 bits, // otherwise it is automatic +#define UE_REG_DSP_RX_DCOFFSET_Q UE_REG_SR_ADDR(4) // Bit 31 high sets fixed offset mode, using lower 14 bits +#define UE_REG_DSP_RX_MUX UE_REG_SR_ADDR(5) + +/////////////////////////////////////////////////// +// VITA RX CTRL regs +/////////////////////////////////////////////////// +// The following 3 are logically a single command register. +// They are clocked into the underlying fifo when time_ticks is written. +#define UE_REG_CTRL_RX_STREAM_CMD UE_REG_SR_ADDR(8) // {now, chain, num_samples(30) +#define UE_REG_CTRL_RX_TIME_SECS UE_REG_SR_ADDR(9) +#define UE_REG_CTRL_RX_TIME_TICKS UE_REG_SR_ADDR(10) +#define UE_REG_CTRL_RX_CLEAR_OVERRUN UE_REG_SR_ADDR(11) // write anything to clear overrun +#define UE_REG_CTRL_RX_VRT_HEADER UE_REG_SR_ADDR(12) // word 0 of packet. FPGA fills in packet counter +#define UE_REG_CTRL_RX_VRT_STREAM_ID UE_REG_SR_ADDR(13) // word 1 of packet. +#define UE_REG_CTRL_RX_VRT_TRAILER UE_REG_SR_ADDR(14) +#define UE_REG_CTRL_RX_NSAMPS_PER_PKT UE_REG_SR_ADDR(15) +#define UE_REG_CTRL_RX_NCHANNELS UE_REG_SR_ADDR(16) // 1 in basic case, up to 4 for vector sources + +///////////////////////////////////////////////// +// DSP TX Regs +//////////////////////////////////////////////// +#define UE_REG_DSP_TX_FREQ UE_REG_SR_ADDR(17) +#define UE_REG_DSP_TX_SCALE_IQ UE_REG_SR_ADDR(18) // {scale_i,scale_q} +#define UE_REG_DSP_TX_INTERP_RATE UE_REG_SR_ADDR(19) +#define UE_REG_DSP_TX_UNUSED UE_REG_SR_ADDR(20) +#define UE_REG_DSP_TX_MUX UE_REG_SR_ADDR(21) + +///////////////////////////////////////////////// +// VITA TX CTRL regs +//////////////////////////////////////////////// +#define UE_REG_CTRL_TX_NCHANNELS UE_REG_SR_ADDR(24) +#define UE_REG_CTRL_TX_CLEAR_UNDERRUN UE_REG_SR_ADDR(25) +#define UE_REG_CTRL_TX_REPORT_SID UE_REG_SR_ADDR(26) +#define UE_REG_CTRL_TX_POLICY UE_REG_SR_ADDR(27) + +#define UE_FLAG_CTRL_TX_POLICY_WAIT (0x1 << 0) +#define UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET (0x1 << 1) +#define UE_FLAG_CTRL_TX_POLICY_NEXT_BURST (0x1 << 2) + +///////////////////////////////////////////////// +// VITA49 64 bit time (write only) +//////////////////////////////////////////////// + /*! + * \brief Time 64 flags + * + *
+   *
+   *    3                   2                   1
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-----------------------------------------------------------+-+-+
+   * |                                                           |S|P|
+   * +-----------------------------------------------------------+-+-+
+   *
+   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
+   * S - Source (0=sma, 1=mimo, 0=default)
+   *
+   * 
+ */ +#define UE_REG_TIME64_SECS UE_REG_SR_ADDR(28) // value to set absolute secs to on next PPS +#define UE_REG_TIME64_TICKS UE_REG_SR_ADDR(29) // value to set absolute ticks to on next PPS +#define UE_REG_TIME64_FLAGS UE_REG_SR_ADDR(30) // flags - see chart above +#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0) +#define UE_REG_TIME64_TPS UE_REG_SR_ADDR(31) // clock ticks per second (counter rollover) + +//pps flags (see above) +#define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0) +#define UE_FLAG_TIME64_PPS_POSEDGE (1 << 0) +#define UE_FLAG_TIME64_PPS_SMA (0 << 1) +#define UE_FLAG_TIME64_PPS_MIMO (1 << 1) + +#define UE_FLAG_TIME64_LATCH_NOW 1 +#define UE_FLAG_TIME64_LATCH_NEXT_PPS 0 + +#endif + -- cgit v1.2.3 From 5f2c71383a2b5dd0f2f469f6ad8c4720358f2a12 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 9 Nov 2010 19:02:11 -0800 Subject: usrp-e100: renamed files and classes in usrp-e100 to e100 name --- host/lib/usrp/usrp_e100/CMakeLists.txt | 12 +- host/lib/usrp/usrp_e100/clock_ctrl.cpp | 14 +- host/lib/usrp/usrp_e100/clock_ctrl.hpp | 16 +- host/lib/usrp/usrp_e100/codec_ctrl.cpp | 38 ++-- host/lib/usrp/usrp_e100/codec_ctrl.hpp | 16 +- host/lib/usrp/usrp_e100/codec_impl.cpp | 24 +-- host/lib/usrp/usrp_e100/dboard_iface.cpp | 86 ++++----- host/lib/usrp/usrp_e100/dboard_impl.cpp | 24 +-- host/lib/usrp/usrp_e100/dsp_impl.cpp | 24 +-- host/lib/usrp/usrp_e100/fpga-downloader.cc | 2 +- host/lib/usrp/usrp_e100/io_impl.cpp | 38 ++-- host/lib/usrp/usrp_e100/mboard_impl.cpp | 14 +- host/lib/usrp/usrp_e100/usrp_e100_iface.cpp | 194 +++++++++++++++++++ host/lib/usrp/usrp_e100/usrp_e100_iface.hpp | 112 +++++++++++ host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 201 +++++++++++++++++++ host/lib/usrp/usrp_e100/usrp_e100_impl.hpp | 164 ++++++++++++++++ .../usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp | 215 +++++++++++++++++++++ host/lib/usrp/usrp_e100/usrp_e100_regs.hpp | 198 +++++++++++++++++++ host/lib/usrp/usrp_e100/usrp_e_iface.cpp | 194 ------------------- host/lib/usrp/usrp_e100/usrp_e_iface.hpp | 112 ----------- host/lib/usrp/usrp_e100/usrp_e_impl.cpp | 201 ------------------- host/lib/usrp/usrp_e100/usrp_e_impl.hpp | 164 ---------------- host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp | 215 --------------------- host/lib/usrp/usrp_e100/usrp_e_regs.hpp | 198 ------------------- 24 files changed, 1238 insertions(+), 1238 deletions(-) create mode 100644 host/lib/usrp/usrp_e100/usrp_e100_iface.cpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e100_iface.hpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e100_impl.cpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e100_impl.hpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp create mode 100644 host/lib/usrp/usrp_e100/usrp_e100_regs.hpp delete mode 100644 host/lib/usrp/usrp_e100/usrp_e_iface.cpp delete mode 100644 host/lib/usrp/usrp_e100/usrp_e_iface.hpp delete mode 100644 host/lib/usrp/usrp_e100/usrp_e_impl.cpp delete mode 100644 host/lib/usrp/usrp_e100/usrp_e_impl.hpp delete mode 100644 host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp delete mode 100644 host/lib/usrp/usrp_e100/usrp_e_regs.hpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/CMakeLists.txt b/host/lib/usrp/usrp_e100/CMakeLists.txt index 17ef53152..97a3d5d9a 100644 --- a/host/lib/usrp/usrp_e100/CMakeLists.txt +++ b/host/lib/usrp/usrp_e100/CMakeLists.txt @@ -52,12 +52,12 @@ IF(ENABLE_USRP_E100) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/fpga-downloader.cc ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/io_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/mboard_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_impl.hpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_iface.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_iface.hpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e_regs.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e100_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e100_impl.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e100_iface.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e100_iface.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/usrp_e100_regs.hpp ) ELSE(ENABLE_USRP_E100) MESSAGE(STATUS " Skipping USRP-E100 support.") diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index 9d4625305..e99560540 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -19,7 +19,7 @@ #include "ad9522_regs.hpp" #include #include -#include "usrp_e_regs.hpp" //spi slave constants +#include "usrp_e100_regs.hpp" //spi slave constants #include #include #include @@ -58,9 +58,9 @@ static const size_t codec_clock_divider = size_t(master_clock_rate/64e6); /*********************************************************************** * Clock Control Implementation **********************************************************************/ -class usrp_e_clock_ctrl_impl : public usrp_e_clock_ctrl{ +class usrp_e100_clock_ctrl_impl : public usrp_e100_clock_ctrl{ public: - usrp_e_clock_ctrl_impl(usrp_e_iface::sptr iface){ + usrp_e100_clock_ctrl_impl(usrp_e100_iface::sptr iface){ _iface = iface; //init the clock gen registers @@ -137,7 +137,7 @@ public: this->enable_tx_dboard_clock(false); } - ~usrp_e_clock_ctrl_impl(void){ + ~usrp_e100_clock_ctrl_impl(void){ this->enable_rx_dboard_clock(false); this->enable_tx_dboard_clock(false); } @@ -210,7 +210,7 @@ public: } private: - usrp_e_iface::sptr _iface; + usrp_e100_iface::sptr _iface; ad9522_regs_t _ad9522_regs; void latch_regs(void){ @@ -232,6 +232,6 @@ private: /*********************************************************************** * Clock Control Make **********************************************************************/ -usrp_e_clock_ctrl::sptr usrp_e_clock_ctrl::make(usrp_e_iface::sptr iface){ - return sptr(new usrp_e_clock_ctrl_impl(iface)); +usrp_e100_clock_ctrl::sptr usrp_e100_clock_ctrl::make(usrp_e100_iface::sptr iface){ + return sptr(new usrp_e100_clock_ctrl_impl(iface)); } diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.hpp b/host/lib/usrp/usrp_e100/clock_ctrl.hpp index 3b5103ed1..0ae68728e 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.hpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.hpp @@ -15,10 +15,10 @@ // along with this program. If not, see . // -#ifndef INCLUDED_USRP_E_CLOCK_CTRL_HPP -#define INCLUDED_USRP_E_CLOCK_CTRL_HPP +#ifndef INCLUDED_USRP_E100_CLOCK_CTRL_HPP +#define INCLUDED_USRP_E100_CLOCK_CTRL_HPP -#include "usrp_e_iface.hpp" +#include "usrp_e100_iface.hpp" #include #include #include @@ -28,16 +28,16 @@ * - Setup system clocks. * - Disable/enable clock lines. */ -class usrp_e_clock_ctrl : boost::noncopyable{ +class usrp_e100_clock_ctrl : boost::noncopyable{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; /*! * Make a new clock control object. - * \param iface the usrp_e iface object + * \param iface the usrp_e100 iface object * \return the clock control object */ - static sptr make(usrp_e_iface::sptr iface); + static sptr make(usrp_e100_iface::sptr iface); /*! * Get the rate of the fpga clock line. @@ -85,4 +85,4 @@ public: }; -#endif /* INCLUDED_USRP_E_CLOCK_CTRL_HPP */ +#endif /* INCLUDED_USRP_E100_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e100/codec_ctrl.cpp b/host/lib/usrp/usrp_e100/codec_ctrl.cpp index a728d7e46..e7fd9792e 100644 --- a/host/lib/usrp/usrp_e100/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/codec_ctrl.cpp @@ -23,7 +23,7 @@ #include #include #include -#include "usrp_e_regs.hpp" //spi slave constants +#include "usrp_e100_regs.hpp" //spi slave constants #include #include @@ -31,17 +31,17 @@ using namespace uhd; static const bool codec_debug = false; -const gain_range_t usrp_e_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); -const gain_range_t usrp_e_codec_ctrl::rx_pga_gain_range(0, 20, 1); +const gain_range_t usrp_e100_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); +const gain_range_t usrp_e100_codec_ctrl::rx_pga_gain_range(0, 20, 1); /*********************************************************************** * Codec Control Implementation **********************************************************************/ -class usrp_e_codec_ctrl_impl : public usrp_e_codec_ctrl{ +class usrp_e100_codec_ctrl_impl : public usrp_e100_codec_ctrl{ public: //structors - usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface); - ~usrp_e_codec_ctrl_impl(void); + usrp_e100_codec_ctrl_impl(usrp_e100_iface::sptr iface); + ~usrp_e100_codec_ctrl_impl(void); //aux adc and dac control float read_aux_adc(aux_adc_t which); @@ -54,7 +54,7 @@ public: float get_rx_pga_gain(char); private: - usrp_e_iface::sptr _iface; + usrp_e100_iface::sptr _iface; ad9862_regs_t _ad9862_regs; aux_adc_t _last_aux_adc_a, _last_aux_adc_b; void send_reg(boost::uint8_t addr); @@ -64,7 +64,7 @@ private: /*********************************************************************** * Codec Control Structors **********************************************************************/ -usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ +usrp_e100_codec_ctrl_impl::usrp_e100_codec_ctrl_impl(usrp_e100_iface::sptr iface){ _iface = iface; //soft reset @@ -115,7 +115,7 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ this->send_reg(34); } -usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ +usrp_e100_codec_ctrl_impl::~usrp_e100_codec_ctrl_impl(void){ //set aux dacs to zero this->write_aux_dac(AUX_DAC_A, 0); this->write_aux_dac(AUX_DAC_B, 0); @@ -135,19 +135,19 @@ usrp_e_codec_ctrl_impl::~usrp_e_codec_ctrl_impl(void){ **********************************************************************/ static const int mtpgw = 255; //maximum tx pga gain word -void usrp_e_codec_ctrl_impl::set_tx_pga_gain(float gain){ +void usrp_e100_codec_ctrl_impl::set_tx_pga_gain(float gain){ int gain_word = int(mtpgw*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw); this->send_reg(16); } -float usrp_e_codec_ctrl_impl::get_tx_pga_gain(void){ +float usrp_e100_codec_ctrl_impl::get_tx_pga_gain(void){ return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/mtpgw) + tx_pga_gain_range.min; } static const int mrpgw = 0x14; //maximum rx pga gain word -void usrp_e_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){ +void usrp_e100_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){ int gain_word = int(mrpgw*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min)); gain_word = std::clip(gain_word, 0, mrpgw); switch(which){ @@ -163,7 +163,7 @@ void usrp_e_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){ } } -float usrp_e_codec_ctrl_impl::get_rx_pga_gain(char which){ +float usrp_e100_codec_ctrl_impl::get_rx_pga_gain(char which){ int gain_word; switch(which){ case 'A': gain_word = _ad9862_regs.rx_pga_a; break; @@ -180,7 +180,7 @@ static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){ return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; } -float usrp_e_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ +float usrp_e100_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ //check to see if the switch needs to be set bool write_switch = false; switch(which){ @@ -233,7 +233,7 @@ float usrp_e_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ /*********************************************************************** * Codec Control AUX DAC Methods **********************************************************************/ -void usrp_e_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ +void usrp_e100_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ //special case for aux dac d (aka sigma delta word) if (which == AUX_DAC_D){ boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff); @@ -266,7 +266,7 @@ void usrp_e_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ /*********************************************************************** * Codec Control SPI Methods **********************************************************************/ -void usrp_e_codec_ctrl_impl::send_reg(boost::uint8_t addr){ +void usrp_e100_codec_ctrl_impl::send_reg(boost::uint8_t addr){ boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); if (codec_debug) std::cout << "codec control write reg: " << std::hex << reg << std::endl; _iface->transact_spi( @@ -276,7 +276,7 @@ void usrp_e_codec_ctrl_impl::send_reg(boost::uint8_t addr){ ); } -void usrp_e_codec_ctrl_impl::recv_reg(boost::uint8_t addr){ +void usrp_e100_codec_ctrl_impl::recv_reg(boost::uint8_t addr){ boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); if (codec_debug) std::cout << "codec control read reg: " << std::hex << reg << std::endl; boost::uint32_t ret = _iface->transact_spi( @@ -291,6 +291,6 @@ void usrp_e_codec_ctrl_impl::recv_reg(boost::uint8_t addr){ /*********************************************************************** * Codec Control Make **********************************************************************/ -usrp_e_codec_ctrl::sptr usrp_e_codec_ctrl::make(usrp_e_iface::sptr iface){ - return sptr(new usrp_e_codec_ctrl_impl(iface)); +usrp_e100_codec_ctrl::sptr usrp_e100_codec_ctrl::make(usrp_e100_iface::sptr iface){ + return sptr(new usrp_e100_codec_ctrl_impl(iface)); } diff --git a/host/lib/usrp/usrp_e100/codec_ctrl.hpp b/host/lib/usrp/usrp_e100/codec_ctrl.hpp index 87b6ff951..74ce9bd9a 100644 --- a/host/lib/usrp/usrp_e100/codec_ctrl.hpp +++ b/host/lib/usrp/usrp_e100/codec_ctrl.hpp @@ -15,10 +15,10 @@ // along with this program. If not, see . // -#ifndef INCLUDED_USRP_E_CODEC_CTRL_HPP -#define INCLUDED_USRP_E_CODEC_CTRL_HPP +#ifndef INCLUDED_USRP_E100_CODEC_CTRL_HPP +#define INCLUDED_USRP_E100_CODEC_CTRL_HPP -#include "usrp_e_iface.hpp" +#include "usrp_e100_iface.hpp" #include #include #include @@ -28,19 +28,19 @@ * - Init/power down codec. * - Read aux adc, write aux dac. */ -class usrp_e_codec_ctrl : boost::noncopyable{ +class usrp_e100_codec_ctrl : boost::noncopyable{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; static const uhd::gain_range_t tx_pga_gain_range; static const uhd::gain_range_t rx_pga_gain_range; /*! * Make a new codec control object. - * \param iface the usrp_e iface object + * \param iface the usrp_e100 iface object * \return the codec control object */ - static sptr make(usrp_e_iface::sptr iface); + static sptr make(usrp_e100_iface::sptr iface); //! aux adc identifier constants enum aux_adc_t{ @@ -87,4 +87,4 @@ public: virtual float get_rx_pga_gain(char which) = 0; }; -#endif /* INCLUDED_USRP_E_CODEC_CTRL_HPP */ +#endif /* INCLUDED_USRP_E100_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp_e100/codec_impl.cpp b/host/lib/usrp/usrp_e100/codec_impl.cpp index 696fb37ec..6fd44bad3 100644 --- a/host/lib/usrp/usrp_e100/codec_impl.cpp +++ b/host/lib/usrp/usrp_e100/codec_impl.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . // -#include "usrp_e_impl.hpp" +#include "usrp_e100_impl.hpp" #include #include #include @@ -26,15 +26,15 @@ using namespace uhd::usrp; /*********************************************************************** * Helper Methods **********************************************************************/ -void usrp_e_impl::codec_init(void){ +void usrp_e100_impl::codec_init(void){ //make proxies _rx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp_e_impl::rx_codec_get, this, _1, _2), - boost::bind(&usrp_e_impl::rx_codec_set, this, _1, _2) + boost::bind(&usrp_e100_impl::rx_codec_get, this, _1, _2), + boost::bind(&usrp_e100_impl::rx_codec_set, this, _1, _2) ); _tx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp_e_impl::tx_codec_get, this, _1, _2), - boost::bind(&usrp_e_impl::tx_codec_set, this, _1, _2) + boost::bind(&usrp_e100_impl::tx_codec_get, this, _1, _2), + boost::bind(&usrp_e100_impl::tx_codec_set, this, _1, _2) ); } @@ -43,7 +43,7 @@ void usrp_e_impl::codec_init(void){ **********************************************************************/ static const std::string ad9862_pga_gain_name = "ad9862 pga"; -void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key @@ -62,7 +62,7 @@ void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ case CODEC_PROP_GAIN_RANGE: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = usrp_e_codec_ctrl::rx_pga_gain_range; + val = usrp_e100_codec_ctrl::rx_pga_gain_range; return; case CODEC_PROP_GAIN_I: @@ -79,7 +79,7 @@ void usrp_e_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ } } -void usrp_e_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ +void usrp_e100_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); //handle the set request conditioned on the key @@ -101,7 +101,7 @@ void usrp_e_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ /*********************************************************************** * TX Codec Properties **********************************************************************/ -void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key @@ -120,7 +120,7 @@ void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ case CODEC_PROP_GAIN_RANGE: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = usrp_e_codec_ctrl::tx_pga_gain_range; + val = usrp_e100_codec_ctrl::tx_pga_gain_range; return; case CODEC_PROP_GAIN_I: //only one gain for I and Q @@ -133,7 +133,7 @@ void usrp_e_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ } } -void usrp_e_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val){ +void usrp_e100_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); //handle the set request conditioned on the key diff --git a/host/lib/usrp/usrp_e100/dboard_iface.cpp b/host/lib/usrp/usrp_e100/dboard_iface.cpp index 6898df8df..aa96171d6 100644 --- a/host/lib/usrp/usrp_e100/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e100/dboard_iface.cpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#include "usrp_e_iface.hpp" -#include "usrp_e_regs.hpp" +#include "usrp_e100_iface.hpp" +#include "usrp_e100_regs.hpp" #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" #include @@ -29,13 +29,13 @@ using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; -class usrp_e_dboard_iface : public dboard_iface{ +class usrp_e100_dboard_iface : public dboard_iface{ public: - usrp_e_dboard_iface( - usrp_e_iface::sptr iface, - usrp_e_clock_ctrl::sptr clock, - usrp_e_codec_ctrl::sptr codec + usrp_e100_dboard_iface( + usrp_e100_iface::sptr iface, + usrp_e100_clock_ctrl::sptr clock, + usrp_e100_codec_ctrl::sptr codec ){ _iface = iface; _clock = clock; @@ -49,7 +49,7 @@ public: _iface->poke16(UE_REG_GPIO_TX_DBG, 0); } - ~usrp_e_dboard_iface(void){ + ~usrp_e100_dboard_iface(void){ /* NOP */ } @@ -94,27 +94,27 @@ public: double get_codec_rate(unit_t); private: - usrp_e_iface::sptr _iface; - usrp_e_clock_ctrl::sptr _clock; - usrp_e_codec_ctrl::sptr _codec; + usrp_e100_iface::sptr _iface; + usrp_e100_clock_ctrl::sptr _clock; + usrp_e100_codec_ctrl::sptr _codec; uhd::dict _clock_rates; }; /*********************************************************************** * Make Function **********************************************************************/ -dboard_iface::sptr make_usrp_e_dboard_iface( - usrp_e_iface::sptr iface, - usrp_e_clock_ctrl::sptr clock, - usrp_e_codec_ctrl::sptr codec +dboard_iface::sptr make_usrp_e100_dboard_iface( + usrp_e100_iface::sptr iface, + usrp_e100_clock_ctrl::sptr clock, + usrp_e100_codec_ctrl::sptr codec ){ - return dboard_iface::sptr(new usrp_e_dboard_iface(iface, clock, codec)); + return dboard_iface::sptr(new usrp_e100_dboard_iface(iface, clock, codec)); } /*********************************************************************** * Clock Rates **********************************************************************/ -void usrp_e_dboard_iface::set_clock_rate(unit_t unit, double rate){ +void usrp_e100_dboard_iface::set_clock_rate(unit_t unit, double rate){ _clock_rates[unit] = rate; switch(unit){ case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate); @@ -122,7 +122,7 @@ void usrp_e_dboard_iface::set_clock_rate(unit_t unit, double rate){ } } -std::vector usrp_e_dboard_iface::get_clock_rates(unit_t unit){ +std::vector usrp_e100_dboard_iface::get_clock_rates(unit_t unit){ switch(unit){ case UNIT_RX: return _clock->get_rx_dboard_clock_rates(); case UNIT_TX: return _clock->get_tx_dboard_clock_rates(); @@ -130,25 +130,25 @@ std::vector usrp_e_dboard_iface::get_clock_rates(unit_t unit){ } } -double usrp_e_dboard_iface::get_clock_rate(unit_t unit){ +double usrp_e100_dboard_iface::get_clock_rate(unit_t unit){ return _clock_rates[unit]; } -void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ +void usrp_e100_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ switch(unit){ case UNIT_RX: return _clock->enable_rx_dboard_clock(enb); case UNIT_TX: return _clock->enable_tx_dboard_clock(enb); } } -double usrp_e_dboard_iface::get_codec_rate(unit_t){ +double usrp_e100_dboard_iface::get_codec_rate(unit_t){ return _clock->get_fpga_clock_rate(); } /*********************************************************************** * GPIO **********************************************************************/ -void usrp_e_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){ +void usrp_e100_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){ UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption switch(unit){ case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_SEL, value); return; @@ -156,21 +156,21 @@ void usrp_e_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){ } } -void usrp_e_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ +void usrp_e100_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ switch(unit){ case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_DDR, value); return; case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_DDR, value); return; } } -void usrp_e_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){ +void usrp_e100_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){ switch(unit){ case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_IO, value); return; case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_IO, value); return; } } -boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t unit){ +boost::uint16_t usrp_e100_dboard_iface::read_gpio(unit_t unit){ switch(unit){ case UNIT_RX: return _iface->peek16(UE_REG_GPIO_RX_IO); case UNIT_TX: return _iface->peek16(UE_REG_GPIO_TX_IO); @@ -178,7 +178,7 @@ boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t unit){ } } -void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ +void usrp_e100_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ //define mapping of unit to atr regs to register address static const uhd::dict< unit_t, uhd::dict @@ -199,7 +199,7 @@ void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_ _iface->poke16(unit_to_atr_to_addr[unit][atr], value); } -void usrp_e_dboard_iface::set_gpio_debug(unit_t unit, int which){ +void usrp_e100_dboard_iface::set_gpio_debug(unit_t unit, int which){ //set this unit to all outputs this->set_gpio_ddr(unit, 0xffff); @@ -238,7 +238,7 @@ static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit){ throw std::invalid_argument("unknown unit type"); } -void usrp_e_dboard_iface::write_spi( +void usrp_e100_dboard_iface::write_spi( unit_t unit, const spi_config_t &config, boost::uint32_t data, @@ -247,7 +247,7 @@ void usrp_e_dboard_iface::write_spi( _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); } -boost::uint32_t usrp_e_dboard_iface::read_write_spi( +boost::uint32_t usrp_e100_dboard_iface::read_write_spi( unit_t unit, const spi_config_t &config, boost::uint32_t data, @@ -259,39 +259,39 @@ boost::uint32_t usrp_e_dboard_iface::read_write_spi( /*********************************************************************** * I2C **********************************************************************/ -void usrp_e_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ +void usrp_e100_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ return _iface->write_i2c(addr, bytes); } -byte_vector_t usrp_e_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ +byte_vector_t usrp_e100_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ return _iface->read_i2c(addr, num_bytes); } /*********************************************************************** * Aux DAX/ADC **********************************************************************/ -void usrp_e_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which, float value){ +void usrp_e100_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which, float value){ //same aux dacs for each unit - static const uhd::dict which_to_aux_dac = map_list_of - (AUX_DAC_A, usrp_e_codec_ctrl::AUX_DAC_A) - (AUX_DAC_B, usrp_e_codec_ctrl::AUX_DAC_B) - (AUX_DAC_C, usrp_e_codec_ctrl::AUX_DAC_C) - (AUX_DAC_D, usrp_e_codec_ctrl::AUX_DAC_D) + static const uhd::dict which_to_aux_dac = map_list_of + (AUX_DAC_A, usrp_e100_codec_ctrl::AUX_DAC_A) + (AUX_DAC_B, usrp_e100_codec_ctrl::AUX_DAC_B) + (AUX_DAC_C, usrp_e100_codec_ctrl::AUX_DAC_C) + (AUX_DAC_D, usrp_e100_codec_ctrl::AUX_DAC_D) ; _codec->write_aux_dac(which_to_aux_dac[which], value); } -float usrp_e_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, aux_adc_t which){ +float usrp_e100_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, aux_adc_t which){ static const uhd::dict< - unit_t, uhd::dict + unit_t, uhd::dict > unit_to_which_to_aux_adc = map_list_of (UNIT_RX, map_list_of - (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A1) - (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B1) + (AUX_ADC_A, usrp_e100_codec_ctrl::AUX_ADC_A1) + (AUX_ADC_B, usrp_e100_codec_ctrl::AUX_ADC_B1) ) (UNIT_TX, map_list_of - (AUX_ADC_A, usrp_e_codec_ctrl::AUX_ADC_A2) - (AUX_ADC_B, usrp_e_codec_ctrl::AUX_ADC_B2) + (AUX_ADC_A, usrp_e100_codec_ctrl::AUX_ADC_A2) + (AUX_ADC_B, usrp_e100_codec_ctrl::AUX_ADC_B2) ) ; return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]); diff --git a/host/lib/usrp/usrp_e100/dboard_impl.cpp b/host/lib/usrp/usrp_e100/dboard_impl.cpp index f2840dcfc..9f2bfb8ae 100644 --- a/host/lib/usrp/usrp_e100/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/dboard_impl.cpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" +#include "usrp_e100_impl.hpp" +#include "usrp_e100_regs.hpp" #include #include #include @@ -30,12 +30,12 @@ using namespace uhd::usrp; /*********************************************************************** * Dboard Initialization **********************************************************************/ -void usrp_e_impl::dboard_init(void){ +void usrp_e100_impl::dboard_init(void){ _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); //create a new dboard interface and manager - _dboard_iface = make_usrp_e_dboard_iface( + _dboard_iface = make_usrp_e100_dboard_iface( _iface, _clock_ctrl, _codec_ctrl ); _dboard_manager = dboard_manager::make( @@ -44,19 +44,19 @@ void usrp_e_impl::dboard_init(void){ //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) + boost::bind(&usrp_e100_impl::rx_dboard_get, this, _1, _2), + boost::bind(&usrp_e100_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) + boost::bind(&usrp_e100_impl::tx_dboard_get, this, _1, _2), + boost::bind(&usrp_e100_impl::tx_dboard_set, this, _1, _2) ); } /*********************************************************************** * RX Dboard Get **********************************************************************/ -void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key @@ -101,7 +101,7 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * RX Dboard Set **********************************************************************/ -void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ +void usrp_e100_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as()){ case DBOARD_PROP_DBOARD_ID: _rx_db_eeprom.id = val.as(); @@ -115,7 +115,7 @@ void usrp_e_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ /*********************************************************************** * TX Dboard Get **********************************************************************/ -void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key @@ -160,7 +160,7 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * TX Dboard Set **********************************************************************/ -void usrp_e_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ +void usrp_e100_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as()){ case DBOARD_PROP_DBOARD_ID: _tx_db_eeprom.id = val.as(); diff --git a/host/lib/usrp/usrp_e100/dsp_impl.cpp b/host/lib/usrp/usrp_e100/dsp_impl.cpp index 97f173c1a..43a3bd3be 100644 --- a/host/lib/usrp/usrp_e100/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e100/dsp_impl.cpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" +#include "usrp_e100_impl.hpp" +#include "usrp_e100_regs.hpp" #include #include #include @@ -30,10 +30,10 @@ using namespace uhd::usrp; /*********************************************************************** * RX DDC Initialization **********************************************************************/ -void usrp_e_impl::rx_ddc_init(void){ +void usrp_e100_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) + boost::bind(&usrp_e100_impl::rx_ddc_get, this, _1, _2), + boost::bind(&usrp_e100_impl::rx_ddc_set, this, _1, _2) ); //initial config and update @@ -44,7 +44,7 @@ void usrp_e_impl::rx_ddc_init(void){ /*********************************************************************** * RX DDC Get **********************************************************************/ -void usrp_e_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); switch(key.as()){ @@ -79,7 +79,7 @@ void usrp_e_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * RX DDC Set **********************************************************************/ -void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ +void usrp_e100_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); switch(key.as()){ @@ -113,10 +113,10 @@ void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ /*********************************************************************** * TX DUC Initialization **********************************************************************/ -void usrp_e_impl::tx_duc_init(void){ +void usrp_e100_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) + boost::bind(&usrp_e100_impl::tx_duc_get, this, _1, _2), + boost::bind(&usrp_e100_impl::tx_duc_set, this, _1, _2) ); //initial config and update @@ -127,7 +127,7 @@ void usrp_e_impl::tx_duc_init(void){ /*********************************************************************** * TX DUC Get **********************************************************************/ -void usrp_e_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); switch(key.as()){ @@ -162,7 +162,7 @@ void usrp_e_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * TX DUC Set **********************************************************************/ -void usrp_e_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ +void usrp_e100_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); switch(key.as()){ diff --git a/host/lib/usrp/usrp_e100/fpga-downloader.cc b/host/lib/usrp/usrp_e100/fpga-downloader.cc index 4dc537919..4a3d3b9af 100644 --- a/host/lib/usrp/usrp_e100/fpga-downloader.cc +++ b/host/lib/usrp/usrp_e100/fpga-downloader.cc @@ -253,7 +253,7 @@ int main(int argc, char *argv[]) } */ -void usrp_e_load_fpga(const std::string &bin_file){ +void usrp_e100_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); diff --git a/host/lib/usrp/usrp_e100/io_impl.cpp b/host/lib/usrp/usrp_e100/io_impl.cpp index e863944e8..7cb3e25e5 100644 --- a/host/lib/usrp/usrp_e100/io_impl.cpp +++ b/host/lib/usrp/usrp_e100/io_impl.cpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" +#include "usrp_e100_impl.hpp" +#include "usrp_e100_regs.hpp" #include #include #include @@ -30,7 +30,7 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; -zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); +zero_copy_if::sptr usrp_e100_make_mmap_zero_copy(usrp_e100_iface::sptr iface); /*********************************************************************** * Constants @@ -46,14 +46,14 @@ static const bool recv_debug = false; * - thread loop * - vrt packet handler states **********************************************************************/ -struct usrp_e_impl::io_impl{ +struct usrp_e100_impl::io_impl{ //state management for the vrt packet handler code vrt_packet_handler::recv_state packet_handler_recv_state; vrt_packet_handler::send_state packet_handler_send_state; zero_copy_if::sptr data_xport; bool continuous_streaming; - io_impl(usrp_e_iface::sptr iface): - data_xport(usrp_e_make_mmap_zero_copy(iface)), + io_impl(usrp_e100_iface::sptr iface): + data_xport(usrp_e100_make_mmap_zero_copy(iface)), recv_pirate_booty(recv_booty_type::make(data_xport->get_num_recv_frames())), async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) { @@ -73,7 +73,7 @@ struct usrp_e_impl::io_impl{ } //a pirate's life is the life for me! - void recv_pirate_loop(usrp_e_clock_ctrl::sptr); + void recv_pirate_loop(usrp_e100_clock_ctrl::sptr); typedef bounded_buffer recv_booty_type; recv_booty_type::sptr recv_pirate_booty; bounded_buffer::sptr async_msg_fifo; @@ -86,7 +86,7 @@ struct usrp_e_impl::io_impl{ * - while raiding, loot for recv buffers * - put booty into the alignment buffer **********************************************************************/ -void usrp_e_impl::io_impl::recv_pirate_loop(usrp_e_clock_ctrl::sptr clock_ctrl) +void usrp_e100_impl::io_impl::recv_pirate_loop(usrp_e100_clock_ctrl::sptr clock_ctrl) { set_thread_priority_safe(); recv_pirate_crew_raiding = true; @@ -140,7 +140,7 @@ void usrp_e_impl::io_impl::recv_pirate_loop(usrp_e_clock_ctrl::sptr clock_ctrl) /*********************************************************************** * Helper Functions **********************************************************************/ -void usrp_e_impl::io_init(void){ +void usrp_e100_impl::io_init(void){ //setup otw types _send_otw_type.width = 16; _send_otw_type.shift = 0; @@ -172,11 +172,11 @@ void usrp_e_impl::io_init(void){ //spawn a pirate, yarrr! _io_impl->recv_pirate_crew.create_thread(boost::bind( - &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl + &usrp_e100_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl )); } -void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ +void usrp_e100_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ _io_impl->continuous_streaming = (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS); _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, dsp_type1::calc_stream_cmd_word( stream_cmd, get_max_recv_samps_per_packet() @@ -185,7 +185,7 @@ void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); } -void usrp_e_impl::handle_overrun(size_t){ +void usrp_e100_impl::handle_overrun(size_t){ std::cerr << "O"; //the famous OOOOOOOOOOO _iface->poke32(UE_REG_CTRL_RX_CLEAR_OVERRUN, 0); if (_io_impl->continuous_streaming){ @@ -205,7 +205,7 @@ bool get_send_buffs( return buffs[0].get() != NULL; } -size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ +size_t usrp_e100_impl::get_max_send_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - sizeof(vrt::if_packet_info_t().cid) //no class id ever used @@ -214,7 +214,7 @@ size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ return bpp/_send_otw_type.get_sample_size(); } -size_t usrp_e_impl::send( +size_t usrp_e100_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, send_mode_t send_mode, double timeout @@ -234,7 +234,7 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ -size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ +size_t usrp_e100_impl::get_max_recv_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer @@ -244,7 +244,7 @@ size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ return bpp/_recv_otw_type.get_sample_size(); } -size_t usrp_e_impl::recv( +size_t usrp_e100_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, double timeout @@ -256,15 +256,15 @@ size_t usrp_e_impl::recv( io_type, _recv_otw_type, //input and output types to convert _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, - boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), - boost::bind(&usrp_e_impl::handle_overrun, this, _1) + boost::bind(&usrp_e100_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), + boost::bind(&usrp_e100_impl::handle_overrun, this, _1) ); } /*********************************************************************** * Async Recv **********************************************************************/ -bool usrp_e_impl::recv_async_msg( +bool usrp_e100_impl::recv_async_msg( async_metadata_t &async_metadata, double timeout ){ boost::this_thread::disable_interruption di; //disable because the wait can throw diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index f0118aa4b..2d5d028e6 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" +#include "usrp_e100_impl.hpp" +#include "usrp_e100_regs.hpp" #include #include #include @@ -30,10 +30,10 @@ using namespace uhd::usrp; /*********************************************************************** * Mboard Initialization **********************************************************************/ -void usrp_e_impl::mboard_init(void){ +void usrp_e100_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) + boost::bind(&usrp_e100_impl::mboard_get, this, _1, _2), + boost::bind(&usrp_e100_impl::mboard_set, this, _1, _2) ); //init the clock config @@ -46,7 +46,7 @@ void usrp_e_impl::mboard_init(void){ /*********************************************************************** * Mboard Get **********************************************************************/ -void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::mboard_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key @@ -114,7 +114,7 @@ void usrp_e_impl::mboard_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * Mboard Set **********************************************************************/ -void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ +void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp new file mode 100644 index 000000000..ad623777e --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp @@ -0,0 +1,194 @@ +// +// 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 . +// + +#include "usrp_e100_iface.hpp" +#include +#include //ioctl +#include //open, close +#include //ioctl structures and constants +#include +#include //mutex +#include + +using namespace uhd; + +class usrp_e100_iface_impl : public usrp_e100_iface{ +public: + + int get_file_descriptor(void){ + return _node_fd; + } + + /******************************************************************* + * Structors + ******************************************************************/ + usrp_e100_iface_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 + )); + } + } + + ~usrp_e100_iface_impl(void){ + //close the device node file descriptor + ::close(_node_fd); + } + + /******************************************************************* + * IOCTL: provides the communication base for all other calls + ******************************************************************/ + void ioctl(int request, void *mem){ + boost::mutex::scoped_lock lock(_ctrl_mutex); + + if (::ioctl(_node_fd, request, mem) < 0){ + throw std::runtime_error(str( + boost::format("ioctl failed with request %d") % request + )); + } + } + + /******************************************************************* + * Peek and Poke + ******************************************************************/ + void 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 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 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 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]; + } + + /******************************************************************* + * I2C + ******************************************************************/ + static const size_t max_i2c_data_bytes = 10; + + void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ + //allocate some memory for this transaction + UHD_ASSERT_THROW(bytes.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(mem); + data->addr = addr; + data->len = bytes.size(); + std::copy(bytes.begin(), bytes.end(), data->data); + + //call the spi ioctl + this->ioctl(USRP_E_I2C_WRITE, data); + } + + byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ + //allocate some memory for this transaction + UHD_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(mem); + data->addr = addr; + data->len = num_bytes; + + //call the spi ioctl + this->ioctl(USRP_E_I2C_READ, data); + + //unload the data + byte_vector_t bytes(data->len); + UHD_ASSERT_THROW(bytes.size() == num_bytes); + std::copy(data->data, data->data+bytes.size(), bytes.begin()); + return bytes; + } + + /******************************************************************* + * SPI + ******************************************************************/ + boost::uint32_t transact_spi( + int which_slave, + const spi_config_t &config, + boost::uint32_t bits, + size_t num_bits, + bool readback + ){ + //load data struct + usrp_e_spi data; + data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; + data.slave = which_slave; + data.length = num_bits; + data.data = bits; + + //load the flags + data.flags = 0; + data.flags |= (config.miso_edge == spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; + data.flags |= (config.mosi_edge == spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; + + //call the spi ioctl + this->ioctl(USRP_E_SPI, &data); + + //unload the data + return data.data; + } + +private: + int _node_fd; + boost::mutex _ctrl_mutex; +}; + +/*********************************************************************** + * Public Make Function + **********************************************************************/ +usrp_e100_iface::sptr usrp_e100_iface::make(const std::string &node){ + return sptr(new usrp_e100_iface_impl(node)); +} diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp new file mode 100644 index 000000000..b52209a42 --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp @@ -0,0 +1,112 @@ +// +// 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 . +// + +#ifndef INCLUDED_USRP_E100_IFACE_HPP +#define INCLUDED_USRP_E100_IFACE_HPP + +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////// +// I2C addresses +//////////////////////////////////////////////////////////////////////// +#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx +#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) +#define I2C_ADDR_TX_DB (I2C_DEV_EEPROM | 0x4) +#define I2C_ADDR_RX_DB (I2C_DEV_EEPROM | 0x5) +//////////////////////////////////////////////////////////////////////// + +/*! + * The usrp-e interface class: + * Provides a set of functions to implementation layer. + * Including spi, peek, poke, control... + */ +class usrp_e100_iface : boost::noncopyable, public uhd::i2c_iface{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new usrp-e interface with the control transport. + * \param node the device node name + * \return a new usrp-e interface object + */ + static sptr make(const std::string &node); + + /*! + * Get the underlying file descriptor. + * \return the file descriptor + */ + virtual int get_file_descriptor(void) = 0; + + /*! + * 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 + */ + virtual void ioctl(int request, void *mem) = 0; + + /*! + * Write a register (32 bits) + * \param addr the address + * \param data the 32bit data + */ + virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; + + /*! + * Read a register (32 bits) + * \param addr the address + * \return the 32bit data + */ + virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; + + /*! + * Write a register (16 bits) + * \param addr the address + * \param data the 16bit data + */ + virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; + + /*! + * Read a register (16 bits) + * \param addr the address + * \return the 16bit data + */ + virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; + + /*! + * Perform an spi transaction. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write + * \param num_bits how many bits in data + * \param readback true to readback a value + * \return spi data if readback set + */ + virtual boost::uint32_t transact_spi( + int which_slave, + const uhd::spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ) = 0; +}; + +#endif /* INCLUDED_USRP_E100_IFACE_HPP */ diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp new file mode 100644 index 000000000..73cb1f285 --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -0,0 +1,201 @@ +// +// 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 . +// + +#include "usrp_e100_impl.hpp" +#include "usrp_e100_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +namespace fs = boost::filesystem; + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static std::string abs_path(const std::string &file_path){ + return fs::system_complete(fs::path(file_path)).file_string(); +} + +/*********************************************************************** + * Discovery + **********************************************************************/ +static device_addrs_t usrp_e100_find(const device_addr_t &hint){ + device_addrs_t usrp_e100_addrs; + + //return an empty list of addresses when type is set to non-usrp-e + if (hint.has_key("type") and hint["type"] != "usrp-e") return usrp_e100_addrs; + + //device node not provided, assume its 0 + if (not hint.has_key("node")){ + device_addr_t new_addr = hint; + new_addr["node"] = "/dev/usrp_e1000"; + return usrp_e100_find(new_addr); + } + + //use the given device node name + if (fs::exists(hint["node"])){ + device_addr_t new_addr; + new_addr["type"] = "usrp-e"; + new_addr["node"] = abs_path(hint["node"]); + usrp_e100_addrs.push_back(new_addr); + } + + return usrp_e100_addrs; +} + +/*********************************************************************** + * Make + **********************************************************************/ +static device::sptr usrp_e100_make(const device_addr_t &device_addr){ + + //setup the main interface into fpga + std::string node = device_addr["node"]; + std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; + usrp_e100_iface::sptr iface = usrp_e100_iface::make(node); + + //------------------------------------------------------------------ + //-- Handle the FPGA loading... + //-- The image can be confimed as already loaded when: + //-- 1) The compatibility number matches. + //-- 2) The hash in the hash-file matches. + //------------------------------------------------------------------ + static const char *hash_file_path = "/tmp/usrp_e100100_hash"; + + //extract the fpga path for usrp-e + std::string usrp_e100_fpga_image = find_image_path( + device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100100_fpga.bin" + ); + + //calculate a hash of the fpga file + size_t fpga_hash = 0; + { + std::ifstream file(usrp_e100_fpga_image.c_str()); + if (not file.good()) throw std::runtime_error( + "cannot open fpga file for read: " + usrp_e100_fpga_image + ); + do{ + boost::hash_combine(fpga_hash, file.get()); + } while (file.good()); + file.close(); + } + + //read the compatibility number + boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + + //read the hash in the hash-file + size_t loaded_hash = 0; + try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} + + //if not loaded: load the fpga image and write the hash-file + if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ + iface.reset(); + usrp_e100_load_fpga(usrp_e100_fpga_image); + std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl; + iface = usrp_e100_iface::make(node); + try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} + } + + //check that the compatibility is correct + fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + if (fpga_compat_num != USRP_E_COMPAT_NUM){ + throw std::runtime_error(str(boost::format( + "Expected fpga compatibility number 0x%x, but got 0x%x:\n" + "The fpga build is not compatible with the host code build." + ) % USRP_E_COMPAT_NUM % fpga_compat_num)); + } + + return device::sptr(new usrp_e100_impl(iface)); +} + +UHD_STATIC_BLOCK(register_usrp_e100_device){ + device::register_device(&usrp_e100_find, &usrp_e100_make); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp_e100_impl::usrp_e100_impl(usrp_e100_iface::sptr iface): _iface(iface){ + + //setup interfaces into hardware + _clock_ctrl = usrp_e100_clock_ctrl::make(_iface); + _codec_ctrl = usrp_e100_codec_ctrl::make(_iface); + + //initialize the mboard + mboard_init(); + + //initialize the dboards + dboard_init(); + + //initialize the dsps + rx_ddc_init(); + tx_duc_init(); + + //init the codec properties + codec_init(); + + //init the io send/recv + io_init(); + + //set default subdev specs + this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t()); + this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t()); +} + +usrp_e100_impl::~usrp_e100_impl(void){ + /* NOP */ +} + +/*********************************************************************** + * Device Get + **********************************************************************/ +void usrp_e100_impl::get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case DEVICE_PROP_NAME: + val = std::string("usrp-e device"); + return; + + case DEVICE_PROP_MBOARD: + UHD_ASSERT_THROW(key.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; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +/*********************************************************************** + * Device Set + **********************************************************************/ +void usrp_e100_impl::set(const wax::obj &, const wax::obj &){ + UHD_THROW_PROP_SET_ERROR(); +} diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp new file mode 100644 index 000000000..fe60ac0be --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp @@ -0,0 +1,164 @@ +// +// 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 . +// + +#include "usrp_e100_iface.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef INCLUDED_USRP_E100_IMPL_HPP +#define INCLUDED_USRP_E100_IMPL_HPP + +static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; + +//! load an fpga image from a bin file into the usrp-e fpga +extern void usrp_e100_load_fpga(const std::string &bin_file); + +/*! + * Make a usrp-e dboard interface. + * \param iface the usrp-e interface object + * \param clock the clock control interface + * \param codec the codec control interface + * \return a sptr to a new dboard interface + */ +uhd::usrp::dboard_iface::sptr make_usrp_e100_dboard_iface( + usrp_e100_iface::sptr iface, + usrp_e100_clock_ctrl::sptr clock, + usrp_e100_codec_ctrl::sptr codec +); + +/*! + * 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 get_t; + typedef boost::function set_t; + typedef boost::shared_ptr sptr; + + static sptr make(const get_t &get, const set_t &set){ + return sptr(new wax_obj_proxy(get, set)); + } + +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);} +}; + +/*! + * USRP-E100 implementation guts: + * The implementation details are encapsulated here. + * Handles properties on the mboard, dboard, dsps... + */ +class usrp_e100_impl : public uhd::device{ +public: + //structors + usrp_e100_impl(usrp_e100_iface::sptr); + ~usrp_e100_impl(void); + + //the io interface + size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); + size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); + bool recv_async_msg(uhd::async_metadata_t &, double); + size_t get_max_send_samps_per_packet(void) const; + size_t get_max_recv_samps_per_packet(void) const; + +private: + //interface to ioctls and file descriptor + usrp_e100_iface::sptr _iface; + + //handle io stuff + UHD_PIMPL_DECL(io_impl) _io_impl; + uhd::otw_type_t _send_otw_type, _recv_otw_type; + void io_init(void); + void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); + void handle_overrun(size_t); + + //configuration shadows + uhd::clock_config_t _clock_config; + //TODO otw type recv/send + + //ad9522 clock control + usrp_e100_clock_ctrl::sptr _clock_ctrl; + + //ad9862 codec control + usrp_e100_codec_ctrl::sptr _codec_ctrl; + + //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; + uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; + + //xx dboard functions and settings + void dboard_init(void); + uhd::usrp::dboard_manager::sptr _dboard_manager; + uhd::usrp::dboard_iface::sptr _dboard_iface; + + //rx dboard functions and settings + uhd::usrp::dboard_eeprom_t _rx_db_eeprom; + 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 + uhd::usrp::dboard_eeprom_t _tx_db_eeprom; + 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 &); + double _ddc_freq; size_t _ddc_decim; + 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 &); + double _duc_freq; size_t _duc_interp; + wax_obj_proxy::sptr _tx_duc_proxy; + + //codec functions and settings + void codec_init(void); + void rx_codec_get(const wax::obj &, wax::obj &); + void rx_codec_set(const wax::obj &, const wax::obj &); + void tx_codec_get(const wax::obj &, wax::obj &); + void tx_codec_set(const wax::obj &, const wax::obj &); + wax_obj_proxy::sptr _rx_codec_proxy, _tx_codec_proxy; +}; + +#endif /* INCLUDED_USRP_E100_IMPL_HPP */ diff --git a/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp new file mode 100644 index 000000000..bf378a9b1 --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp @@ -0,0 +1,215 @@ +// +// 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 . +// + +#include "usrp_e100_iface.hpp" +#include +#include +#include +#include //mmap +#include //getpagesize +#include //poll +#include +#include +#include + +using namespace uhd; +using namespace uhd::transport; + +static const bool fp_verbose = false; //fast-path verbose +static const bool sp_verbose = false; //slow-path verbose +static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout + +/*********************************************************************** + * The zero copy interface implementation + **********************************************************************/ +class usrp_e100_mmap_zero_copy_impl : public zero_copy_if, public boost::enable_shared_from_this { +public: + usrp_e100_mmap_zero_copy_impl(usrp_e100_iface::sptr iface): + _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) + { + //get system sizes + iface->ioctl(USRP_E_GET_RB_INFO, &_rb_size); + size_t page_size = getpagesize(); + _frame_size = page_size/2; + + //calculate the memory size + _map_size = + (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + + (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; + + //print sizes summary + if (sp_verbose){ + std::cout << "page_size: " << page_size << std::endl; + std::cout << "frame_size: " << _frame_size << std::endl; + std::cout << "num_pages_rx_flags: " << _rb_size.num_pages_rx_flags << std::endl; + std::cout << "num_rx_frames: " << _rb_size.num_rx_frames << std::endl; + std::cout << "num_pages_tx_flags: " << _rb_size.num_pages_tx_flags << std::endl; + std::cout << "num_tx_frames: " << _rb_size.num_tx_frames << std::endl; + std::cout << "map_size: " << _map_size << std::endl; + } + + //call mmap to get the memory + _mapped_mem = ::mmap( + NULL, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 + ); + UHD_ASSERT_THROW(_mapped_mem != MAP_FAILED); + + //calculate the memory offsets for info and buffers + size_t recv_info_off = 0; + size_t recv_buff_off = recv_info_off + (_rb_size.num_pages_rx_flags * page_size); + size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); + size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); + + //print offset summary + if (sp_verbose){ + std::cout << "recv_info_off: " << recv_info_off << std::endl; + std::cout << "recv_buff_off: " << recv_buff_off << std::endl; + std::cout << "send_info_off: " << send_info_off << std::endl; + std::cout << "send_buff_off: " << send_buff_off << std::endl; + } + + //set the internal pointers for info and buffers + typedef ring_buffer_info (*rbi_pta)[]; + char *rb_ptr = reinterpret_cast(_mapped_mem); + _recv_info = reinterpret_cast(rb_ptr + recv_info_off); + _recv_buff = rb_ptr + recv_buff_off; + _send_info = reinterpret_cast(rb_ptr + send_info_off); + _send_buff = rb_ptr + send_buff_off; + } + + ~usrp_e100_mmap_zero_copy_impl(void){ + if (sp_verbose) std::cout << "cleanup: munmap" << std::endl; + ::munmap(_mapped_mem, _map_size); + } + + managed_recv_buffer::sptr get_recv_buff(double timeout){ + if (fp_verbose) std::cout << "get_recv_buff: " << _recv_index << std::endl; + + //grab pointers to the info and buffer + ring_buffer_info *info = (*_recv_info) + _recv_index; + void *mem = _recv_buff + _frame_size*_recv_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_USER)){ + for (size_t i = 0; i < poll_breakout; i++){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLIN; + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3/poll_breakout)); + if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; + if (poll_ret > 0) goto found_user_frame; //good poll, continue on + } + return managed_recv_buffer::sptr(); //timed-out for real + } found_user_frame: + + //the process has claimed the frame + info->flags = RB_USER_PROCESS; + + //increment the index for the next call + if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; + + //return the managed buffer for this frame + if (fp_verbose) std::cout << " make_recv_buff: " << info->len << std::endl; + return managed_recv_buffer::make_safe( + boost::asio::const_buffer(mem, info->len), + boost::bind(&usrp_e100_mmap_zero_copy_impl::release, shared_from_this(), info) + ); + } + + size_t get_num_recv_frames(void) const{ + return _rb_size.num_rx_frames; + } + + size_t get_recv_frame_size(void) const{ + return _frame_size; + } + + managed_send_buffer::sptr get_send_buff(double timeout){ + if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; + + //grab pointers to the info and buffer + ring_buffer_info *info = (*_send_info) + _send_index; + void *mem = _send_buff + _frame_size*_send_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_KERNEL)){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLOUT; + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); + if (fp_verbose) std::cout << " POLLOUT: " << poll_ret << std::endl; + if (poll_ret <= 0) return managed_send_buffer::sptr(); + } + + //increment the index for the next call + if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; + + //return the managed buffer for this frame + if (fp_verbose) std::cout << " make_send_buff: " << _frame_size << std::endl; + return managed_send_buffer::make_safe( + boost::asio::mutable_buffer(mem, _frame_size), + boost::bind(&usrp_e100_mmap_zero_copy_impl::commit, shared_from_this(), info, _1) + ); + } + + size_t get_num_send_frames(void) const{ + return _rb_size.num_tx_frames; + } + + size_t get_send_frame_size(void) const{ + return _frame_size; + } + +private: + + void release(ring_buffer_info *info){ + if (fp_verbose) std::cout << "recv buff: release" << std::endl; + info->flags = RB_KERNEL; + } + + void commit(ring_buffer_info *info, size_t len){ + if (fp_verbose) std::cout << "send buff: commit " << len << std::endl; + info->len = len; + info->flags = RB_USER; + if (::write(_fd, NULL, 0) < 0){ + std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl; + } + } + + int _fd; + + //the mapped memory itself + void *_mapped_mem; + + //mapped memory sizes + usrp_e_ring_buffer_size_t _rb_size; + size_t _frame_size, _map_size; + + //pointers to sections in the mapped memory + ring_buffer_info (*_recv_info)[], (*_send_info)[]; + char *_recv_buff, *_send_buff; + + //indexes into sub-sections of mapped memory + size_t _recv_index, _send_index; +}; + +/*********************************************************************** + * The zero copy interface make function + **********************************************************************/ +zero_copy_if::sptr usrp_e100_make_mmap_zero_copy(usrp_e100_iface::sptr iface){ + return zero_copy_if::sptr(new usrp_e100_mmap_zero_copy_impl(iface)); +} diff --git a/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp new file mode 100644 index 000000000..625fb2c35 --- /dev/null +++ b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp @@ -0,0 +1,198 @@ + + +//////////////////////////////////////////////////////////////// +// +// 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 INCLUDED_USRP_E100_REGS_HPP +#define INCLUDED_USRP_E100_REGS_HPP + +///////////////////////////////////////////////////// +// Slave pointers + +#define UE_REG_SLAVE(n) ((n)<<7) +#define UE_REG_SR_ADDR(n) ((UE_REG_SLAVE(5)) + (4*(n))) + +///////////////////////////////////////////////////// +// 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 +#define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 +#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 +#define UE_REG_MISC_XFER_RATE UE_REG_MISC_BASE + 14 +#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 16 + +///////////////////////////////////////////////////// +// 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) + +//spi slave constants +#define UE_SPI_SS_AD9522 (1 << 3) +#define UE_SPI_SS_AD9862 (1 << 2) +#define UE_SPI_SS_TX_DB (1 << 1) +#define UE_SPI_SS_RX_DB (1 << 0) + +//////////////////////////////////////////////// +// 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 + +//possible bit values for sel when dbg is 0: +#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 + +//possible bit values for sel when dbg is 1: +#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 + +///////////////////////////////////////////////// +// DSP RX Regs +//////////////////////////////////////////////// +#define UE_REG_DSP_RX_FREQ UE_REG_SR_ADDR(0) +#define UE_REG_DSP_RX_SCALE_IQ UE_REG_SR_ADDR(1) // {scale_i,scale_q} +#define UE_REG_DSP_RX_DECIM_RATE UE_REG_SR_ADDR(2) // hb and decim rate +#define UE_REG_DSP_RX_DCOFFSET_I UE_REG_SR_ADDR(3) // Bit 31 high sets fixed offset mode, using lower 14 bits, // otherwise it is automatic +#define UE_REG_DSP_RX_DCOFFSET_Q UE_REG_SR_ADDR(4) // Bit 31 high sets fixed offset mode, using lower 14 bits +#define UE_REG_DSP_RX_MUX UE_REG_SR_ADDR(5) + +/////////////////////////////////////////////////// +// VITA RX CTRL regs +/////////////////////////////////////////////////// +// The following 3 are logically a single command register. +// They are clocked into the underlying fifo when time_ticks is written. +#define UE_REG_CTRL_RX_STREAM_CMD UE_REG_SR_ADDR(8) // {now, chain, num_samples(30) +#define UE_REG_CTRL_RX_TIME_SECS UE_REG_SR_ADDR(9) +#define UE_REG_CTRL_RX_TIME_TICKS UE_REG_SR_ADDR(10) +#define UE_REG_CTRL_RX_CLEAR_OVERRUN UE_REG_SR_ADDR(11) // write anything to clear overrun +#define UE_REG_CTRL_RX_VRT_HEADER UE_REG_SR_ADDR(12) // word 0 of packet. FPGA fills in packet counter +#define UE_REG_CTRL_RX_VRT_STREAM_ID UE_REG_SR_ADDR(13) // word 1 of packet. +#define UE_REG_CTRL_RX_VRT_TRAILER UE_REG_SR_ADDR(14) +#define UE_REG_CTRL_RX_NSAMPS_PER_PKT UE_REG_SR_ADDR(15) +#define UE_REG_CTRL_RX_NCHANNELS UE_REG_SR_ADDR(16) // 1 in basic case, up to 4 for vector sources + +///////////////////////////////////////////////// +// DSP TX Regs +//////////////////////////////////////////////// +#define UE_REG_DSP_TX_FREQ UE_REG_SR_ADDR(17) +#define UE_REG_DSP_TX_SCALE_IQ UE_REG_SR_ADDR(18) // {scale_i,scale_q} +#define UE_REG_DSP_TX_INTERP_RATE UE_REG_SR_ADDR(19) +#define UE_REG_DSP_TX_UNUSED UE_REG_SR_ADDR(20) +#define UE_REG_DSP_TX_MUX UE_REG_SR_ADDR(21) + +///////////////////////////////////////////////// +// VITA TX CTRL regs +//////////////////////////////////////////////// +#define UE_REG_CTRL_TX_NCHANNELS UE_REG_SR_ADDR(24) +#define UE_REG_CTRL_TX_CLEAR_UNDERRUN UE_REG_SR_ADDR(25) +#define UE_REG_CTRL_TX_REPORT_SID UE_REG_SR_ADDR(26) +#define UE_REG_CTRL_TX_POLICY UE_REG_SR_ADDR(27) + +#define UE_FLAG_CTRL_TX_POLICY_WAIT (0x1 << 0) +#define UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET (0x1 << 1) +#define UE_FLAG_CTRL_TX_POLICY_NEXT_BURST (0x1 << 2) + +///////////////////////////////////////////////// +// VITA49 64 bit time (write only) +//////////////////////////////////////////////// + /*! + * \brief Time 64 flags + * + *
+   *
+   *    3                   2                   1
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-----------------------------------------------------------+-+-+
+   * |                                                           |S|P|
+   * +-----------------------------------------------------------+-+-+
+   *
+   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
+   * S - Source (0=sma, 1=mimo, 0=default)
+   *
+   * 
+ */ +#define UE_REG_TIME64_SECS UE_REG_SR_ADDR(28) // value to set absolute secs to on next PPS +#define UE_REG_TIME64_TICKS UE_REG_SR_ADDR(29) // value to set absolute ticks to on next PPS +#define UE_REG_TIME64_FLAGS UE_REG_SR_ADDR(30) // flags - see chart above +#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0) +#define UE_REG_TIME64_TPS UE_REG_SR_ADDR(31) // clock ticks per second (counter rollover) + +//pps flags (see above) +#define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0) +#define UE_FLAG_TIME64_PPS_POSEDGE (1 << 0) +#define UE_FLAG_TIME64_PPS_SMA (0 << 1) +#define UE_FLAG_TIME64_PPS_MIMO (1 << 1) + +#define UE_FLAG_TIME64_LATCH_NOW 1 +#define UE_FLAG_TIME64_LATCH_NEXT_PPS 0 + +#endif + diff --git a/host/lib/usrp/usrp_e100/usrp_e_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e_iface.cpp deleted file mode 100644 index f00e92946..000000000 --- a/host/lib/usrp/usrp_e100/usrp_e_iface.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_iface.hpp" -#include -#include //ioctl -#include //open, close -#include //ioctl structures and constants -#include -#include //mutex -#include - -using namespace uhd; - -class usrp_e_iface_impl : public usrp_e_iface{ -public: - - int get_file_descriptor(void){ - return _node_fd; - } - - /******************************************************************* - * Structors - ******************************************************************/ - usrp_e_iface_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 - )); - } - } - - ~usrp_e_iface_impl(void){ - //close the device node file descriptor - ::close(_node_fd); - } - - /******************************************************************* - * IOCTL: provides the communication base for all other calls - ******************************************************************/ - void ioctl(int request, void *mem){ - boost::mutex::scoped_lock lock(_ctrl_mutex); - - if (::ioctl(_node_fd, request, mem) < 0){ - throw std::runtime_error(str( - boost::format("ioctl failed with request %d") % request - )); - } - } - - /******************************************************************* - * Peek and Poke - ******************************************************************/ - void 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 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 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 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]; - } - - /******************************************************************* - * I2C - ******************************************************************/ - static const size_t max_i2c_data_bytes = 10; - - void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ - //allocate some memory for this transaction - UHD_ASSERT_THROW(bytes.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(mem); - data->addr = addr; - data->len = bytes.size(); - std::copy(bytes.begin(), bytes.end(), data->data); - - //call the spi ioctl - this->ioctl(USRP_E_I2C_WRITE, data); - } - - byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ - //allocate some memory for this transaction - UHD_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(mem); - data->addr = addr; - data->len = num_bytes; - - //call the spi ioctl - this->ioctl(USRP_E_I2C_READ, data); - - //unload the data - byte_vector_t bytes(data->len); - UHD_ASSERT_THROW(bytes.size() == num_bytes); - std::copy(data->data, data->data+bytes.size(), bytes.begin()); - return bytes; - } - - /******************************************************************* - * SPI - ******************************************************************/ - boost::uint32_t transact_spi( - int which_slave, - const spi_config_t &config, - boost::uint32_t bits, - size_t num_bits, - bool readback - ){ - //load data struct - usrp_e_spi data; - data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; - data.slave = which_slave; - data.length = num_bits; - data.data = bits; - - //load the flags - data.flags = 0; - data.flags |= (config.miso_edge == spi_config_t::EDGE_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; - data.flags |= (config.mosi_edge == spi_config_t::EDGE_RISE)? UE_SPI_PUSH_FALL : UE_SPI_PUSH_RISE; - - //call the spi ioctl - this->ioctl(USRP_E_SPI, &data); - - //unload the data - return data.data; - } - -private: - int _node_fd; - boost::mutex _ctrl_mutex; -}; - -/*********************************************************************** - * Public Make Function - **********************************************************************/ -usrp_e_iface::sptr usrp_e_iface::make(const std::string &node){ - return sptr(new usrp_e_iface_impl(node)); -} diff --git a/host/lib/usrp/usrp_e100/usrp_e_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e_iface.hpp deleted file mode 100644 index 59aac43d9..000000000 --- a/host/lib/usrp/usrp_e100/usrp_e_iface.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_USRP_E_IFACE_HPP -#define INCLUDED_USRP_E_IFACE_HPP - -#include -#include -#include -#include -#include - -//////////////////////////////////////////////////////////////////////// -// I2C addresses -//////////////////////////////////////////////////////////////////////// -#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx -#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) -#define I2C_ADDR_TX_DB (I2C_DEV_EEPROM | 0x4) -#define I2C_ADDR_RX_DB (I2C_DEV_EEPROM | 0x5) -//////////////////////////////////////////////////////////////////////// - -/*! - * The usrp-e interface class: - * Provides a set of functions to implementation layer. - * Including spi, peek, poke, control... - */ -class usrp_e_iface : boost::noncopyable, public uhd::i2c_iface{ -public: - typedef boost::shared_ptr sptr; - - /*! - * Make a new usrp-e interface with the control transport. - * \param node the device node name - * \return a new usrp-e interface object - */ - static sptr make(const std::string &node); - - /*! - * Get the underlying file descriptor. - * \return the file descriptor - */ - virtual int get_file_descriptor(void) = 0; - - /*! - * 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 - */ - virtual void ioctl(int request, void *mem) = 0; - - /*! - * Write a register (32 bits) - * \param addr the address - * \param data the 32bit data - */ - virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; - - /*! - * Read a register (32 bits) - * \param addr the address - * \return the 32bit data - */ - virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; - - /*! - * Write a register (16 bits) - * \param addr the address - * \param data the 16bit data - */ - virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; - - /*! - * Read a register (16 bits) - * \param addr the address - * \return the 16bit data - */ - virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; - - /*! - * Perform an spi transaction. - * \param which_slave the slave device number - * \param config spi config args - * \param data the bits to write - * \param num_bits how many bits in data - * \param readback true to readback a value - * \return spi data if readback set - */ - virtual boost::uint32_t transact_spi( - int which_slave, - const uhd::spi_config_t &config, - boost::uint32_t data, - size_t num_bits, - bool readback - ) = 0; -}; - -#endif /* INCLUDED_USRP_E_IFACE_HPP */ diff --git a/host/lib/usrp/usrp_e100/usrp_e_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e_impl.cpp deleted file mode 100644 index 70cc399fb..000000000 --- a/host/lib/usrp/usrp_e100/usrp_e_impl.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_impl.hpp" -#include "usrp_e_regs.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; -namespace fs = boost::filesystem; - -/*********************************************************************** - * Helper Functions - **********************************************************************/ -static std::string abs_path(const std::string &file_path){ - return fs::system_complete(fs::path(file_path)).file_string(); -} - -/*********************************************************************** - * Discovery - **********************************************************************/ -static device_addrs_t usrp_e_find(const device_addr_t &hint){ - device_addrs_t usrp_e_addrs; - - //return an empty list of addresses when type is set to non-usrp-e - if (hint.has_key("type") and hint["type"] != "usrp-e") return usrp_e_addrs; - - //device node not provided, assume its 0 - if (not hint.has_key("node")){ - device_addr_t new_addr = hint; - new_addr["node"] = "/dev/usrp_e0"; - return usrp_e_find(new_addr); - } - - //use the given device node name - if (fs::exists(hint["node"])){ - device_addr_t new_addr; - new_addr["type"] = "usrp-e"; - new_addr["node"] = abs_path(hint["node"]); - usrp_e_addrs.push_back(new_addr); - } - - return usrp_e_addrs; -} - -/*********************************************************************** - * Make - **********************************************************************/ -static device::sptr usrp_e_make(const device_addr_t &device_addr){ - - //setup the main interface into fpga - std::string node = device_addr["node"]; - std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; - usrp_e_iface::sptr iface = usrp_e_iface::make(node); - - //------------------------------------------------------------------ - //-- Handle the FPGA loading... - //-- The image can be confimed as already loaded when: - //-- 1) The compatibility number matches. - //-- 2) The hash in the hash-file matches. - //------------------------------------------------------------------ - static const char *hash_file_path = "/tmp/usrp_e100_hash"; - - //extract the fpga path for usrp-e - std::string usrp_e_fpga_image = find_image_path( - device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" - ); - - //calculate a hash of the fpga file - size_t fpga_hash = 0; - { - std::ifstream file(usrp_e_fpga_image.c_str()); - if (not file.good()) throw std::runtime_error( - "cannot open fpga file for read: " + usrp_e_fpga_image - ); - do{ - boost::hash_combine(fpga_hash, file.get()); - } while (file.good()); - file.close(); - } - - //read the compatibility number - boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); - - //read the hash in the hash-file - size_t loaded_hash = 0; - try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} - - //if not loaded: load the fpga image and write the hash-file - if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ - iface.reset(); - usrp_e_load_fpga(usrp_e_fpga_image); - std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl; - iface = usrp_e_iface::make(node); - try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} - } - - //check that the compatibility is correct - fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); - if (fpga_compat_num != USRP_E_COMPAT_NUM){ - throw std::runtime_error(str(boost::format( - "Expected fpga compatibility number 0x%x, but got 0x%x:\n" - "The fpga build is not compatible with the host code build." - ) % USRP_E_COMPAT_NUM % fpga_compat_num)); - } - - return device::sptr(new usrp_e_impl(iface)); -} - -UHD_STATIC_BLOCK(register_usrp_e_device){ - device::register_device(&usrp_e_find, &usrp_e_make); -} - -/*********************************************************************** - * Structors - **********************************************************************/ -usrp_e_impl::usrp_e_impl(usrp_e_iface::sptr iface): _iface(iface){ - - //setup interfaces into hardware - _clock_ctrl = usrp_e_clock_ctrl::make(_iface); - _codec_ctrl = usrp_e_codec_ctrl::make(_iface); - - //initialize the mboard - mboard_init(); - - //initialize the dboards - dboard_init(); - - //initialize the dsps - rx_ddc_init(); - tx_duc_init(); - - //init the codec properties - codec_init(); - - //init the io send/recv - io_init(); - - //set default subdev specs - this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t()); - this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t()); -} - -usrp_e_impl::~usrp_e_impl(void){ - /* NOP */ -} - -/*********************************************************************** - * Device Get - **********************************************************************/ -void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case DEVICE_PROP_NAME: - val = std::string("usrp-e device"); - return; - - case DEVICE_PROP_MBOARD: - UHD_ASSERT_THROW(key.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; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -/*********************************************************************** - * Device Set - **********************************************************************/ -void usrp_e_impl::set(const wax::obj &, const wax::obj &){ - UHD_THROW_PROP_SET_ERROR(); -} diff --git a/host/lib/usrp/usrp_e100/usrp_e_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e_impl.hpp deleted file mode 100644 index b5f21810d..000000000 --- a/host/lib/usrp/usrp_e100/usrp_e_impl.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_iface.hpp" -#include "clock_ctrl.hpp" -#include "codec_ctrl.hpp" -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef INCLUDED_USRP_E_IMPL_HPP -#define INCLUDED_USRP_E_IMPL_HPP - -static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; - -//! load an fpga image from a bin file into the usrp-e fpga -extern void usrp_e_load_fpga(const std::string &bin_file); - -/*! - * Make a usrp-e dboard interface. - * \param iface the usrp-e interface object - * \param clock the clock control interface - * \param codec the codec control interface - * \return a sptr to a new dboard interface - */ -uhd::usrp::dboard_iface::sptr make_usrp_e_dboard_iface( - usrp_e_iface::sptr iface, - usrp_e_clock_ctrl::sptr clock, - usrp_e_codec_ctrl::sptr codec -); - -/*! - * 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 get_t; - typedef boost::function set_t; - typedef boost::shared_ptr sptr; - - static sptr make(const get_t &get, const set_t &set){ - return sptr(new wax_obj_proxy(get, set)); - } - -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(usrp_e_iface::sptr); - ~usrp_e_impl(void); - - //the io interface - size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); - size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); - bool recv_async_msg(uhd::async_metadata_t &, double); - size_t get_max_send_samps_per_packet(void) const; - size_t get_max_recv_samps_per_packet(void) const; - -private: - //interface to ioctls and file descriptor - usrp_e_iface::sptr _iface; - - //handle io stuff - UHD_PIMPL_DECL(io_impl) _io_impl; - uhd::otw_type_t _send_otw_type, _recv_otw_type; - void io_init(void); - void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); - void handle_overrun(size_t); - - //configuration shadows - uhd::clock_config_t _clock_config; - //TODO otw type recv/send - - //ad9522 clock control - usrp_e_clock_ctrl::sptr _clock_ctrl; - - //ad9862 codec control - usrp_e_codec_ctrl::sptr _codec_ctrl; - - //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; - uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; - - //xx dboard functions and settings - void dboard_init(void); - uhd::usrp::dboard_manager::sptr _dboard_manager; - uhd::usrp::dboard_iface::sptr _dboard_iface; - - //rx dboard functions and settings - uhd::usrp::dboard_eeprom_t _rx_db_eeprom; - 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 - uhd::usrp::dboard_eeprom_t _tx_db_eeprom; - 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 &); - double _ddc_freq; size_t _ddc_decim; - 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 &); - double _duc_freq; size_t _duc_interp; - wax_obj_proxy::sptr _tx_duc_proxy; - - //codec functions and settings - void codec_init(void); - void rx_codec_get(const wax::obj &, wax::obj &); - void rx_codec_set(const wax::obj &, const wax::obj &); - void tx_codec_get(const wax::obj &, wax::obj &); - void tx_codec_set(const wax::obj &, const wax::obj &); - wax_obj_proxy::sptr _rx_codec_proxy, _tx_codec_proxy; -}; - -#endif /* INCLUDED_USRP_E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp deleted file mode 100644 index 274bb043e..000000000 --- a/host/lib/usrp/usrp_e100/usrp_e_mmap_zero_copy.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "usrp_e_iface.hpp" -#include -#include -#include -#include //mmap -#include //getpagesize -#include //poll -#include -#include -#include - -using namespace uhd; -using namespace uhd::transport; - -static const bool fp_verbose = false; //fast-path verbose -static const bool sp_verbose = false; //slow-path verbose -static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout - -/*********************************************************************** - * The zero copy interface implementation - **********************************************************************/ -class usrp_e_mmap_zero_copy_impl : public zero_copy_if, public boost::enable_shared_from_this { -public: - usrp_e_mmap_zero_copy_impl(usrp_e_iface::sptr iface): - _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) - { - //get system sizes - iface->ioctl(USRP_E_GET_RB_INFO, &_rb_size); - size_t page_size = getpagesize(); - _frame_size = page_size/2; - - //calculate the memory size - _map_size = - (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + - (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; - - //print sizes summary - if (sp_verbose){ - std::cout << "page_size: " << page_size << std::endl; - std::cout << "frame_size: " << _frame_size << std::endl; - std::cout << "num_pages_rx_flags: " << _rb_size.num_pages_rx_flags << std::endl; - std::cout << "num_rx_frames: " << _rb_size.num_rx_frames << std::endl; - std::cout << "num_pages_tx_flags: " << _rb_size.num_pages_tx_flags << std::endl; - std::cout << "num_tx_frames: " << _rb_size.num_tx_frames << std::endl; - std::cout << "map_size: " << _map_size << std::endl; - } - - //call mmap to get the memory - _mapped_mem = ::mmap( - NULL, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 - ); - UHD_ASSERT_THROW(_mapped_mem != MAP_FAILED); - - //calculate the memory offsets for info and buffers - size_t recv_info_off = 0; - size_t recv_buff_off = recv_info_off + (_rb_size.num_pages_rx_flags * page_size); - size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); - size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); - - //print offset summary - if (sp_verbose){ - std::cout << "recv_info_off: " << recv_info_off << std::endl; - std::cout << "recv_buff_off: " << recv_buff_off << std::endl; - std::cout << "send_info_off: " << send_info_off << std::endl; - std::cout << "send_buff_off: " << send_buff_off << std::endl; - } - - //set the internal pointers for info and buffers - typedef ring_buffer_info (*rbi_pta)[]; - char *rb_ptr = reinterpret_cast(_mapped_mem); - _recv_info = reinterpret_cast(rb_ptr + recv_info_off); - _recv_buff = rb_ptr + recv_buff_off; - _send_info = reinterpret_cast(rb_ptr + send_info_off); - _send_buff = rb_ptr + send_buff_off; - } - - ~usrp_e_mmap_zero_copy_impl(void){ - if (sp_verbose) std::cout << "cleanup: munmap" << std::endl; - ::munmap(_mapped_mem, _map_size); - } - - managed_recv_buffer::sptr get_recv_buff(double timeout){ - if (fp_verbose) std::cout << "get_recv_buff: " << _recv_index << std::endl; - - //grab pointers to the info and buffer - ring_buffer_info *info = (*_recv_info) + _recv_index; - void *mem = _recv_buff + _frame_size*_recv_index; - - //poll/wait for a ready frame - if (not (info->flags & RB_USER)){ - for (size_t i = 0; i < poll_breakout; i++){ - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLIN; - ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3/poll_breakout)); - if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; - if (poll_ret > 0) goto found_user_frame; //good poll, continue on - } - return managed_recv_buffer::sptr(); //timed-out for real - } found_user_frame: - - //the process has claimed the frame - info->flags = RB_USER_PROCESS; - - //increment the index for the next call - if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; - - //return the managed buffer for this frame - if (fp_verbose) std::cout << " make_recv_buff: " << info->len << std::endl; - return managed_recv_buffer::make_safe( - boost::asio::const_buffer(mem, info->len), - boost::bind(&usrp_e_mmap_zero_copy_impl::release, shared_from_this(), info) - ); - } - - size_t get_num_recv_frames(void) const{ - return _rb_size.num_rx_frames; - } - - size_t get_recv_frame_size(void) const{ - return _frame_size; - } - - managed_send_buffer::sptr get_send_buff(double timeout){ - if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; - - //grab pointers to the info and buffer - ring_buffer_info *info = (*_send_info) + _send_index; - void *mem = _send_buff + _frame_size*_send_index; - - //poll/wait for a ready frame - if (not (info->flags & RB_KERNEL)){ - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLOUT; - ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); - if (fp_verbose) std::cout << " POLLOUT: " << poll_ret << std::endl; - if (poll_ret <= 0) return managed_send_buffer::sptr(); - } - - //increment the index for the next call - if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; - - //return the managed buffer for this frame - if (fp_verbose) std::cout << " make_send_buff: " << _frame_size << std::endl; - return managed_send_buffer::make_safe( - boost::asio::mutable_buffer(mem, _frame_size), - boost::bind(&usrp_e_mmap_zero_copy_impl::commit, shared_from_this(), info, _1) - ); - } - - size_t get_num_send_frames(void) const{ - return _rb_size.num_tx_frames; - } - - size_t get_send_frame_size(void) const{ - return _frame_size; - } - -private: - - void release(ring_buffer_info *info){ - if (fp_verbose) std::cout << "recv buff: release" << std::endl; - info->flags = RB_KERNEL; - } - - void commit(ring_buffer_info *info, size_t len){ - if (fp_verbose) std::cout << "send buff: commit " << len << std::endl; - info->len = len; - info->flags = RB_USER; - if (::write(_fd, NULL, 0) < 0){ - std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl; - } - } - - int _fd; - - //the mapped memory itself - void *_mapped_mem; - - //mapped memory sizes - usrp_e_ring_buffer_size_t _rb_size; - size_t _frame_size, _map_size; - - //pointers to sections in the mapped memory - ring_buffer_info (*_recv_info)[], (*_send_info)[]; - char *_recv_buff, *_send_buff; - - //indexes into sub-sections of mapped memory - size_t _recv_index, _send_index; -}; - -/*********************************************************************** - * The zero copy interface make function - **********************************************************************/ -zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface){ - return zero_copy_if::sptr(new usrp_e_mmap_zero_copy_impl(iface)); -} diff --git a/host/lib/usrp/usrp_e100/usrp_e_regs.hpp b/host/lib/usrp/usrp_e100/usrp_e_regs.hpp deleted file mode 100644 index 8bfb08b6f..000000000 --- a/host/lib/usrp/usrp_e100/usrp_e_regs.hpp +++ /dev/null @@ -1,198 +0,0 @@ - - -//////////////////////////////////////////////////////////////// -// -// 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) -#define UE_REG_SR_ADDR(n) ((UE_REG_SLAVE(5)) + (4*(n))) - -///////////////////////////////////////////////////// -// 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 -#define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 -#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 -#define UE_REG_MISC_XFER_RATE UE_REG_MISC_BASE + 14 -#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 16 - -///////////////////////////////////////////////////// -// 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) - -//spi slave constants -#define UE_SPI_SS_AD9522 (1 << 3) -#define UE_SPI_SS_AD9862 (1 << 2) -#define UE_SPI_SS_TX_DB (1 << 1) -#define UE_SPI_SS_RX_DB (1 << 0) - -//////////////////////////////////////////////// -// 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 - -//possible bit values for sel when dbg is 0: -#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 - -//possible bit values for sel when dbg is 1: -#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 - -///////////////////////////////////////////////// -// DSP RX Regs -//////////////////////////////////////////////// -#define UE_REG_DSP_RX_FREQ UE_REG_SR_ADDR(0) -#define UE_REG_DSP_RX_SCALE_IQ UE_REG_SR_ADDR(1) // {scale_i,scale_q} -#define UE_REG_DSP_RX_DECIM_RATE UE_REG_SR_ADDR(2) // hb and decim rate -#define UE_REG_DSP_RX_DCOFFSET_I UE_REG_SR_ADDR(3) // Bit 31 high sets fixed offset mode, using lower 14 bits, // otherwise it is automatic -#define UE_REG_DSP_RX_DCOFFSET_Q UE_REG_SR_ADDR(4) // Bit 31 high sets fixed offset mode, using lower 14 bits -#define UE_REG_DSP_RX_MUX UE_REG_SR_ADDR(5) - -/////////////////////////////////////////////////// -// VITA RX CTRL regs -/////////////////////////////////////////////////// -// The following 3 are logically a single command register. -// They are clocked into the underlying fifo when time_ticks is written. -#define UE_REG_CTRL_RX_STREAM_CMD UE_REG_SR_ADDR(8) // {now, chain, num_samples(30) -#define UE_REG_CTRL_RX_TIME_SECS UE_REG_SR_ADDR(9) -#define UE_REG_CTRL_RX_TIME_TICKS UE_REG_SR_ADDR(10) -#define UE_REG_CTRL_RX_CLEAR_OVERRUN UE_REG_SR_ADDR(11) // write anything to clear overrun -#define UE_REG_CTRL_RX_VRT_HEADER UE_REG_SR_ADDR(12) // word 0 of packet. FPGA fills in packet counter -#define UE_REG_CTRL_RX_VRT_STREAM_ID UE_REG_SR_ADDR(13) // word 1 of packet. -#define UE_REG_CTRL_RX_VRT_TRAILER UE_REG_SR_ADDR(14) -#define UE_REG_CTRL_RX_NSAMPS_PER_PKT UE_REG_SR_ADDR(15) -#define UE_REG_CTRL_RX_NCHANNELS UE_REG_SR_ADDR(16) // 1 in basic case, up to 4 for vector sources - -///////////////////////////////////////////////// -// DSP TX Regs -//////////////////////////////////////////////// -#define UE_REG_DSP_TX_FREQ UE_REG_SR_ADDR(17) -#define UE_REG_DSP_TX_SCALE_IQ UE_REG_SR_ADDR(18) // {scale_i,scale_q} -#define UE_REG_DSP_TX_INTERP_RATE UE_REG_SR_ADDR(19) -#define UE_REG_DSP_TX_UNUSED UE_REG_SR_ADDR(20) -#define UE_REG_DSP_TX_MUX UE_REG_SR_ADDR(21) - -///////////////////////////////////////////////// -// VITA TX CTRL regs -//////////////////////////////////////////////// -#define UE_REG_CTRL_TX_NCHANNELS UE_REG_SR_ADDR(24) -#define UE_REG_CTRL_TX_CLEAR_UNDERRUN UE_REG_SR_ADDR(25) -#define UE_REG_CTRL_TX_REPORT_SID UE_REG_SR_ADDR(26) -#define UE_REG_CTRL_TX_POLICY UE_REG_SR_ADDR(27) - -#define UE_FLAG_CTRL_TX_POLICY_WAIT (0x1 << 0) -#define UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET (0x1 << 1) -#define UE_FLAG_CTRL_TX_POLICY_NEXT_BURST (0x1 << 2) - -///////////////////////////////////////////////// -// VITA49 64 bit time (write only) -//////////////////////////////////////////////// - /*! - * \brief Time 64 flags - * - *
-   *
-   *    3                   2                   1
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-----------------------------------------------------------+-+-+
-   * |                                                           |S|P|
-   * +-----------------------------------------------------------+-+-+
-   *
-   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
-   * S - Source (0=sma, 1=mimo, 0=default)
-   *
-   * 
- */ -#define UE_REG_TIME64_SECS UE_REG_SR_ADDR(28) // value to set absolute secs to on next PPS -#define UE_REG_TIME64_TICKS UE_REG_SR_ADDR(29) // value to set absolute ticks to on next PPS -#define UE_REG_TIME64_FLAGS UE_REG_SR_ADDR(30) // flags - see chart above -#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0) -#define UE_REG_TIME64_TPS UE_REG_SR_ADDR(31) // clock ticks per second (counter rollover) - -//pps flags (see above) -#define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0) -#define UE_FLAG_TIME64_PPS_POSEDGE (1 << 0) -#define UE_FLAG_TIME64_PPS_SMA (0 << 1) -#define UE_FLAG_TIME64_PPS_MIMO (1 << 1) - -#define UE_FLAG_TIME64_LATCH_NOW 1 -#define UE_FLAG_TIME64_LATCH_NEXT_PPS 0 - -#endif - -- cgit v1.2.3 From b43a1a9d5e01566457d9c9ee478d13e899a46e77 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 9 Nov 2010 19:23:17 -0800 Subject: usrp-e100: moved kernel header to lib dir, remove the header check, default enable to false --- host/include/linux/usrp_e.h | 91 -------------------------- host/lib/usrp/usrp_e100/CMakeLists.txt | 10 +-- host/lib/usrp/usrp_e100/include/linux/usrp_e.h | 91 ++++++++++++++++++++++++++ host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 2 +- 4 files changed, 95 insertions(+), 99 deletions(-) delete mode 100644 host/include/linux/usrp_e.h create mode 100644 host/lib/usrp/usrp_e100/include/linux/usrp_e.h (limited to 'host/lib/usrp') diff --git a/host/include/linux/usrp_e.h b/host/include/linux/usrp_e.h deleted file mode 100644 index 4c6a5dd89..000000000 --- a/host/include/linux/usrp_e.h +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * Copyright (C) 2010 Ettus Research, LLC - * - * Written by Philip Balister - * - * 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 -#include - -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_TXNEG (1<<10) -#define UE_SPI_CTRL_RXNEG (1<<9) - -#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 _IOWR(USRP_E_IOC_MAGIC, 0x24, struct usrp_e_spi) -#define USRP_E_I2C_READ _IOWR(USRP_E_IOC_MAGIC, 0x25, struct usrp_e_i2c) -#define USRP_E_I2C_WRITE _IOW(USRP_E_IOC_MAGIC, 0x26, struct usrp_e_i2c) -#define USRP_E_GET_RB_INFO _IOR(USRP_E_IOC_MAGIC, 0x27, struct usrp_e_ring_buffer_size_t) -#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) - -#define USRP_E_COMPAT_NUMBER 1 - -/* Flag defines */ -#define RB_USER (1<<0) -#define RB_KERNEL (1<<1) -#define RB_OVERRUN (1<<2) -#define RB_DMA_ACTIVE (1<<3) -#define RB_USER_PROCESS (1<<4) - -struct ring_buffer_info { - int flags; - int len; -}; - -struct usrp_e_ring_buffer_size_t { - int num_pages_rx_flags; - int num_rx_frames; - int num_pages_tx_flags; - int num_tx_frames; -}; - -#endif diff --git a/host/lib/usrp/usrp_e100/CMakeLists.txt b/host/lib/usrp/usrp_e100/CMakeLists.txt index 97a3d5d9a..66c87e0d8 100644 --- a/host/lib/usrp/usrp_e100/CMakeLists.txt +++ b/host/lib/usrp/usrp_e100/CMakeLists.txt @@ -22,24 +22,20 @@ ######################################################################## MESSAGE(STATUS "Configuring USRP-E100 support...") -INCLUDE(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(linux/usrp_e.h HAVE_LINUX_USRP_E_H) - -SET(ENABLE_USRP_E TRUE) - IF(DEFINED ENABLE_USRP_E100) IF(ENABLE_USRP_E100) MESSAGE(STATUS "USRP-E100 support enabled by configure flag") ELSE(ENABLE_USRP_E100) MESSAGE(STATUS "USRP-E100 support disabled by configure flag") ENDIF(ENABLE_USRP_E100) -ELSE(DEFINED ENABLE_USRP_E100) #not defined: automatic enabling of component - SET(ENABLE_USRP_E100 ${HAVE_LINUX_USRP_E_H}) +ELSE(DEFINED ENABLE_USRP_E100) #not defined: automatic disabling of component + SET(ENABLE_USRP_E100 FALSE) ENDIF(DEFINED ENABLE_USRP_E100) SET(ENABLE_USRP_E100 ${ENABLE_USRP_E100} CACHE BOOL "enable USRP-E100 support") IF(ENABLE_USRP_E100) MESSAGE(STATUS " Building USRP-E100 support.") + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/include) LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/clock_ctrl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/clock_ctrl.hpp diff --git a/host/lib/usrp/usrp_e100/include/linux/usrp_e.h b/host/lib/usrp/usrp_e100/include/linux/usrp_e.h new file mode 100644 index 000000000..4c6a5dd89 --- /dev/null +++ b/host/lib/usrp/usrp_e100/include/linux/usrp_e.h @@ -0,0 +1,91 @@ + +/* + * Copyright (C) 2010 Ettus Research, LLC + * + * Written by Philip Balister + * + * 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 +#include + +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_TXNEG (1<<10) +#define UE_SPI_CTRL_RXNEG (1<<9) + +#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 _IOWR(USRP_E_IOC_MAGIC, 0x24, struct usrp_e_spi) +#define USRP_E_I2C_READ _IOWR(USRP_E_IOC_MAGIC, 0x25, struct usrp_e_i2c) +#define USRP_E_I2C_WRITE _IOW(USRP_E_IOC_MAGIC, 0x26, struct usrp_e_i2c) +#define USRP_E_GET_RB_INFO _IOR(USRP_E_IOC_MAGIC, 0x27, struct usrp_e_ring_buffer_size_t) +#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) + +#define USRP_E_COMPAT_NUMBER 1 + +/* Flag defines */ +#define RB_USER (1<<0) +#define RB_KERNEL (1<<1) +#define RB_OVERRUN (1<<2) +#define RB_DMA_ACTIVE (1<<3) +#define RB_USER_PROCESS (1<<4) + +struct ring_buffer_info { + int flags; + int len; +}; + +struct usrp_e_ring_buffer_size_t { + int num_pages_rx_flags; + int num_rx_frames; + int num_pages_tx_flags; + int num_tx_frames; +}; + +#endif diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 73cb1f285..1ff135eac 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -51,7 +51,7 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){ //device node not provided, assume its 0 if (not hint.has_key("node")){ device_addr_t new_addr = hint; - new_addr["node"] = "/dev/usrp_e1000"; + new_addr["node"] = "/dev/usrp_e0"; return usrp_e100_find(new_addr); } -- cgit v1.2.3 From 3e695d1c0026383fd0509da8e4ebbf5ce5dd1fa3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 10 Nov 2010 10:09:40 -0800 Subject: fixed string constants find and replace typo --- host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 1ff135eac..8e40458d5 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -82,11 +82,11 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){ //-- 1) The compatibility number matches. //-- 2) The hash in the hash-file matches. //------------------------------------------------------------------ - static const char *hash_file_path = "/tmp/usrp_e100100_hash"; + static const char *hash_file_path = "/tmp/usrp_e100_hash"; //extract the fpga path for usrp-e std::string usrp_e100_fpga_image = find_image_path( - device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100100_fpga.bin" + device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" ); //calculate a hash of the fpga file -- cgit v1.2.3 From 57a2fa2e0654226c8a13c7eddad2fcdb43f72703 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 10 Nov 2010 10:30:41 -0800 Subject: usrp-e100: added empty eeprom for eeprom get property --- host/lib/usrp/usrp_e100/mboard_impl.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index 2d5d028e6..e45d7c5a0 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,10 @@ void usrp_e100_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = _tx_subdev_spec; return; + case MBOARD_PROP_EEPROM_MAP: + val = mboard_eeprom_t(); + return; + default: UHD_THROW_PROP_GET_ERROR(); } } -- cgit v1.2.3 From a724f4b7262c6da6d24dccdbd64e08da61cb87fc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 10 Nov 2010 16:48:02 -0800 Subject: usrp-e100: implemented wrapper for i2c device node + ioctls, implemented e100 eeprom map --- host/include/uhd/usrp/mboard_eeprom.hpp | 3 +- host/lib/usrp/mboard_eeprom.cpp | 77 +++++++++++++++++++++++++++ host/lib/usrp/usrp_e100/mboard_impl.cpp | 10 +++- host/lib/usrp/usrp_e100/usrp_e100_iface.cpp | 82 +++++++++++++++++++++++++++-- host/lib/usrp/usrp_e100/usrp_e100_iface.hpp | 7 +++ 5 files changed, 172 insertions(+), 7 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/mboard_eeprom.hpp b/host/include/uhd/usrp/mboard_eeprom.hpp index 530b177be..52363b95c 100644 --- a/host/include/uhd/usrp/mboard_eeprom.hpp +++ b/host/include/uhd/usrp/mboard_eeprom.hpp @@ -37,7 +37,8 @@ namespace uhd{ namespace usrp{ //! Possible EEPROM maps types enum map_type{ MAP_N100, - MAP_B000 + MAP_B000, + MAP_E100 }; //! Make a new empty mboard eeprom diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 661030aa7..444057ad9 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -171,6 +172,80 @@ static void store_b000(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN) ); } +/*********************************************************************** + * Implementation of E100 load/store + **********************************************************************/ +static const boost::uint8_t E100_EEPROM_ADDR = 0x51; + +struct e100_eeprom_map{ + unsigned int device_vendor; + unsigned char revision; + unsigned char content; + unsigned char fab_revision[8]; + unsigned char env_var[16]; + unsigned char env_setting[64]; + unsigned char serial[10]; + unsigned char name[NAME_MAX_LEN]; +}; + +template static const byte_vector_t to_bytes(const T &item){ + return byte_vector_t( + reinterpret_cast(&item), + reinterpret_cast(&item)+sizeof(item) + ); +} + +static void load_e100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ + const size_t num_bytes = offsetof(e100_eeprom_map, fab_revision); + byte_vector_t map_bytes = iface.read_eeprom(E100_EEPROM_ADDR, 0, num_bytes); + e100_eeprom_map map; std::memcpy(&map, &map_bytes[0], map_bytes.size()); + + mb_eeprom["device_vendor"] = boost::lexical_cast(map.device_vendor); + mb_eeprom["revision"] = boost::lexical_cast(map.revision); + mb_eeprom["content"] = boost::lexical_cast(map.content); + + #define load_e100_string_xx(key) mb_eeprom[#key] = bytes_to_string(iface.read_eeprom( \ + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, key), sizeof(e100_eeprom_map::key) \ + )); + + load_e100_string_xx(fab_revision); + load_e100_string_xx(env_var); + load_e100_string_xx(env_setting); + load_e100_string_xx(serial); + load_e100_string_xx(fab_revision); + load_e100_string_xx(name); +} + +static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ + + if (mb_eeprom.has_key("device_vendor")) iface.write_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, device_vendor), + to_bytes(boost::lexical_cast(mb_eeprom["device_vendor"])) + ); + + if (mb_eeprom.has_key("revision")) iface.write_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, revision), + to_bytes(boost::lexical_cast(mb_eeprom["revision"])) + ); + + if (mb_eeprom.has_key("content")) iface.write_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, content), + to_bytes(boost::lexical_cast(mb_eeprom["content"])) + ); + + #define store_e100_string_xx(key) if (mb_eeprom.has_key(#key)) iface.write_eeprom( \ + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, key), \ + string_to_bytes(mb_eeprom[#key], sizeof(e100_eeprom_map::key)) \ + ); + + store_e100_string_xx(fab_revision); + store_e100_string_xx(env_var); + store_e100_string_xx(env_setting); + store_e100_string_xx(serial); + store_e100_string_xx(fab_revision); + store_e100_string_xx(name); + +} /*********************************************************************** * Implementation of mboard eeprom @@ -183,6 +258,7 @@ mboard_eeprom_t::mboard_eeprom_t(i2c_iface &iface, map_type map){ switch(map){ case MAP_N100: load_n100(*this, iface); break; case MAP_B000: load_b000(*this, iface); break; + case MAP_E100: load_e100(*this, iface); break; } } @@ -190,5 +266,6 @@ void mboard_eeprom_t::commit(i2c_iface &iface, map_type map){ switch(map){ case MAP_N100: store_n100(*this, iface); break; case MAP_B000: store_b000(*this, iface); break; + case MAP_E100: store_e100(*this, iface); break; } } diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index e45d7c5a0..9c6317b94 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -109,7 +108,7 @@ void usrp_e100_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_EEPROM_MAP: - val = mboard_eeprom_t(); + val = _iface->mb_eeprom; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -159,6 +158,13 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){ )); return; + case MBOARD_PROP_EEPROM_MAP: + // Step1: commit the map, writing only those values set. + // Step2: readback the entire eeprom map into the iface. + val.as().commit(_iface->get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100); + _iface->mb_eeprom = mboard_eeprom_t(_iface->get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp index ad623777e..40c7afabb 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp @@ -22,10 +22,74 @@ #include //ioctl structures and constants #include #include //mutex +#include +#include #include using namespace uhd; +using namespace uhd::usrp; +/*********************************************************************** + * I2C device node implementation wrapper + **********************************************************************/ +class i2c_dev_iface : public i2c_iface{ +public: + i2c_dev_iface(const std::string &node){ + if ((_node_fd = ::open(node.c_str(), O_RDWR)) < 0){ + throw std::runtime_error("Failed to open " + node); + } + } + + ~i2c_dev_iface(void){ + ::close(_node_fd); + } + + void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ + byte_vector_t rw_bytes(bytes); + + //setup the message + i2c_msg msg; + msg.addr = addr; + msg.flags = 0; + msg.len = bytes.size(); + msg.buf = &rw_bytes.front(); + + //setup the data + i2c_rdwr_ioctl_data data; + data.msgs = &msg; + data.nmsgs = 1; + + //call the ioctl + UHD_ASSERT_THROW(::ioctl(_node_fd, I2C_RDWR, &data) >= 0); + } + + byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ + byte_vector_t bytes(num_bytes); + + //setup the message + i2c_msg msg; + msg.addr = addr; + msg.flags = I2C_M_RD; + msg.len = bytes.size(); + msg.buf = &bytes.front(); + + //setup the data + i2c_rdwr_ioctl_data data; + data.msgs = &msg; + data.nmsgs = 1; + + //call the ioctl + UHD_ASSERT_THROW(::ioctl(_node_fd, I2C_RDWR, &data) >= 0); + + return bytes; + } + +private: int _node_fd; +}; + +/*********************************************************************** + * USRP-E100 interface implementation + **********************************************************************/ class usrp_e100_iface_impl : public usrp_e100_iface{ public: @@ -36,13 +100,15 @@ public: /******************************************************************* * Structors ******************************************************************/ - usrp_e100_iface_impl(const std::string &node){ + usrp_e100_iface_impl(const std::string &node): + _i2c_dev_iface(i2c_dev_iface("/dev/i2c-3")) + { //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 - )); + throw std::runtime_error("Failed to open " + node); } + + mb_eeprom = mboard_eeprom_t(get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100); } ~usrp_e100_iface_impl(void){ @@ -63,6 +129,13 @@ public: } } + /******************************************************************* + * I2C device node interface + ******************************************************************/ + i2c_iface &get_i2c_dev_iface(void){ + return _i2c_dev_iface; + } + /******************************************************************* * Peek and Poke ******************************************************************/ @@ -183,6 +256,7 @@ public: private: int _node_fd; + i2c_dev_iface _i2c_dev_iface; boost::mutex _ctrl_mutex; }; diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp index b52209a42..12283fb52 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp @@ -19,6 +19,7 @@ #define INCLUDED_USRP_E100_IFACE_HPP #include +#include #include #include #include @@ -63,6 +64,9 @@ public: */ virtual void ioctl(int request, void *mem) = 0; + //! Get the I2C interface for the I2C device node + virtual uhd::i2c_iface &get_i2c_dev_iface(void) = 0; + /*! * Write a register (32 bits) * \param addr the address @@ -107,6 +111,9 @@ public: size_t num_bits, bool readback ) = 0; + + //motherboard eeprom map structure + uhd::usrp::mboard_eeprom_t mb_eeprom; }; #endif /* INCLUDED_USRP_E100_IFACE_HPP */ -- cgit v1.2.3 From f2d5f0b12bd0e9a29d22a93a6aaa4565021583e4 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 11 Nov 2010 09:20:26 -0800 Subject: usrp_eXXX: Only include i2c-dev.h due to struct definition conflicts. --- host/lib/usrp/usrp_e100/usrp_e100_iface.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp index 40c7afabb..50ff4a8ff 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp @@ -23,7 +23,6 @@ #include #include //mutex #include -#include #include using namespace uhd; -- cgit v1.2.3 From 791401f979aae3e5909ed0a7a06e176f0c16cd5a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 11 Nov 2010 10:41:05 -0800 Subject: usrp-e100: split vendor/device field for eeprom, rename fab rev to model, fixed char cast (to treat like integer) --- host/lib/usrp/mboard_eeprom.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 444057ad9..842ee01e3 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -178,10 +178,11 @@ static void store_b000(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ static const boost::uint8_t E100_EEPROM_ADDR = 0x51; struct e100_eeprom_map{ - unsigned int device_vendor; + boost::uint16_t vendor; + boost::uint16_t device; unsigned char revision; unsigned char content; - unsigned char fab_revision[8]; + unsigned char model[8]; unsigned char env_var[16]; unsigned char env_setting[64]; unsigned char serial[10]; @@ -196,41 +197,46 @@ template static const byte_vector_t to_bytes(const T &item){ } static void load_e100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ - const size_t num_bytes = offsetof(e100_eeprom_map, fab_revision); + const size_t num_bytes = offsetof(e100_eeprom_map, model); byte_vector_t map_bytes = iface.read_eeprom(E100_EEPROM_ADDR, 0, num_bytes); e100_eeprom_map map; std::memcpy(&map, &map_bytes[0], map_bytes.size()); - mb_eeprom["device_vendor"] = boost::lexical_cast(map.device_vendor); - mb_eeprom["revision"] = boost::lexical_cast(map.revision); - mb_eeprom["content"] = boost::lexical_cast(map.content); + mb_eeprom["vendor"] = boost::lexical_cast(map.vendor); + mb_eeprom["device"] = boost::lexical_cast(map.device); + mb_eeprom["revision"] = boost::lexical_cast(unsigned(map.revision)); + mb_eeprom["content"] = boost::lexical_cast(unsigned(map.content)); #define load_e100_string_xx(key) mb_eeprom[#key] = bytes_to_string(iface.read_eeprom( \ E100_EEPROM_ADDR, offsetof(e100_eeprom_map, key), sizeof(e100_eeprom_map::key) \ )); - load_e100_string_xx(fab_revision); + load_e100_string_xx(model); load_e100_string_xx(env_var); load_e100_string_xx(env_setting); load_e100_string_xx(serial); - load_e100_string_xx(fab_revision); load_e100_string_xx(name); } static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ - if (mb_eeprom.has_key("device_vendor")) iface.write_eeprom( - E100_EEPROM_ADDR, offsetof(e100_eeprom_map, device_vendor), - to_bytes(boost::lexical_cast(mb_eeprom["device_vendor"])) + if (mb_eeprom.has_key("vendor")) iface.write_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, vendor), + to_bytes(boost::lexical_cast(mb_eeprom["vendor"])) + ); + + if (mb_eeprom.has_key("device")) iface.write_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, device), + to_bytes(boost::lexical_cast(mb_eeprom["device"])) ); if (mb_eeprom.has_key("revision")) iface.write_eeprom( E100_EEPROM_ADDR, offsetof(e100_eeprom_map, revision), - to_bytes(boost::lexical_cast(mb_eeprom["revision"])) + byte_vector_t(1, boost::lexical_cast(mb_eeprom["revision"])) ); if (mb_eeprom.has_key("content")) iface.write_eeprom( E100_EEPROM_ADDR, offsetof(e100_eeprom_map, content), - to_bytes(boost::lexical_cast(mb_eeprom["content"])) + byte_vector_t(1, boost::lexical_cast(mb_eeprom["content"])) ); #define store_e100_string_xx(key) if (mb_eeprom.has_key(#key)) iface.write_eeprom( \ @@ -238,11 +244,10 @@ static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ string_to_bytes(mb_eeprom[#key], sizeof(e100_eeprom_map::key)) \ ); - store_e100_string_xx(fab_revision); + store_e100_string_xx(model); store_e100_string_xx(env_var); store_e100_string_xx(env_setting); store_e100_string_xx(serial); - store_e100_string_xx(fab_revision); store_e100_string_xx(name); } -- cgit v1.2.3 From 926fd69de88725f14c34062a81969a4a833a7f61 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 11 Nov 2010 11:07:39 -0800 Subject: usrp_e100: added byteswapping calls to vendor and device (its NBO) --- host/lib/usrp/mboard_eeprom.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 842ee01e3..70f4664a0 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -201,8 +202,8 @@ static void load_e100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ byte_vector_t map_bytes = iface.read_eeprom(E100_EEPROM_ADDR, 0, num_bytes); e100_eeprom_map map; std::memcpy(&map, &map_bytes[0], map_bytes.size()); - mb_eeprom["vendor"] = boost::lexical_cast(map.vendor); - mb_eeprom["device"] = boost::lexical_cast(map.device); + mb_eeprom["vendor"] = boost::lexical_cast(uhd::ntohx(map.vendor)); + mb_eeprom["device"] = boost::lexical_cast(uhd::ntohx(map.device)); mb_eeprom["revision"] = boost::lexical_cast(unsigned(map.revision)); mb_eeprom["content"] = boost::lexical_cast(unsigned(map.content)); @@ -221,12 +222,12 @@ static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ if (mb_eeprom.has_key("vendor")) iface.write_eeprom( E100_EEPROM_ADDR, offsetof(e100_eeprom_map, vendor), - to_bytes(boost::lexical_cast(mb_eeprom["vendor"])) + to_bytes(uhd::htonx(boost::lexical_cast(mb_eeprom["vendor"]))) ); if (mb_eeprom.has_key("device")) iface.write_eeprom( E100_EEPROM_ADDR, offsetof(e100_eeprom_map, device), - to_bytes(boost::lexical_cast(mb_eeprom["device"])) + to_bytes(uhd::htonx(boost::lexical_cast(mb_eeprom["device"]))) ); if (mb_eeprom.has_key("revision")) iface.write_eeprom( -- cgit v1.2.3 From be3f1411c5c2ba7714b1531418a57f3be06829bf Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 11 Nov 2010 11:27:01 -0800 Subject: usrp-e100: add serial and name checks to the usrp-e100 discovery routine --- host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 8e40458d5..13d31e423 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -32,13 +32,6 @@ using namespace uhd; using namespace uhd::usrp; namespace fs = boost::filesystem; -/*********************************************************************** - * Helper Functions - **********************************************************************/ -static std::string abs_path(const std::string &file_path){ - return fs::system_complete(fs::path(file_path)).file_string(); -} - /*********************************************************************** * Discovery **********************************************************************/ @@ -59,8 +52,24 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){ if (fs::exists(hint["node"])){ device_addr_t new_addr; new_addr["type"] = "usrp-e"; - new_addr["node"] = abs_path(hint["node"]); - usrp_e100_addrs.push_back(new_addr); + new_addr["node"] = fs::system_complete(fs::path(hint["node"])).file_string(); + try{ + usrp_e100_iface::sptr iface = usrp_e100_iface::make(new_addr["node"]); + new_addr["name"] = iface->mb_eeprom["name"]; + new_addr["serial"] = iface->mb_eeprom["serial"]; + if ( + (not hint.has_key("name") or hint["name"] == new_addr["name"]) and + (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) + ){ + usrp_e100_addrs.push_back(new_addr); + } + } + catch(const std::exception &e){ + uhd::warning::post( + std::string("Ignoring discovered device\n") + + e.what() + ); + } } return usrp_e100_addrs; -- cgit v1.2.3 From 309964637e5eac309a6d9d36300a14a4235f34fb Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 11 Nov 2010 14:41:21 -0800 Subject: usrp_e : Add missing header file. --- host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 13d31e423..a3e03056a 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 862a3f264671a133d9ff7e5b39d707d105a1dd45 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 17 Nov 2010 11:11:37 -0800 Subject: usrp e100 : Add i2c header back. --- host/lib/usrp/usrp_e100/usrp_e100_iface.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp index 50ff4a8ff..40c7afabb 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp @@ -23,6 +23,7 @@ #include #include //mutex #include +#include #include using namespace uhd; -- cgit v1.2.3 From 27e128ea70249bf4a79c6957fab14a3c4cad75f8 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 17 Nov 2010 11:13:31 -0800 Subject: usrp e100 : Add sleep after loading module. After loading the module, we need to wait until /dev/usrp_e0 is available before proceeding. --- host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index a3e03056a..40ea56466 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -123,6 +123,7 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){ if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ iface.reset(); usrp_e100_load_fpga(usrp_e100_fpga_image); + sleep(1); ///\todo do this better one day. std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl; iface = usrp_e100_iface::make(node); try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} -- cgit v1.2.3 From e7b98030eb3ea7e42bd8d6fa5f115b0219ae2685 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Nov 2010 12:23:04 -0800 Subject: usrp2: ms didnt seem to like unlocking an unlocked mutex --- host/lib/usrp/usrp2/io_impl.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 4d9528f66..4b498ff7f 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -165,8 +165,7 @@ void usrp2_impl::io_init(void){ //create a new pirate thread for each zc if (yarr!!) for (size_t i = 0; i < _data_transports.size(); i++){ - //ensure a non-blocking mutex lock - _io_impl->spawn_mutex.unlock(); + //lock the unlocked mutex (non-blocking) _io_impl->spawn_mutex.lock(); //spawn a new pirate to plunder the recv booty _io_impl->recv_pirate_crew.create_thread(boost::bind( @@ -174,8 +173,10 @@ void usrp2_impl::io_init(void){ _io_impl.get(), _data_transports.at(i), _mboards.at(i), i )); - //will block here until the thread unlocks + //block here until the spawned thread unlocks _io_impl->spawn_mutex.lock(); + //exit loop iteration in an unlocked condition + _io_impl->spawn_mutex.unlock(); } } -- cgit v1.2.3 From 13ae4786e091d5581baf31c9967dca822ef15e39 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 22 Nov 2010 18:26:54 -0800 Subject: E100: clock sync implemented. --- host/lib/usrp/usrp_e100/clock_ctrl.cpp | 26 ++++++++++++++++++++++++++ host/lib/usrp/usrp_e100/clock_ctrl.hpp | 15 +++++++++++++++ host/lib/usrp/usrp_e100/mboard_impl.cpp | 30 +++++++++++++++++++++++++++++- host/lib/usrp/usrp_e100/usrp_e100_impl.hpp | 5 ++++- 4 files changed, 74 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index e99560540..1fb1a7125 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -208,6 +208,32 @@ public: this->send_reg(0x197); this->latch_regs(); } + + /*********************************************************************** + * Clock reference control + **********************************************************************/ + void use_internal_ref(void) { + _ad9522_regs.enable_ref2 = 1; + _ad9522_regs.enable_ref1 = 0; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; + _ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL; + this->send_reg(0x01C); + } + + void use_external_ref(void) { + _ad9522_regs.enable_ref2 = 0; + _ad9522_regs.enable_ref1 = 1; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1; + _ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL; + this->send_reg(0x01C); + } + + void use_auto_ref(void) { + _ad9522_regs.enable_ref2 = 1; + _ad9522_regs.enable_ref1 = 1; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1; + _ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_AUTO; + } private: usrp_e100_iface::sptr _iface; diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.hpp b/host/lib/usrp/usrp_e100/clock_ctrl.hpp index 0ae68728e..d613d1473 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.hpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.hpp @@ -82,6 +82,21 @@ public: * \param enb true to enable */ virtual void enable_tx_dboard_clock(bool enb) = 0; + + /*! + * Use the internal TCXO reference + */ + virtual void use_internal_ref(void) = 0; + + /*! + * Use the external SMA reference + */ + virtual void use_external_ref(void) = 0; + + /*! + * Use external if available, internal otherwise + */ + virtual void use_auto_ref(void) = 0; }; diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index 9c6317b94..03c4385aa 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -39,8 +39,31 @@ void usrp_e100_impl::mboard_init(void){ //init the clock config _clock_config.ref_source = clock_config_t::REF_AUTO; _clock_config.pps_source = clock_config_t::PPS_SMA; + _clock_config.pps_polarity = clock_config_t::PPS_NEG; - //TODO poke the clock config regs + update_clock_config(); +} + +void usrp_e100_impl::update_clock_config(void){ + boost::uint32_t pps_flags = 0; + + //translate pps polarity enums + switch(_clock_config.pps_polarity){ + case clock_config_t::PPS_POS: pps_flags |= UE_FLAG_TIME64_PPS_POSEDGE; break; + case clock_config_t::PPS_NEG: pps_flags |= UE_FLAG_TIME64_PPS_NEGEDGE; break; + default: throw std::runtime_error("unhandled clock configuration pps polarity"); + } + + //set the pps flags + _iface->poke32(UE_REG_TIME64_FLAGS, pps_flags); + + //clock source ref 10mhz + switch(_clock_config.ref_source){ + case clock_config_t::REF_AUTO: _clock_ctrl->use_auto_ref(); + case clock_config_t::REF_INT: _clock_ctrl->use_internal_ref(); + case clock_config_t::REF_SMA: _clock_ctrl->use_external_ref(); + default: throw std::runtime_error("unhandled clock configuration ref source"); + } } /*********************************************************************** @@ -164,6 +187,11 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){ val.as().commit(_iface->get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100); _iface->mb_eeprom = mboard_eeprom_t(_iface->get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100); return; + + case MBOARD_PROP_CLOCK_CONFIG: + _clock_config = val.as(); + update_clock_config(); + return; default: UHD_THROW_PROP_SET_ERROR(); } diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp index fe60ac0be..de158ea5e 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp @@ -102,7 +102,6 @@ private: //configuration shadows uhd::clock_config_t _clock_config; - //TODO otw type recv/send //ad9522 clock control usrp_e100_clock_ctrl::sptr _clock_ctrl; @@ -159,6 +158,10 @@ private: void tx_codec_get(const wax::obj &, wax::obj &); void tx_codec_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _rx_codec_proxy, _tx_codec_proxy; + + //clock control functions and settings + void init_clock_config(void); + void update_clock_config(void); }; #endif /* INCLUDED_USRP_E100_IMPL_HPP */ -- cgit v1.2.3 From 8ce75a3ca7a51f4bdee87d78a610a0f2519473ae Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 23 Nov 2010 10:19:05 -0800 Subject: usrp_nxxx: software workarounds for weird power up state --- host/lib/usrp/usrp2/io_impl.cpp | 49 ++++++++++++++++++++++++------------- host/lib/usrp/usrp2/mboard_impl.cpp | 8 +++--- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 ++ 3 files changed, 38 insertions(+), 21 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f2101519d..f903a80f6 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -194,8 +194,27 @@ void usrp2_impl::io_impl::recv_pirate_loop( const boost::uint32_t *vrt_hdr = buff->cast(); vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info); + //handle the rx data stream + if (if_packet_info.sid == usrp2_impl::RECV_SID and if_packet_info.packet_type == vrt::if_packet_info_t::PACKET_TYPE_DATA){ + //handle the packet count / sequence number + if (if_packet_info.packet_count != next_packet_seq){ + //std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16; + std::cerr << "O" << std::flush; //report overflow (drops in the kernel) + } + next_packet_seq = (if_packet_info.packet_count+1)%16; + + //extract the timespec and round to the nearest packet + UHD_ASSERT_THROW(if_packet_info.has_tsi and if_packet_info.has_tsf); + time_spec_t time( + time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), mboard->get_master_clock_freq() + ); + + //push the packet into the buffer with the new time + recv_pirate_booty->push_with_pop_on_full(buff, time, index); + } + //handle a tx async report message - if (if_packet_info.sid == 1 and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ + else if (if_packet_info.sid == usrp2_impl::ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ //fill in the async metadata async_metadata_t metadata; @@ -217,24 +236,10 @@ void usrp2_impl::io_impl::recv_pirate_loop( if (metadata.event_code & underflow_flags) std::cerr << "U" << std::flush; //else std::cout << "metadata.event_code " << metadata.event_code << std::endl; async_msg_fifo->push_with_pop_on_full(metadata); - continue; } - - //handle the packet count / sequence number - if (if_packet_info.packet_count != next_packet_seq){ - //std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16; - std::cerr << "O" << std::flush; //report overflow (drops in the kernel) + else{ + //TODO unknown received packet, may want to print error... } - next_packet_seq = (if_packet_info.packet_count+1)%16; - - //extract the timespec and round to the nearest packet - UHD_ASSERT_THROW(if_packet_info.has_tsi and if_packet_info.has_tsf); - time_spec_t time( - time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), mboard->get_master_clock_freq() - ); - - //push the packet into the buffer with the new time - recv_pirate_booty->push_with_pop_on_full(buff, time, index); }catch(const std::exception &e){ std::cerr << "Error (usrp2 recv pirate loop): " << e.what() << std::endl; } @@ -253,6 +258,16 @@ void usrp2_impl::io_init(void){ //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, (num_recv_frames, send_frame_size, _data_transports.size())); + //TODO temporary fix for weird power up state, remove when FPGA fixed + { + //send an initial packet to all transports + tx_metadata_t md; md.end_of_burst = true; + this->send( + std::vector(_data_transports.size(), NULL), 0, md, + io_type_t::COMPLEX_FLOAT32, device::SEND_MODE_ONE_PACKET, 0 + ); + } + //create a new pirate thread for each zc if (yarr!!) for (size_t i = 0; i < _data_transports.size(); i++){ //lock the unlocked mutex (non-blocking) diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 92b1d0be9..13d8b9856 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -84,23 +84,23 @@ usrp2_mboard_impl::usrp2_mboard_impl( this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); //setup the vrt rx registers + _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset _iface->poke32(_iface->regs.rx_ctrl_nsamps_per_pkt, recv_samps_per_packet); _iface->poke32(_iface->regs.rx_ctrl_nchannels, 1); - _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset _iface->poke32(_iface->regs.rx_ctrl_vrt_header, 0 | (0x1 << 28) //if data with stream id | (0x1 << 26) //has trailer | (0x3 << 22) //integer time other | (0x1 << 20) //fractional time sample count ); - _iface->poke32(_iface->regs.rx_ctrl_vrt_stream_id, 0); + _iface->poke32(_iface->regs.rx_ctrl_vrt_stream_id, usrp2_impl::RECV_SID); _iface->poke32(_iface->regs.rx_ctrl_vrt_trailer, 0); _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq())); //init the tx control registers - _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0); //1 channel _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset - _iface->poke32(_iface->regs.tx_ctrl_report_sid, 1); //sid 1 (different from rx) + _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0); //1 channel + _iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID); _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); //setting the cycles per update diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index ede777323..aa8eb0155 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -180,6 +180,8 @@ private: class usrp2_impl : public uhd::device{ public: static const size_t sram_bytes = size_t(1 << 20); + static const boost::uint32_t RECV_SID = 1; + static const boost::uint32_t ASYNC_SID = 2; /*! * Create a new usrp2 impl base. -- cgit v1.2.3 From eb26e8adb4a5718ee3db3bb7f32c0cd31d060af9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 23 Nov 2010 14:43:02 -0800 Subject: uhd: added new hardware to readme --- fpga/usrp2/coregen/_xmsgs/pn_parser.xmsgs | 2 +- host/README | 4 +++- host/lib/usrp/README | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/fpga/usrp2/coregen/_xmsgs/pn_parser.xmsgs b/fpga/usrp2/coregen/_xmsgs/pn_parser.xmsgs index 032a35f41..d946af064 100644 --- a/fpga/usrp2/coregen/_xmsgs/pn_parser.xmsgs +++ b/fpga/usrp2/coregen/_xmsgs/pn_parser.xmsgs @@ -8,7 +8,7 @@ -Parsing Verilog file "/home/jblum/uhdpriv/fpga/usrp2/coregen/fifo_xlnx_512x36_2clk_18to36.v" into library work +Parsing Verilog file "/home/jblum/uhdpriv/fpga/usrp2/coregen/fifo_xlnx_512x36_2clk_prog_full.v" into library work diff --git a/host/README b/host/README index c4a72cd83..f3dcde53d 100644 --- a/host/README +++ b/host/README @@ -8,7 +8,9 @@ The hardware driver for Ettus Research products. ######################################################################## USRP1 USRP2 -USRP-N2XX +USRP-N200 +USRP-N210 +USRP-E100 ######################################################################## # Supported USRP Daughterboards diff --git a/host/lib/usrp/README b/host/lib/usrp/README index c125d1dad..344209179 100644 --- a/host/lib/usrp/README +++ b/host/lib/usrp/README @@ -9,4 +9,7 @@ usrp1: Implementation code for the USB-based USRP Classic motherboard. usrp2: - Implementation code for USRP2 and USRP-N2XX. + Implementation code for USRP2, USRP-N200, and USRP-N210. + +usrp_e100: + Implementation code for USRP-E100. -- cgit v1.2.3