diff options
Diffstat (limited to 'host')
123 files changed, 1581 insertions, 1587 deletions
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index e4f272a76..bbcf34373 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -61,10 +61,7 @@ IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE "Release") MESSAGE(STATUS "Build type not specified: defaulting to release.") ENDIF(NOT CMAKE_BUILD_TYPE) - -#Creating a shared pointer itself has allocation overhead. -#Define the quick allocator to reduce fast-path overhead. -ADD_DEFINITIONS(-DBOOST_SP_USE_QUICK_ALLOCATOR) +SET(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "") IF(CMAKE_COMPILER_IS_GNUCXX) ADD_DEFINITIONS(-Wall) diff --git a/host/Modules/UHDPython.cmake b/host/Modules/UHDPython.cmake index cad549ea4..345e0187d 100644 --- a/host/Modules/UHDPython.cmake +++ b/host/Modules/UHDPython.cmake @@ -31,7 +31,7 @@ ELSE(PYTHON_EXECUTABLE) #and if that fails use the find program routine IF(NOT PYTHONINTERP_FOUND) - FIND_PROGRAM(PYTHON_EXECUTABLE python) + FIND_PROGRAM(PYTHON_EXECUTABLE NAMES python python2.7 python2.6) IF(PYTHON_EXECUTABLE) SET(PYTHONINTERP_FOUND TRUE) ENDIF(PYTHON_EXECUTABLE) diff --git a/host/apps/omap_debug/fetch-bin.sh b/host/apps/omap_debug/fetch-bin.sh deleted file mode 100755 index 019ddaaf2..000000000 --- a/host/apps/omap_debug/fetch-bin.sh +++ /dev/null @@ -1,6 +0,0 @@ -if [ $GHQ ]; then - scp $GHQ_USER@astro:/workspace/usrp1-e-dev/u1e.bin /home/root -else - scp -P 8822 balister@192.168.1.10:src/git/fpgapriv/usrp2/top/u1e/build/u1e.bin /home/root -fi -sync diff --git a/host/apps/omap_debug/fetch-kernel.sh b/host/apps/omap_debug/fetch-kernel.sh deleted file mode 100755 index ce420f3d2..000000000 --- a/host/apps/omap_debug/fetch-kernel.sh +++ /dev/null @@ -1,7 +0,0 @@ -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.10:src/git/kernel_usrp/arch/arm/boot/uImage /media/mmcblk0p1/uImage -fi -sync - diff --git a/host/apps/omap_debug/fetch-module.sh b/host/apps/omap_debug/fetch-module.sh deleted file mode 100755 index ec28989bd..000000000 --- a/host/apps/omap_debug/fetch-module.sh +++ /dev/null @@ -1,6 +0,0 @@ -if [ $GHQ ]; then - scp $GHQ_USER@astro:/workspace/usrp1-e-dev/kernel_usrp/drivers/misc/usrp_e.ko /lib/modules/2.6.33/kernel/drivers/misc -else - scp balister@192.168.1.10:src/git/kernel_usrp/drivers/misc/usrp_e.ko /lib/modules/2.6.33/kernel/drivers/misc -fi -sync diff --git a/host/apps/omap_debug/fetch-u-boot.sh b/host/apps/omap_debug/fetch-u-boot.sh deleted file mode 100755 index 5309364b8..000000000 --- a/host/apps/omap_debug/fetch-u-boot.sh +++ /dev/null @@ -1,7 +0,0 @@ -if [ $GHQ ]; then - scp $GHQ_USER@astro:/workspace/usrp1-e-dev/u-boot-overo/u-boot.bin /media/mmcblk0p1/ -else - scp balister@192.168.1.167:src/git/u-boot/u-boot.bin /media/mmcblk0p1/ -fi -sync - diff --git a/host/apps/omap_debug/read_board_id.sh b/host/apps/omap_debug/read_board_id.sh deleted file mode 100755 index 96081f219..000000000 --- a/host/apps/omap_debug/read_board_id.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -i2cget -y 3 0x51 0x00 b -i2cget -y 3 0x51 0x01 b -i2cget -y 3 0x51 0x02 b -i2cget -y 3 0x51 0x03 b -i2cget -y 3 0x51 0x04 b -i2cget -y 3 0x51 0x05 b - - diff --git a/host/apps/omap_debug/reload-fpga.sh b/host/apps/omap_debug/reload-fpga.sh deleted file mode 100755 index 2754718a4..000000000 --- a/host/apps/omap_debug/reload-fpga.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -rmmod usrp_e -fpga-downloader /home/root/u1e.bin -modprobe usrp_e -usrp-e-debug-pins 1 - diff --git a/host/apps/omap_debug/setup-board-id-eeprom.sh b/host/apps/omap_debug/setup-board-id-eeprom.sh deleted file mode 100755 index 4dba1cce5..000000000 --- a/host/apps/omap_debug/setup-board-id-eeprom.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -i2cset -y 3 0x51 0x00 0x00 -i2cset -y 3 0x51 0x01 0x03 -i2cset -y 3 0x51 0x02 0x00 -i2cset -y 3 0x51 0x03 0x01 -i2cset -y 3 0x51 0x04 0x01 -i2cset -y 3 0x51 0x05 0x00 -i2cset -y 3 0x51 0x06 0x00 - -i2cget -y 3 0x51 0 b -i2cget -y 3 0x51 1 b -i2cget -y 3 0x51 2 b -i2cget -y 3 0x51 3 b -i2cget -y 3 0x51 4 b -i2cget -y 3 0x51 5 b -i2cget -y 3 0x51 6 b diff --git a/host/apps/omap_debug/write-eeprom.sh b/host/apps/omap_debug/write-eeprom.sh deleted file mode 100755 index 301b06f07..000000000 --- a/host/apps/omap_debug/write-eeprom.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash - -if [ $# -ne 3 ] && [ $# -ne 5 ]; -then - echo "Usage:" - echo "" - echo "writeprom.sh deviceid rev fab_rev [envvar envsetting]" - echo - echo " deviceid - expansion board device number from table:" - echo - echo " Summit 0x01" - echo " Tobi 0x02" - echo " Tobi Duo 0x03" - echo " Palo35 0x04" - echo " Palo43 0x05" - echo " Chestnut43 0x06" - echo " Pinto 0x07" - echo - echo " rev - board revision (e.g. 0x00)" - echo " fab_rev - revision marking from pcb (e.g. R2411)" - echo " envvar - optional u-boot env variable name" - echo " (e.g. dvimode)" - echo " envsetting - optional u-boot env variable setting" - echo " (e.g. 1024x768MR-16@60)" - exit 1 -fi - -fabrevision=$3 -if [ ${#fabrevision} -ge 8 ]; then - echo "Error: fab revision string must less than 8 characters" - exit 1 -fi - -envvar=$4 -if [ ${#envar} -ge 16 ]; then - echo "Error: environment variable name string must less than 16 characters" - exit 1 -fi - -envsetting=$5 -if [ ${#ensetting} -ge 64 ]; then - echo "Error: environment setting string must less than 64 characters" - exit 1 -fi - -bus=3 -device=0x51 -vendorid=0x03 - -i2cset -y $bus $device 0x00 0x00 -i2cset -y $bus $device 0x01 $vendorid -i2cset -y $bus $device 0x02 0x00 -i2cset -y $bus $device 0x03 $1 -i2cset -y $bus $device 0x04 $2 -i2cset -y $bus $device 0x05 00 - -let i=6 -hexdumpargs="'${#fabrevision}/1 \"0x%02x \"'" -command="echo -n \"$fabrevision\" | hexdump -e $hexdumpargs" -hex=$(eval $command) -for character in $hex; do - i2cset -y $bus $device $i $character - let i=$i+1 -done -i2cset -y $bus $device $i 0x00 - -if [ $# -eq 5 ] -then - i2cset -y $bus $device 0x05 0x01 - - let i=14 - hexdumpargs="'${#envvar}/1 \"0x%02x \"'" - command="echo -n \"$envvar\" | hexdump -e $hexdumpargs" - hex=$(eval $command) - for character in $hex; do - i2cset -y $bus $device $i $character - let i=$i+1 - done - i2cset -y $bus $device $i 0x00 - - let i=30 - hexdumpargs="'${#envsetting}/1 \"0x%02x \"'" - command="echo -n \"$envsetting\" | hexdump -e $hexdumpargs" - hex=$(eval $command) - for character in $hex; do - i2cset -y $bus $device $i $character - let i=$i+1 - done - i2cset -y $bus $device $i 0x00 -fi - - diff --git a/host/apps/omap_debug/write_board_id.sh b/host/apps/omap_debug/write_board_id.sh deleted file mode 100755 index 067269c64..000000000 --- a/host/apps/omap_debug/write_board_id.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -i2cset -y 3 0x51 0x00 0x00 -i2cset -y 3 0x51 0x01 0x03 -i2cset -y 3 0x51 0x02 0x00 -i2cset -y 3 0x51 0x03 0x01 -i2cset -y 3 0x51 0x04 0x00 -i2cset -y 3 0x51 0x05 0x00 - - diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index b7a22cf0b..db755511e 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -25,6 +25,7 @@ INSTALL(FILES config.hpp convert.hpp device.hpp + exception.hpp version.hpp wax.hpp DESTINATION ${INCLUDE_DIR}/uhd diff --git a/host/include/uhd/exception.hpp b/host/include/uhd/exception.hpp new file mode 100644 index 000000000..e2a50bf1e --- /dev/null +++ b/host/include/uhd/exception.hpp @@ -0,0 +1,133 @@ +// +// Copyright 2010-2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_EXCEPTION_HPP +#define INCLUDED_UHD_UTILS_EXCEPTION_HPP + +#include <uhd/config.hpp> +#include <boost/current_function.hpp> +#include <stdexcept> +#include <string> + +/*! + * Define common exceptions used throughout the code: + * + * - The python built-in exceptions were used as inspiration. + * - Exceptions inherit from std::exception to provide what(). + * - Exceptions inherit from uhd::exception to provide code(). + * + * The code() provides an error code which allows the application + * the option of printing a cryptic error message from the 1990s. + */ +namespace uhd{ + + struct UHD_API exception : std::runtime_error{ + exception(const std::string &what); + virtual unsigned code(void) const = 0; + }; + + struct UHD_API assertion_error : exception{ + assertion_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API lookup_error : exception{ + lookup_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API index_error : lookup_error{ + index_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API key_error : lookup_error{ + key_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API type_error : exception{ + type_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API value_error : exception{ + value_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API runtime_error : exception{ + runtime_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API not_implemented_error : runtime_error{ + not_implemented_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API environment_error : exception{ + environment_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API io_error : environment_error{ + io_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API os_error : environment_error{ + os_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API system_error : exception{ + system_error(const std::string &what); + virtual unsigned code(void) const; + }; + + /*! + * Create a formated string with throw-site information. + * Fills in the function name, file name, and line number. + * \param what the std::exeption message + * \return the formatted exception message + */ + #define UHD_THROW_SITE_INFO(what) std::string( \ + std::string(what) + "\n" + \ + " in " + std::string(BOOST_CURRENT_FUNCTION) + "\n" + \ + " at " + std::string(__FILE__) + ":" + BOOST_STRINGIZE(__LINE__) + "\n" \ + ) + + /*! + * Throws an invalid code path exception with throw-site information. + * Use this macro in places that code execution is not supposed to go. + */ + #define UHD_THROW_INVALID_CODE_PATH() \ + throw uhd::system_error(UHD_THROW_SITE_INFO("invalid code path")) + + /*! + * Assert the result of the code evaluation. + * If the code evaluates to false, throw an assertion error. + * \param code the code that resolved to a boolean + */ + #define UHD_ASSERT_THROW(code) if (not (code)) \ + throw uhd::assertion_error(UHD_THROW_SITE_INFO(#code)); \ + else void(0) + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_EXCEPTION_HPP */ diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp index eb3394230..2c0841146 100644 --- a/host/include/uhd/types/device_addr.hpp +++ b/host/include/uhd/types/device_addr.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -84,9 +84,15 @@ namespace uhd{ } }; - //handy typedef for a vector of device addresses + //! A typedef for a vector of device addresses typedef std::vector<device_addr_t> device_addrs_t; + //! Separate an indexed device address into a vector of device addresses + UHD_API device_addrs_t separate_device_addr(const device_addr_t &dev_addr); + + //! Combine a vector of device addresses into an indexed device address + UHD_API device_addr_t combine_device_addrs(const device_addrs_t &dev_addrs); + } //namespace uhd #endif /* INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP */ diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp index 0c014474e..5e9cf97ad 100644 --- a/host/include/uhd/types/dict.ipp +++ b/host/include/uhd/types/dict.ipp @@ -18,18 +18,18 @@ #ifndef INCLUDED_UHD_TYPES_DICT_IPP #define INCLUDED_UHD_TYPES_DICT_IPP +#include <uhd/exception.hpp> #include <boost/foreach.hpp> #include <boost/format.hpp> #include <boost/lexical_cast.hpp> -#include <stdexcept> #include <typeinfo> namespace uhd{ namespace /*anon*/{ template<typename Key, typename Val> - struct key_not_found: std::out_of_range{ - key_not_found(const Key &key): std::out_of_range( + struct key_not_found: uhd::key_error{ + key_not_found(const Key &key): uhd::key_error( str(boost::format( "key \"%s\" not found in dict(%s, %s)" ) % boost::lexical_cast<std::string>(key) diff --git a/host/include/uhd/types/serial.hpp b/host/include/uhd/types/serial.hpp index c134725f5..5c6de162b 100644 --- a/host/include/uhd/types/serial.hpp +++ b/host/include/uhd/types/serial.hpp @@ -116,6 +116,59 @@ namespace uhd{ */ spi_config_t(edge_t edge = EDGE_RISE); }; + + /*! + * The SPI interface class. + * Provides routines to transact SPI and do other useful things which haven't been defined yet. + */ + class UHD_API spi_iface{ + public: + /*! + * Perform a 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 spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ) = 0; + + /*! + * Read from the SPI bus. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write out (be sure to set write bit) + * \param num_bits how many bits in data + * \return spi data + */ + virtual boost::uint32_t read_spi( + int which_slave, + const spi_config_t &config, + boost::uint16_t data, + size_t num_bits + ); + + /*! + * Write to the SPI bus. + * \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 + */ + virtual void write_spi( + int which_slave, + const spi_config_t &config, + boost::uint16_t data, + size_t num_bits + ); + }; } //namespace uhd diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index f60b35e59..59a1302af 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -43,6 +43,7 @@ INSTALL(FILES ### interfaces ### single_usrp.hpp multi_usrp.hpp + mboard_iface.hpp DESTINATION ${INCLUDE_DIR}/uhd/usrp ) diff --git a/host/include/uhd/usrp/dsp_props.hpp b/host/include/uhd/usrp/dsp_props.hpp index 3e1690317..e68e11deb 100644 --- a/host/include/uhd/usrp/dsp_props.hpp +++ b/host/include/uhd/usrp/dsp_props.hpp @@ -39,8 +39,8 @@ namespace uhd{ namespace usrp{ enum dsp_prop_t{ DSP_PROP_NAME, //ro, std::string DSP_PROP_OTHERS, //ro, prop_names_t + DSP_PROP_STREAM_CMD, //wo, stream_cmd_t DSP_PROP_FREQ_SHIFT, //rw, double Hz - DSP_PROP_FREQ_SHIFT_NAMES, //ro, prop_names_t DSP_PROP_CODEC_RATE, //ro, double Sps DSP_PROP_HOST_RATE //rw, double Sps }; diff --git a/host/include/uhd/usrp/mboard_iface.hpp b/host/include/uhd/usrp/mboard_iface.hpp new file mode 100644 index 000000000..784fbc7c5 --- /dev/null +++ b/host/include/uhd/usrp/mboard_iface.hpp @@ -0,0 +1,85 @@ +// +// Copyright 2010-2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_MBOARD_IFACE_HPP +#define INCLUDED_UHD_USRP_MBOARD_IFACE_HPP + +#include <uhd/types/serial.hpp> +#include <uhd/usrp/mboard_eeprom.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <boost/cstdint.hpp> +#include <utility> +#include <string> + +namespace uhd{ namespace usrp{ + +/*! + * The mboard interface class: + * Provides a set of functions to implementation layer. + * Including spi, peek, poke, control... + */ +class mboard_iface : public uhd::i2c_iface, public uhd::spi_iface { +public: + typedef boost::shared_ptr<mboard_iface> sptr; + /*! + * 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; + + /*! + * Write to a serial port. + * \param dev which UART to write to + * \param buf the data to write + */ + virtual void write_uart(boost::uint8_t dev, const std::string &buf) = 0; + + /*! + * Read from a serial port. + * \param dev which UART to read from + * \return the data read from the serial port + */ + virtual std::string read_uart(boost::uint8_t dev) = 0; + +}; + +}} + +#endif //INCLUDED_UHD_USRP_DBOARD_IFACE_HPP diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp index 8855e2b75..a2580954e 100644 --- a/host/include/uhd/usrp/mboard_props.hpp +++ b/host/include/uhd/usrp/mboard_props.hpp @@ -47,8 +47,8 @@ namespace uhd{ namespace usrp{ MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t MBOARD_PROP_TIME_NOW, //rw, time_spec_t MBOARD_PROP_TIME_PPS, //wo, time_spec_t - MBOARD_PROP_STREAM_CMD, //wo, stream_cmd_t - MBOARD_PROP_EEPROM_MAP //wr, mboard_eeprom_t + MBOARD_PROP_EEPROM_MAP, //wr, mboard_eeprom_t + MBOARD_PROP_IFACE, //ro, mboard_iface::sptr }; }} //namespace diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 3c8dd5fac..b161d1278 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -28,6 +28,7 @@ #include <uhd/types/sensors.hpp> #include <uhd/usrp/subdev_spec.hpp> #include <uhd/usrp/dboard_iface.hpp> +#include <uhd/usrp/mboard_iface.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include <vector> @@ -87,6 +88,9 @@ public: //! A wildcard motherboard index static const size_t ALL_MBOARDS = size_t(~0); + //! A wildcard channel index + static const size_t ALL_CHANS = size_t(~0); + //! A wildcard gain element name static const std::string ALL_GAINS; @@ -215,8 +219,9 @@ public: * to ensure that the packets can be aligned by their time specs. * * \param stream_cmd the stream command to issue + * \param chan the channel index 0 to N-1 */ - virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; + virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan = ALL_CHANS) = 0; /*! * Set the clock configuration for the usrp device. @@ -246,6 +251,12 @@ public: * \return a vector of sensor names */ virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0; + + /*! + * Get a handle to the mboard_iface object which controls peripheral access. + * \return a mboard_iface::sptr object + */ + virtual mboard_iface::sptr get_mboard_iface(size_t mboard) = 0; /******************************************************************* * RX methods @@ -282,16 +293,18 @@ public: virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; /*! - * Set the RX sample rate across all channels. + * Set the RX sample rate. * \param rate the rate in Sps + * \param chan the channel index 0 to N-1 */ - virtual void set_rx_rate(double rate) = 0; + virtual void set_rx_rate(double rate, size_t chan = ALL_CHANS) = 0; /*! - * Gets the RX sample rate for all channels. + * Gets the RX sample rate. + * \param chan the channel index 0 to N-1 * \return the rate in Sps */ - virtual double get_rx_rate(void) = 0; + virtual double get_rx_rate(size_t chan = 0) = 0; /*! * Set the RX center frequency. @@ -480,16 +493,18 @@ public: virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; /*! - * Set the TX sample rate across all channels. + * Set the TX sample rate. * \param rate the rate in Sps + * \param chan the channel index 0 to N-1 */ - virtual void set_tx_rate(double rate) = 0; + virtual void set_tx_rate(double rate, size_t chan = ALL_CHANS) = 0; /*! - * Gets the TX sample rate for all channels. + * Gets the TX sample rate. + * \param chan the channel index 0 to N-1 * \return the rate in Sps */ - virtual double get_tx_rate(void) = 0; + virtual double get_tx_rate(size_t chan = 0) = 0; /*! * Set the TX center frequency. diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp index db12241c1..e97ab0298 100644 --- a/host/include/uhd/usrp/tune_helper.hpp +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -32,24 +32,21 @@ namespace uhd{ namespace usrp{ * The ddc cordic is setup to bring the IF down to baseband. * \param subdev the dboard subdevice object with properties * \param ddc the mboard dsp object with properties - * \param chan the channel of the dsp to tune * \param tune_request tune request instructions * \return a tune result struct */ UHD_API tune_result_t tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, size_t chan, - const tune_request_t &tune_request + wax::obj subdev, wax::obj ddc, const tune_request_t &tune_request ); /*! * Calculate the overall frequency from the combination of dboard IF and DDC shift. * \param subdev the dboard subdevice object with properties * \param ddc the mboard dsp object with properties - * \param chan the channel of the dsp to tune * \return the overall tune frequency of the system in Hz */ UHD_API double derive_freq_from_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, size_t chan + wax::obj subdev, wax::obj ddc ); /*! @@ -59,24 +56,21 @@ namespace uhd{ namespace usrp{ * The duc cordic is setup to bring the baseband up to IF. * \param subdev the dboard subdevice object with properties * \param duc the mboard dsp object with properties - * \param chan the channel of the dsp to tune * \param tune_request tune request instructions * \return a tune result struct */ UHD_API tune_result_t tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, size_t chan, - const tune_request_t &tune_request + wax::obj subdev, wax::obj duc, const tune_request_t &tune_request ); /*! * Calculate the overall frequency from the combination of dboard IF and DUC shift. * \param subdev the dboard subdevice object with properties * \param duc the mboard dsp object with properties - * \param chan the channel of the dsp to tune * \return the overall tune frequency of the system in Hz */ UHD_API double derive_freq_from_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, size_t chan + wax::obj subdev, wax::obj duc ); }} diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index 0dee310a8..70f724c2d 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2010 Ettus Research LLC +# Copyright 2010-2011 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 @@ -17,11 +17,10 @@ INSTALL(FILES algorithm.hpp - assert.hpp - assert.ipp + assert_has.hpp + assert_has.ipp byteswap.hpp byteswap.ipp - exception.hpp gain_group.hpp images.hpp pimpl.hpp diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp index d3a07db96..5598d862b 100644 --- a/host/include/uhd/utils/algorithm.hpp +++ b/host/include/uhd/utils/algorithm.hpp @@ -21,24 +21,12 @@ #include <algorithm> #include <boost/range/begin.hpp> #include <boost/range/end.hpp> -#include <boost/range/size.hpp> -/*! \file algorithm.hpp +/*! * Useful templated functions and classes that I like to pretend are part of stl. * Many of the range wrapper functions come with recent versions of boost (1.43). */ -namespace std{ - - /*! - * A wrapper around std::sort that takes a range instead of an iterator. - * - * The elements are sorted into ascending order using the less-than operator. - * - * \param range the range of elements to be sorted - */ - template<typename Range> inline void sort(Range &range){ - return std::sort(boost::begin(range), boost::end(range)); - } +namespace uhd{ /*! * A wrapper around std::sort that takes a range instead of an iterator. @@ -51,18 +39,7 @@ namespace std{ * \return a new range with the elements sorted */ template<typename Range> inline Range sorted(const Range &range){ - Range srange(range); std::sort(srange); return srange; - } - - /*! - * A wrapper around std::reverse that takes a range instead of an iterator. - * - * The elements are reversed into descending order using the less-than operator. - * - * \param range the range of elements to be reversed - */ - template<typename Range> inline void reverse(Range &range){ - return std::reverse(boost::begin(range), boost::end(range)); + Range r(range); std::sort(boost::begin(r), boost::end(r)); return r; } /*! @@ -76,7 +53,7 @@ namespace std{ * \return a new range with the elements reversed */ template<typename Range> inline Range reversed(const Range &range){ - Range srange(range); std::reverse(srange); return srange; + Range r(range); std::reverse(boost::begin(r), boost::end(r)); return r; } /*! @@ -94,35 +71,6 @@ namespace std{ } /*! - * Count the number of appearances of a value in a range. - * - * Uses std::count to count the appearances in the range. - * - * \param range the elements to iterate through - * \param value the value to count in the range - * \return the number of appearances of the value - */ - template<typename Range, typename T> inline - size_t count(const Range &range, const T &value){ - return std::count(boost::begin(range), boost::end(range), value); - } - - /*! - * Are the ranges equal (are their elements equivalent)? - * - * Uses std::equal to search the iterable for an element. - * - * \param range1 the first range of elements - * \param range2 the second range of elements - * \return true when the elements are equivalent - */ - template<typename Range> inline - bool equal(const Range &range1, const Range &range2){ - return (boost::size(range1) == boost::size(range2)) and - std::equal(boost::begin(range1), boost::end(range1), boost::begin(range2)); - } - - /*! * A templated clip implementation. * \param val the value to clip between an upper and lower limit * \param bound1 the upper or lower bound @@ -137,6 +85,6 @@ namespace std{ return val; } -}//namespace std +} //namespace uhd #endif /* INCLUDED_UHD_UTILS_ALGORITHM_HPP */ diff --git a/host/include/uhd/utils/assert.hpp b/host/include/uhd/utils/assert_has.hpp index 7f7b71cfb..eae7652ad 100644 --- a/host/include/uhd/utils/assert.hpp +++ b/host/include/uhd/utils/assert_has.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -15,26 +15,14 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#ifndef INCLUDED_UHD_UTILS_ASSERT_HPP -#define INCLUDED_UHD_UTILS_ASSERT_HPP +#ifndef INCLUDED_UHD_UTILS_ASSERT_HAS_HPP +#define INCLUDED_UHD_UTILS_ASSERT_HAS_HPP #include <uhd/config.hpp> -#include <uhd/utils/exception.hpp> -#include <stdexcept> #include <string> namespace uhd{ - //! The exception to throw when assertions fail - struct UHD_API assert_error : std::runtime_error{ - assert_error(const std::string &what); - }; - - //! Throw an assert error with throw-site information - #define UHD_ASSERT_THROW(_x) if (not (_x)) throw uhd::assert_error( \ - UHD_THROW_SITE_INFO("assertion failed: " + std::string(#_x)) \ - ); else void(0) - /*! * Check that an element is found in a container. * If not, throw a meaningful assertion error. @@ -54,6 +42,6 @@ namespace uhd{ }//namespace uhd -#include <uhd/utils/assert.ipp> +#include <uhd/utils/assert_has.ipp> -#endif /* INCLUDED_UHD_UTILS_ASSERT_HPP */ +#endif /* INCLUDED_UHD_UTILS_ASSERT_HAS_HPP */ diff --git a/host/include/uhd/utils/assert.ipp b/host/include/uhd/utils/assert_has.ipp index 6a8b3e417..7b3c88cb7 100644 --- a/host/include/uhd/utils/assert.ipp +++ b/host/include/uhd/utils/assert_has.ipp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -15,10 +15,11 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#ifndef INCLUDED_UHD_UTILS_ASSERT_IPP -#define INCLUDED_UHD_UTILS_ASSERT_IPP +#ifndef INCLUDED_UHD_UTILS_ASSERT_HAS_IPP +#define INCLUDED_UHD_UTILS_ASSERT_HAS_IPP #include <uhd/utils/algorithm.hpp> +#include <uhd/exception.hpp> #include <boost/format.hpp> #include <boost/foreach.hpp> #include <boost/lexical_cast.hpp> @@ -30,14 +31,14 @@ namespace uhd{ const T &value, const std::string &what ){ - if (std::has(range, value)) return; + if (uhd::has(range, value)) return; std::string possible_values = ""; size_t i = 0; BOOST_FOREACH(const T &v, range){ if (i++ > 0) possible_values += ", "; possible_values += boost::lexical_cast<std::string>(v); } - throw uhd::assert_error(str(boost::format( + throw uhd::assertion_error(str(boost::format( "assertion failed:\n" " %s is not a valid %s.\n" " possible values are: [%s].\n" @@ -49,4 +50,4 @@ namespace uhd{ }//namespace uhd -#endif /* INCLUDED_UHD_UTILS_ASSERT_IPP */ +#endif /* INCLUDED_UHD_UTILS_ASSERT_HAS_IPP */ diff --git a/host/include/uhd/utils/exception.hpp b/host/include/uhd/utils/exception.hpp deleted file mode 100644 index e74c19b9c..000000000 --- a/host/include/uhd/utils/exception.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_UHD_UTILS_EXCEPTION_HPP -#define INCLUDED_UHD_UTILS_EXCEPTION_HPP - -#include <uhd/config.hpp> -#include <boost/current_function.hpp> -#include <stdexcept> -#include <string> - -/*! - * Create a formated string with throw-site information. - * Fills in the function name, file name, and line number. - * \param what the std::exeption message - * \return the formatted exception message - */ -#define UHD_THROW_SITE_INFO(what) std::string( \ - std::string(what) + "\n" + \ - " in " + std::string(BOOST_CURRENT_FUNCTION) + "\n" + \ - " at " + std::string(__FILE__) + ":" + BOOST_STRINGIZE(__LINE__) + "\n" \ -) - -/*! - * Throws an invalid code path exception with throw-site information. - * Use this macro in places that code execution is not supposed to go. - */ -#define UHD_THROW_INVALID_CODE_PATH() \ - throw std::runtime_error(UHD_THROW_SITE_INFO("invalid code path")) - -#endif /* INCLUDED_UHD_UTILS_EXCEPTION_HPP */ diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp index fbca03019..81737423a 100644 --- a/host/include/uhd/utils/props.hpp +++ b/host/include/uhd/utils/props.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -20,8 +20,7 @@ #include <uhd/config.hpp> #include <uhd/wax.hpp> -#include <uhd/utils/exception.hpp> -#include <stdexcept> +#include <uhd/exception.hpp> #include <vector> #include <string> @@ -68,14 +67,14 @@ namespace uhd{ * Throw-site information will be included with this error. */ #define UHD_THROW_PROP_GET_ERROR() \ - throw std::runtime_error(UHD_THROW_SITE_INFO("cannot get this property")) + throw uhd::key_error(UHD_THROW_SITE_INFO("cannot get this property")) /*! * Throw when setting a not-implemented or read-only property. * Throw-site information will be included with this error. */ #define UHD_THROW_PROP_SET_ERROR() \ - throw std::runtime_error(UHD_THROW_SITE_INFO("cannot set this property")) + throw uhd::key_error(UHD_THROW_SITE_INFO("cannot set this property")) } //namespace uhd diff --git a/host/include/uhd/utils/safe_call.hpp b/host/include/uhd/utils/safe_call.hpp index e23e508c8..6b2c210af 100644 --- a/host/include/uhd/utils/safe_call.hpp +++ b/host/include/uhd/utils/safe_call.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_UTILS_SAFE_CALL_HPP #include <uhd/config.hpp> -#include <uhd/utils/exception.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/warning.hpp> //! helper macro for safe call to produce warnings diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp index 14e6734a5..6fd2b8652 100644 --- a/host/include/uhd/wax.hpp +++ b/host/include/uhd/wax.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -19,7 +19,10 @@ #define INCLUDED_WAX_HPP #include <uhd/config.hpp> +#include <uhd/exception.hpp> #include <boost/any.hpp> +#include <typeinfo> +#include <string> /*! * WAX - it's a metaphor! @@ -47,12 +50,6 @@ namespace wax{ /*! - * The wax::bad cast will be thrown when - * cast is called with the wrong typeid. - */ - typedef boost::bad_any_cast bad_cast; - - /*! * WAX object base class: * * A wax obj has two major purposes: @@ -140,7 +137,12 @@ namespace wax{ * \throw wax::bad_cast when the cast fails */ template<class T> T as(void) const{ - return boost::any_cast<T>(resolve()); + try{ + return boost::any_cast<T>(resolve()); + } + catch(const boost::bad_any_cast &e){ + throw uhd::type_error(std::string("") + "Cannot wax cast " + type().name() + " to " + typeid(T).name() + " " + e.what()); + } } private: diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 8096c15d8..dbfa234b6 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -15,6 +15,10 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # +#Creating a shared pointer itself has allocation overhead. +#Define the quick allocator to reduce fast-path overhead. +ADD_DEFINITIONS(-DBOOST_SP_USE_QUICK_ALLOCATOR) + ######################################################################## # Helpful Macros ######################################################################## @@ -97,6 +101,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_BINARY_DIR}/constants.hpp ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/exception.cpp ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp ) diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 6a5a1465d..d43cecfec 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -17,7 +17,7 @@ #include <uhd/convert.hpp> #include <uhd/utils/static.hpp> -#include <uhd/utils/exception.hpp> +#include <uhd/exception.hpp> #include <iostream> using namespace uhd; diff --git a/host/lib/convert/gen_convert_pred.py b/host/lib/convert/gen_convert_pred.py index d2f90bf41..360fbcf44 100644 --- a/host/lib/convert/gen_convert_pred.py +++ b/host/lib/convert/gen_convert_pred.py @@ -21,11 +21,11 @@ TMPL_TEXT = """ /*********************************************************************** * This file was generated by $file on $time.strftime("%c") **********************************************************************/ +\#include <uhd/exception.hpp> \#include <boost/tokenizer.hpp> \#include <boost/lexical_cast.hpp> \#include <boost/detail/endian.hpp> \#include <boost/cstdint.hpp> -\#include <stdexcept> \#include <string> \#include <vector> @@ -37,9 +37,10 @@ enum dir_type{ DIR_CPU_TO_OTW = 1 }; -struct pred_error : std::runtime_error{ - pred_error(const std::string &what) - :std::runtime_error("convert::make_pred: " + what){ +struct pred_error : uhd::value_error{ + pred_error(const std::string &what): + uhd::value_error("convert::make_pred: " + what) + { /* NOP */ } }; diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 386588a08..0002bee6e 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -17,7 +17,7 @@ #include <uhd/device.hpp> #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/algorithm.hpp> #include <boost/foreach.hpp> @@ -25,7 +25,6 @@ #include <boost/weak_ptr.hpp> #include <boost/functional/hash.hpp> #include <boost/tuple/tuple.hpp> -#include <stdexcept> #include <iostream> using namespace uhd; @@ -44,7 +43,7 @@ static size_t hash_device_addr( ){ //combine the hashes of sorted keys/value pairs size_t hash = 0; - BOOST_FOREACH(const std::string &key, std::sorted(dev_addr.keys())){ + BOOST_FOREACH(const std::string &key, uhd::sorted(dev_addr.keys())){ boost::hash_combine(hash, key); boost::hash_combine(hash, dev_addr[key]); } @@ -106,14 +105,14 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ //check that we found any devices if (dev_addr_makers.size() == 0){ - throw std::runtime_error(str( + throw uhd::key_error(str( boost::format("No devices found for ----->\n%s") % hint.to_pp_string() )); } //check that the which index is valid if (dev_addr_makers.size() <= which){ - throw std::runtime_error(str( + throw uhd::index_error(str( boost::format("No device at index %d for ----->\n%s") % which % hint.to_pp_string() )); } @@ -140,7 +139,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ return hash_to_device[dev_hash].lock(); } //create and register a new device - catch(const uhd::assert_error &){ + catch(const uhd::assertion_error &){ device::sptr dev = maker(dev_addr); hash_to_device[dev_hash] = dev; return dev; diff --git a/host/lib/exception.cpp b/host/lib/exception.cpp new file mode 100644 index 000000000..ecb1fe768 --- /dev/null +++ b/host/lib/exception.cpp @@ -0,0 +1,43 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/exception.hpp> +#include <boost/functional/hash.hpp> +#include <boost/format.hpp> + +using namespace uhd; + +exception::exception(const std::string &what): + std::runtime_error(what){/* NOP */} + +#define make_exception_impl(name, class, base) \ + class::class(const std::string &what): \ + base(str(boost::format("%s: %s") % name % what)){} \ + unsigned class::code(void) const{return boost::hash<std::string>()(#class) & 0xfff;} + +make_exception_impl("AssertionError", assertion_error, exception) +make_exception_impl("LookupError", lookup_error, exception) +make_exception_impl("IndexError", index_error, lookup_error) +make_exception_impl("KeyError", key_error, lookup_error) +make_exception_impl("TypeError", type_error, exception) +make_exception_impl("ValueError", value_error, exception) +make_exception_impl("RuntimeError", runtime_error, exception) +make_exception_impl("NotImplementedError", not_implemented_error, runtime_error) +make_exception_impl("EnvironmentError", environment_error, exception) +make_exception_impl("IOError", io_error, environment_error) +make_exception_impl("OSError", os_error, environment_error) +make_exception_impl("SystemError", system_error, exception) diff --git a/host/lib/ic_reg_maps/common.py b/host/lib/ic_reg_maps/common.py index 986093004..a509936b4 100644 --- a/host/lib/ic_reg_maps/common.py +++ b/host/lib/ic_reg_maps/common.py @@ -30,8 +30,8 @@ COMMON_TMPL = """\ \#define INCLUDED_$(name.upper())_HPP \#include <uhd/config.hpp> +\#include <uhd/exception.hpp> \#include <boost/cstdint.hpp> -\#include <stdexcept> \#include <set> class $(name)_t{ @@ -69,7 +69,7 @@ public: } template<typename T> std::set<T> get_changed_addrs(void){ - if (_state == NULL) throw std::runtime_error("no saved state"); + if (_state == NULL) throw uhd::runtime_error("no saved state"); //check each register for changes std::set<T> addrs; #for $reg in $regs diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py index 427217eb6..8481932ed 100755 --- a/host/lib/transport/gen_vrt_if_packet.py +++ b/host/lib/transport/gen_vrt_if_packet.py @@ -31,10 +31,10 @@ TMPL_TEXT = """ * This file was generated by $file on $time.strftime("%c") **********************************************************************/ +\#include <uhd/exception.hpp> \#include <uhd/transport/vrt_if_packet.hpp> \#include <uhd/utils/byteswap.hpp> \#include <boost/detail/endian.hpp> -\#include <stdexcept> \#include <vector> //define the endian macros to convert integers @@ -157,7 +157,7 @@ void vrt::if_hdr_unpack_$(suffix)( //failure case if (if_packet_info.num_packet_words32 < packet_words32) - throw std::runtime_error("bad vrt header or packet fragment"); + throw uhd::value_error("bad vrt header or packet fragment"); */ //Fix for short packets sent from the fpga: // Use the num_packet_words32 passed in as input, @@ -223,7 +223,7 @@ void vrt::if_hdr_unpack_$(suffix)( ########## Variables ########## //another failure case if (packet_words32 < $($num_header_words + $num_trailer_words)) - throw std::runtime_error("bad vrt header or invalid packet length"); + throw uhd::value_error("bad vrt header or invalid packet length"); if_packet_info.num_header_words32 = $num_header_words; if_packet_info.num_payload_words32 = packet_words32 - $($num_header_words + $num_trailer_words); break; diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index cfa77d9ca..6d4df7875 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -16,7 +16,7 @@ // #include "libusb1_base.hpp" -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/types/dict.hpp> #include <boost/weak_ptr.hpp> #include <boost/foreach.hpp> @@ -93,7 +93,7 @@ public: //allocate a new list of devices libusb_device** dev_list; ssize_t ret = libusb_get_device_list(sess->get_context(), &dev_list); - if (ret < 0) throw std::runtime_error("cannot enumerate usb devices"); + if (ret < 0) throw uhd::os_error("cannot enumerate usb devices"); //fill the vector of device references for (size_t i = 0; i < size_t(ret); i++) _devs.push_back( @@ -206,9 +206,9 @@ libusb::device_handle::sptr libusb::device_handle::get_cached_handle(device::spt handles[dev->get()] = new_handle; return new_handle; } - catch(const std::exception &e){ + catch(const uhd::exception &e){ std::cerr << "USB open failed: see the application notes for your device." << std::endl; - throw std::runtime_error(e.what()); + throw; } } diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index b425843fa..697944089 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -20,7 +20,7 @@ #include <uhd/transport/bounded_buffer.hpp> #include <uhd/transport/buffer_pool.hpp> #include <uhd/utils/thread_priority.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <boost/function.hpp> #include <boost/foreach.hpp> #include <boost/thread/thread.hpp> @@ -33,6 +33,17 @@ using namespace uhd::transport; static const size_t DEFAULT_NUM_XFERS = 16; //num xfers static const size_t DEFAULT_XFER_SIZE = 32*512; //bytes +//! helper function: handles all async callbacks +static void libusb_async_cb(libusb_transfer *lut){ + (*static_cast<boost::function<void()> *>(lut->user_data))(); +} + +//! callback to free transfer upon cancellation +static void cancel_transfer_cb(libusb_transfer *lut){ + if (lut->status == LIBUSB_TRANSFER_CANCELLED) libusb_free_transfer(lut); + else std::cout << "libusb cancel_transfer unexpected status " << lut->status << std::endl; +} + /*********************************************************************** * Reusable managed receiver buffer: * - Associated with a particular libusb transfer struct. @@ -79,7 +90,8 @@ public: void commit(size_t len){ if (_expired) return; _lut->length = len; - UHD_ASSERT_THROW(libusb_submit_transfer(_lut) == 0); + if(len == 0) libusb_async_cb(_lut); + else UHD_ASSERT_THROW(libusb_submit_transfer(_lut) == 0); _expired = true; } @@ -100,17 +112,6 @@ private: bool _expired; }; -//! helper function: handles all async callbacks -static void libusb_async_cb(libusb_transfer *lut){ - (*static_cast<boost::function<void()> *>(lut->user_data))(); -} - -//! callback to free transfer upon cancellation -static void cancel_transfer_cb(libusb_transfer *lut) { - if(lut->status == LIBUSB_TRANSFER_CANCELLED) libusb_free_transfer(lut); - else std::cout << "cancel_transfer unexpected status " << lut->status << std::endl; -} - /*********************************************************************** * USB zero_copy device class **********************************************************************/ diff --git a/host/lib/transport/usb_dummy_impl.cpp b/host/lib/transport/usb_dummy_impl.cpp index 8a9772e7f..930678405 100644 --- a/host/lib/transport/usb_dummy_impl.cpp +++ b/host/lib/transport/usb_dummy_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -18,7 +18,7 @@ #include <uhd/transport/usb_device_handle.hpp> #include <uhd/transport/usb_control.hpp> #include <uhd/transport/usb_zero_copy.hpp> -#include <uhd/utils/exception.hpp> +#include <uhd/exception.hpp> using namespace uhd; using namespace uhd::transport; @@ -28,12 +28,12 @@ std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list(boost::u } usb_control::sptr usb_control::make(usb_device_handle::sptr){ - throw std::runtime_error("no usb support -> usb_control::make not implemented"); + throw uhd::not_implemented_error("no usb support -> usb_control::make not implemented"); } usb_zero_copy::sptr usb_zero_copy::make( usb_device_handle::sptr, size_t, size_t, const device_addr_t & ){ - throw std::runtime_error("no usb support -> usb_zero_copy::make not implemented"); + throw uhd::not_implemented_error("no usb support -> usb_zero_copy::make not implemented"); } diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 6f3ac0421..d74b2c13c 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -20,7 +20,7 @@ #include <uhd/config.hpp> #include <uhd/device.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/types/io_type.hpp> #include <uhd/types/otw_type.hpp> @@ -300,18 +300,18 @@ template <typename T> UHD_INLINE T get_context_code( typedef boost::function<bool(managed_send_buffs_t &)> get_send_buffs_t; typedef boost::function<void(boost::uint32_t *, uhd::transport::vrt::if_packet_info_t &)> vrt_packer_t; + static const boost::uint64_t zeros = 0; + struct send_state{ //init the expected seq number size_t next_packet_seq; managed_send_buffs_t managed_buffs; - const boost::uint64_t zeros; std::vector<const void *> zero_buffs; std::vector<const void *> io_buffs; send_state(size_t width = 1): next_packet_seq(0), managed_buffs(width), - zeros(0), zero_buffs(width, &zeros), io_buffs(0) //resized later { diff --git a/host/lib/types/device_addr.cpp b/host/lib/types/device_addr.cpp index 14afaa24b..193f76f8c 100644 --- a/host/lib/types/device_addr.cpp +++ b/host/lib/types/device_addr.cpp @@ -16,10 +16,11 @@ // #include <uhd/types/device_addr.hpp> -#include <boost/algorithm/string.hpp> //for trim +#include <boost/algorithm/string.hpp> #include <boost/tokenizer.hpp> #include <boost/foreach.hpp> #include <boost/format.hpp> +#include <boost/regex.hpp> #include <stdexcept> #include <sstream> @@ -47,7 +48,7 @@ device_addr_t::device_addr_t(const std::string &args){ goto continue_next_arg; } } - throw std::runtime_error("invalid args string: "+args); + throw uhd::value_error("invalid args string: "+args); continue_next_arg: continue; } } @@ -71,3 +72,51 @@ std::string device_addr_t::to_string(void) const{ } return args_str; } + +#include <uhd/utils/warning.hpp> + +device_addrs_t uhd::separate_device_addr(const device_addr_t &dev_addr){ + //------------ support old deprecated way and print warning -------- + if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){ + std::vector<std::string> addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" ")); + if (addrs.size() > 1){ + device_addr_t fixed_dev_addr = dev_addr; + fixed_dev_addr.pop("addr"); + for (size_t i = 0; i < addrs.size(); i++){ + fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i]; + } + uhd::warning::post( + "addr = <space separated list of ip addresses> is deprecated.\n" + "To address a multi-device, use multiple <key><index> = <val>.\n" + "See the USRP-NXXX application notes. Two device example:\n" + " addr0 = 192.168.10.2\n" + " addr1 = 192.168.10.3\n" + ); + return separate_device_addr(fixed_dev_addr); + } + } + //------------------------------------------------------------------ + device_addrs_t dev_addrs; + BOOST_FOREACH(const std::string &key, dev_addr.keys()){ + boost::cmatch matches; + if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){ + throw std::runtime_error("unknown key format: " + key); + } + std::string key_part(matches[1].first, matches[1].second); + std::string num_part(matches[2].first, matches[2].second); + size_t num = (num_part.empty())? 0 : boost::lexical_cast<size_t>(num_part); + dev_addrs.resize(std::max(num+1, dev_addrs.size())); + dev_addrs[num][key_part] = dev_addr[key]; + } + return dev_addrs; +} + +device_addr_t uhd::combine_device_addrs(const device_addrs_t &dev_addrs){ + device_addr_t dev_addr; + for (size_t i = 0; i < dev_addrs.size(); i++){ + BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){ + dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key]; + } + } + return dev_addr; +} diff --git a/host/lib/types/mac_addr.cpp b/host/lib/types/mac_addr.cpp index cf3c3fa97..a5cb90f97 100644 --- a/host/lib/types/mac_addr.cpp +++ b/host/lib/types/mac_addr.cpp @@ -16,12 +16,11 @@ // #include <uhd/types/mac_addr.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <boost/tokenizer.hpp> #include <boost/foreach.hpp> #include <boost/format.hpp> #include <boost/cstdint.hpp> -#include <stdexcept> #include <sstream> using namespace uhd; @@ -40,7 +39,7 @@ mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){ try{ if (mac_addr_str.size() != 17){ - throw std::runtime_error("expected exactly 17 characters"); + throw uhd::value_error("expected exactly 17 characters"); } //split the mac addr hex string at the colons @@ -55,7 +54,7 @@ mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){ } catch(std::exception const& e){ - throw std::runtime_error(str( + throw uhd::value_error(str( boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what() )); } diff --git a/host/lib/types/ranges.cpp b/host/lib/types/ranges.cpp index 4a0d05d80..6e39bc688 100644 --- a/host/lib/types/ranges.cpp +++ b/host/lib/types/ranges.cpp @@ -16,10 +16,10 @@ // #include <uhd/types/ranges.hpp> +#include <uhd/exception.hpp> #include <boost/math/special_functions/round.hpp> #include <boost/foreach.hpp> #include <algorithm> -#include <stdexcept> #include <sstream> using namespace uhd; @@ -48,7 +48,7 @@ range_t::range_t( _impl(UHD_PIMPL_MAKE(impl, (start, stop, step))) { if (stop < start){ - throw std::invalid_argument("cannot make range where stop < start"); + throw uhd::value_error("cannot make range where stop < start"); } } @@ -78,11 +78,11 @@ const std::string range_t::to_pp_string(void) const{ **********************************************************************/ void check_meta_range_monotonic(const meta_range_t &mr){ if (mr.empty()){ - throw std::runtime_error("meta-range cannot be empty"); + throw uhd::value_error("meta-range cannot be empty"); } for (size_t i = 1; i < mr.size(); i++){ if (mr.at(i).start() < mr.at(i-1).stop()){ - throw std::runtime_error("meta-range is not monotonic"); + throw uhd::value_error("meta-range is not monotonic"); } } } diff --git a/host/lib/types/sensors.cpp b/host/lib/types/sensors.cpp index dd8a170ea..52a63d14c 100644 --- a/host/lib/types/sensors.cpp +++ b/host/lib/types/sensors.cpp @@ -16,7 +16,7 @@ // #include <uhd/types/sensors.hpp> -#include <uhd/utils/exception.hpp> +#include <uhd/exception.hpp> #include <boost/lexical_cast.hpp> #include <boost/format.hpp> diff --git a/host/lib/types/serial.cpp b/host/lib/types/serial.cpp index 9acf7156a..aa1133e72 100644 --- a/host/lib/types/serial.cpp +++ b/host/lib/types/serial.cpp @@ -54,3 +54,25 @@ byte_vector_t i2c_iface::read_eeprom( } return bytes; } + +boost::uint32_t spi_iface::read_spi( + int which_slave, + const spi_config_t &config, + boost::uint16_t data, + size_t num_bits +){ + return transact_spi( + which_slave, config, data, num_bits, true + ); +} + +void spi_iface::write_spi( + int which_slave, + const spi_config_t &config, + boost::uint16_t data, + size_t num_bits +){ + transact_spi( + which_slave, config, data, num_bits, false + ); +} diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 97a54a798..59dabbd58 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -31,7 +31,6 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/multi_usrp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/subdev_spec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tune_helper.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/wrapper_utils.hpp ) INCLUDE_SUBDIRECTORY(dboard) diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index b319289db..3fffeab0c 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -18,7 +18,7 @@ #include <uhd/usrp/subdev_props.hpp> #include <uhd/types/dict.hpp> #include <uhd/types/ranges.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/warning.hpp> #include <uhd/usrp/dboard_base.hpp> @@ -193,7 +193,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ANTENNA: if (val.as<std::string>().empty()) return; - throw std::runtime_error("no selectable antennas on this board"); + throw uhd::value_error("no selectable antennas on this board"); case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it @@ -300,7 +300,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ANTENNA: if (val.as<std::string>().empty()) return; - throw std::runtime_error("no selectable antennas on this board"); + throw uhd::value_error("no selectable antennas on this board"); case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 98d9479fc..b984608ca 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -21,7 +21,7 @@ #include "max2118_regs.hpp" #include <uhd/utils/static.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/utils/warning.hpp> #include <uhd/types/ranges.hpp> @@ -83,8 +83,8 @@ private: void set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ - start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); - stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0x5)); + start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0x5)); + stop_reg = boost::uint8_t(uhd::clip(int(stop_reg), 0x0, 0x5)); for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t) - 1){ int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) - 1 ? sizeof(boost::uint32_t) - 1 : stop_reg - start_addr + 1; @@ -112,8 +112,8 @@ private: void read_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ static const boost::uint8_t status_addr = 0x0; - start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x1)); - stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0x1)); + start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0x1)); + stop_reg = boost::uint8_t(uhd::clip(int(stop_reg), 0x0, 0x1)); for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t)){ int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) ? sizeof(boost::uint32_t) : stop_reg - start_addr + 1; @@ -237,8 +237,8 @@ void dbsrx::set_lo_freq(double target_freq){ bool update_filter_settings = false; //choose refclock std::vector<double> clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); - const double max_clock_rate = std::sorted(clock_rates).back(); - BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){ + const double max_clock_rate = uhd::sorted(clock_rates).back(); + BOOST_FOREACH(ref_clock, uhd::reversed(uhd::sorted(clock_rates))){ if (ref_clock > 27.0e6) continue; if (size_t(max_clock_rate/ref_clock)%2 == 1) continue; //reject asymmetric clocks (odd divisors) @@ -485,14 +485,14 @@ void dbsrx::set_gain(double gain, const std::string &name){ **********************************************************************/ void dbsrx::set_bandwidth(double bandwidth){ //clip the input - bandwidth = std::clip<double>(bandwidth, 4e6, 33e6); + bandwidth = uhd::clip<double>(bandwidth, 4e6, 33e6); double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); //NOTE: _max2118_write_regs.m_divider set in set_lo_freq //compute f_dac setting - _max2118_write_regs.f_dac = std::clip<int>(int((((bandwidth*_max2118_write_regs.m_divider)/ref_clock) - 4)/0.145),0,127); + _max2118_write_regs.f_dac = uhd::clip<int>(int((((bandwidth*_max2118_write_regs.m_divider)/ref_clock) - 4)/0.145),0,127); //determine actual bandwidth _bandwidth = double((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac)); diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp index f4b797995..e7b42cb05 100644 --- a/host/lib/usrp/dboard/db_dbsrx2.cpp +++ b/host/lib/usrp/dboard/db_dbsrx2.cpp @@ -19,7 +19,7 @@ #include "max2112_regs.hpp" #include <uhd/utils/static.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/types/ranges.hpp> #include <uhd/types/sensors.hpp> @@ -79,8 +79,8 @@ private: void set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ - start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0xB)); - stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0xB)); + start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0xB)); + stop_reg = boost::uint8_t(uhd::clip(int(stop_reg), 0x0, 0xB)); for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t) - 1){ int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) - 1 ? sizeof(boost::uint32_t) - 1 : stop_reg - start_addr + 1; @@ -108,8 +108,8 @@ private: void read_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ static const boost::uint8_t status_addr = 0xC; - start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0xD)); - stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0xD)); + start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0xD)); + stop_reg = boost::uint8_t(uhd::clip(int(stop_reg), 0x0, 0xD)); for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t)){ int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) ? sizeof(boost::uint32_t) : stop_reg - start_addr + 1; @@ -216,7 +216,7 @@ dbsrx2::~dbsrx2(void){ * Tuning **********************************************************************/ void dbsrx2::set_lo_freq(double target_freq){ - //target_freq = std::clip(target_freq, dbsrx2_freq_range.min, dbsrx2_freq_range.max); + //target_freq = uhd::clip(target_freq, dbsrx2_freq_range.min, dbsrx2_freq_range.max); //variables used in the calculation below int scaler = target_freq > 1125e6 ? 2 : 4; @@ -330,7 +330,7 @@ void dbsrx2::set_gain(double gain, const std::string &name){ **********************************************************************/ void dbsrx2::set_bandwidth(double bandwidth){ //clip the input - bandwidth = std::clip<double>(bandwidth, 4e6, 40e6); + bandwidth = uhd::clip<double>(bandwidth, 4e6, 40e6); _max2112_write_regs.lp = int((bandwidth/1e6 - 4)/0.29 + 12); _bandwidth = double(4 + (_max2112_write_regs.lp - 12) * 0.29)*1e6; diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 3e3cf00f2..4d8222a52 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -37,7 +37,7 @@ #include <uhd/usrp/subdev_props.hpp> #include <uhd/types/ranges.hpp> #include <uhd/types/sensors.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/utils/warning.hpp> @@ -245,7 +245,7 @@ static double rx_pga0_gain_to_dac_volts(double &gain, double range){ static const double slope = (max_volts-min_volts)/(range); //calculate the voltage for the aux dac - double dac_volts = std::clip<double>(gain*slope + min_volts, max_volts, min_volts); + double dac_volts = uhd::clip<double>(gain*slope + min_volts, max_volts, min_volts); //the actual gain setting gain = (dac_volts - min_volts)/slope; diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index af025952e..d264c9ca4 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -28,7 +28,7 @@ //gain range: [0:1dB:115dB] #include <uhd/utils/static.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/utils/warning.hpp> #include <uhd/types/ranges.hpp> @@ -241,7 +241,7 @@ static std::string get_band(double freq) { static double gain_interp(double gain, boost::array<double, 17> db_vector, boost::array<double, 17> volts_vector) { double volts; - gain = std::clip<double>(gain, db_vector.front(), db_vector.back()); //let's not get carried away here + gain = uhd::clip<double>(gain, db_vector.front(), db_vector.back()); //let's not get carried away here boost::uint8_t gain_step = 0; //find which bin we're in @@ -288,7 +288,7 @@ static double rf_gain_to_voltage(double gain, double lo_freq){ //this is the voltage at the USRP DAC output double dac_volts = gain_volts / opamp_gain; - dac_volts = std::clip<double>(dac_volts, 0.0, 3.3); + dac_volts = uhd::clip<double>(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx RF AGC gain: %f dB, dac_volts: %f V" @@ -311,7 +311,7 @@ static double if_gain_to_voltage(double gain){ double gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); double dac_volts = gain_volts / opamp_gain; - dac_volts = std::clip<double>(dac_volts, 0.0, 3.3); + dac_volts = uhd::clip<double>(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx IF AGC gain: %f dB, dac_volts: %f V" diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index f0a4c000e..cef4bee4a 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -17,7 +17,7 @@ #include <uhd/usrp/subdev_props.hpp> #include <uhd/types/ranges.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/warning.hpp> #include <uhd/usrp/dboard_base.hpp> diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 0bc2d0ca1..2e9a1edc8 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -69,7 +69,7 @@ #include <uhd/usrp/subdev_props.hpp> #include <uhd/types/ranges.hpp> #include <uhd/types/sensors.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/utils/warning.hpp> diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index f4f74eb86..9d25b30a5 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -49,7 +49,7 @@ #include "max2829_regs.hpp" #include <uhd/utils/static.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/utils/warning.hpp> #include <uhd/types/ranges.hpp> @@ -358,7 +358,7 @@ void xcvr2450::set_rx_ant(const std::string &ant){ */ static int gain_to_tx_vga_reg(double &gain){ //calculate the register value - int reg = std::clip(boost::math::iround(gain*60/30.0) + 3, 0, 63); + int reg = uhd::clip(boost::math::iround(gain*60/30.0) + 3, 0, 63); //calculate the actual gain value if (reg < 4) gain = 0; @@ -376,7 +376,7 @@ static int gain_to_tx_vga_reg(double &gain){ * \return gain enum value */ static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(double &gain){ - int reg = std::clip(boost::math::iround(gain*3/5.0), 0, 3); + int reg = uhd::clip(boost::math::iround(gain*3/5.0), 0, 3); switch(reg){ case 0: gain = 0; @@ -401,7 +401,7 @@ static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(double &gain){ * \return 5 bit the register value */ static int gain_to_rx_vga_reg(double &gain){ - int reg = std::clip(boost::math::iround(gain/2.0), 0, 31); + int reg = uhd::clip(boost::math::iround(gain/2.0), 0, 31); gain = double(reg*2); return reg; } @@ -413,7 +413,7 @@ static int gain_to_rx_vga_reg(double &gain){ * \return 2 bit the register value */ static int gain_to_rx_lna_reg(double &gain){ - int reg = std::clip(boost::math::iround(gain*2/30.5) + 1, 0, 3); + int reg = uhd::clip(boost::math::iround(gain*2/30.5) + 1, 0, 3); switch(reg){ case 0: case 1: gain = 0; break; @@ -456,7 +456,7 @@ void xcvr2450::set_rx_gain(double gain, const std::string &name){ * Bandwidth Handling **********************************************************************/ static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(double &bandwidth){ - int reg = std::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3); + int reg = uhd::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3); switch(reg){ case 1: // bandwidth < 15MHz @@ -473,7 +473,7 @@ static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(double } static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(double &bandwidth, double requested_bandwidth){ - int reg = std::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22); + int reg = uhd::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22); switch(reg){ case 18: // requested_bandwidth < 92.5% @@ -496,7 +496,7 @@ static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(double &ba } static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double &bandwidth){ - int reg = std::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11); + int reg = uhd::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11); switch(reg){ case 0: // bandwidth < 7.5MHz diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp index 6c4e29d9e..999dd9ffc 100644 --- a/host/lib/usrp/dboard_base.cpp +++ b/host/lib/usrp/dboard_base.cpp @@ -59,12 +59,12 @@ dboard_id_t dboard_base::get_tx_id(void){ **********************************************************************/ xcvr_dboard_base::xcvr_dboard_base(ctor_args_t args) : dboard_base(args){ if (get_rx_id() == dboard_id_t::none()){ - throw std::runtime_error(str(boost::format( + throw uhd::runtime_error(str(boost::format( "cannot create xcvr board when the rx id is \"%s\"" ) % dboard_id_t::none().to_pp_string())); } if (get_tx_id() == dboard_id_t::none()){ - throw std::runtime_error(str(boost::format( + throw uhd::runtime_error(str(boost::format( "cannot create xcvr board when the tx id is \"%s\"" ) % dboard_id_t::none().to_pp_string())); } @@ -79,7 +79,7 @@ xcvr_dboard_base::~xcvr_dboard_base(void){ **********************************************************************/ rx_dboard_base::rx_dboard_base(ctor_args_t args) : dboard_base(args){ if (get_tx_id() != dboard_id_t::none()){ - throw std::runtime_error(str(boost::format( + throw uhd::runtime_error(str(boost::format( "cannot create rx board when the tx id is \"%s\"" " -> expected a tx id of \"%s\"" ) % get_tx_id().to_pp_string() % dboard_id_t::none().to_pp_string())); @@ -91,11 +91,11 @@ rx_dboard_base::~rx_dboard_base(void){ } void rx_dboard_base::tx_get(const wax::obj &, wax::obj &){ - throw std::runtime_error("cannot call tx_get on a rx dboard"); + throw uhd::runtime_error("cannot call tx_get on a rx dboard"); } void rx_dboard_base::tx_set(const wax::obj &, const wax::obj &){ - throw std::runtime_error("cannot call tx_set on a rx dboard"); + throw uhd::runtime_error("cannot call tx_set on a rx dboard"); } /*********************************************************************** @@ -103,7 +103,7 @@ void rx_dboard_base::tx_set(const wax::obj &, const wax::obj &){ **********************************************************************/ tx_dboard_base::tx_dboard_base(ctor_args_t args) : dboard_base(args){ if (get_rx_id() != dboard_id_t::none()){ - throw std::runtime_error(str(boost::format( + throw uhd::runtime_error(str(boost::format( "cannot create tx board when the rx id is \"%s\"" " -> expected a rx id of \"%s\"" ) % get_rx_id().to_pp_string() % dboard_id_t::none().to_pp_string())); @@ -115,9 +115,9 @@ tx_dboard_base::~tx_dboard_base(void){ } void tx_dboard_base::rx_get(const wax::obj &, wax::obj &){ - throw std::runtime_error("cannot call rx_get on a tx dboard"); + throw uhd::runtime_error("cannot call rx_get on a tx dboard"); } void tx_dboard_base::rx_set(const wax::obj &, const wax::obj &){ - throw std::runtime_error("cannot call rx_set on a tx dboard"); + throw uhd::runtime_error("cannot call rx_set on a tx dboard"); } diff --git a/host/lib/usrp/dboard_eeprom.cpp b/host/lib/usrp/dboard_eeprom.cpp index c47390bf8..c1e44fb74 100644 --- a/host/lib/usrp/dboard_eeprom.cpp +++ b/host/lib/usrp/dboard_eeprom.cpp @@ -16,7 +16,8 @@ // #include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> +#include <boost/foreach.hpp> #include <boost/format.hpp> #include <algorithm> #include <iostream> @@ -128,7 +129,7 @@ void dboard_eeprom_t::load(i2c_iface &iface, boost::uint8_t addr){ &bytes.at(DB_EEPROM_SERIAL+DB_EEPROM_SERIAL_LEN)) ); - }catch(const uhd::assert_error &){ + }catch(const uhd::assertion_error &){ id = dboard_id_t::none(); serial = ""; } diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 75594e670..9055905b1 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -20,7 +20,7 @@ #include <uhd/usrp/subdev_props.hpp> #include <uhd/utils/warning.hpp> #include <uhd/utils/static.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/types/dict.hpp> #include <boost/tuple/tuple.hpp> #include <boost/format.hpp> @@ -50,7 +50,7 @@ void dboard_manager::register_dboard( ){ //std::cout << "registering: " << name << std::endl; if (get_id_to_args_map().has_key(dboard_id)){ - throw std::runtime_error(str(boost::format( + throw uhd::key_error(str(boost::format( "The dboard id %s is already registered to %s." ) % dboard_id.to_string() % dboard_id.to_pp_string())); } @@ -315,7 +315,7 @@ prop_names_t dboard_manager_impl::get_tx_subdev_names(void){ } wax::obj dboard_manager_impl::get_rx_subdev(const std::string &subdev_name){ - if (not _rx_dboards.has_key(subdev_name)) throw std::invalid_argument( + if (not _rx_dboards.has_key(subdev_name)) throw uhd::key_error( str(boost::format("Unknown rx subdev name %s") % subdev_name) ); //get a link to the rx subdev proxy @@ -323,7 +323,7 @@ wax::obj dboard_manager_impl::get_rx_subdev(const std::string &subdev_name){ } wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ - if (not _tx_dboards.has_key(subdev_name)) throw std::invalid_argument( + if (not _tx_dboards.has_key(subdev_name)) throw uhd::key_error( str(boost::format("Unknown tx subdev name %s") % subdev_name) ); //get a link to the tx subdev proxy diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp index 576c4639f..a3a557060 100644 --- a/host/lib/usrp/dsp_utils.cpp +++ b/host/lib/usrp/dsp_utils.cpp @@ -17,7 +17,7 @@ #include <uhd/usrp/dsp_utils.hpp> #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <boost/assign/list_of.hpp> #include <boost/tuple/tuple.hpp> #include <boost/math/special_functions/round.hpp> @@ -44,7 +44,7 @@ boost::uint32_t dsp_type1::calc_rx_mux_word(subdev_conn_t subdev_conn){ case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DDC0Q=ADC0Q, DDC0I=ADC0I case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DDC0Q=ADC0I, DDC0I=ADC0Q case SUBDEV_CONN_REAL_I: return (0xf << 4) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0I - case SUBDEV_CONN_REAL_Q: return (0x1 << 4) | (0xf << 0); //DDC0Q=ADC0Q, DDC0I=ZERO + case SUBDEV_CONN_REAL_Q: return (0xf << 4) | (0x1 << 0); //DDC0Q=ZERO, DDC0I=ADC0Q default: UHD_THROW_INVALID_CODE_PATH(); } } diff --git a/host/lib/usrp/gps_ctrl.cpp b/host/lib/usrp/gps_ctrl.cpp index b1062fa39..e0ab6de90 100644 --- a/host/lib/usrp/gps_ctrl.cpp +++ b/host/lib/usrp/gps_ctrl.cpp @@ -16,11 +16,10 @@ // #include <uhd/usrp/gps_ctrl.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <boost/cstdint.hpp> -#include <string> #include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/thread.hpp> +#include <boost/thread/thread.hpp> #include <boost/algorithm/string/trim.hpp> #include <boost/tokenizer.hpp> @@ -168,7 +167,7 @@ public: break; case GPS_TYPE_NONE: default: - throw std::runtime_error("get_time(): Unsupported GPS or no GPS detected\n"); + throw uhd::runtime_error("get_time(): Unsupported GPS or no GPS detected\n"); break; } return now; diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 2bad83b3c..ddcad41cf 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -16,7 +16,7 @@ // #include <uhd/usrp/misc_utils.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/utils/gain_group.hpp> #include <uhd/usrp/dboard_eeprom.hpp> @@ -167,7 +167,7 @@ static void verify_xx_subdev_spec( BOOST_FOREACH(subdev_spec_pair_t &pair, subdev_spec){ //empty db name means select dboard automatically if (pair.db_name.empty()){ - if (dboard_names.size() != 1) throw std::runtime_error( + if (dboard_names.size() != 1) throw uhd::value_error( "A daughterboard name must be provided for multi-slot motherboards: " + subdev_spec.to_string() ); pair.db_name = dboard_names.front(); @@ -178,7 +178,7 @@ static void verify_xx_subdev_spec( //empty sd name means select the subdev automatically if (pair.sd_name.empty()){ - if (subdev_names.size() != 1) throw std::runtime_error( + if (subdev_names.size() != 1) throw uhd::value_error( "A subdevice name must be provided for multi-subdev daughterboards: " + subdev_spec.to_string() ); pair.sd_name = subdev_names.front(); @@ -186,7 +186,7 @@ static void verify_xx_subdev_spec( uhd::assert_has(subdev_names, pair.sd_name, xx_type + " subdev name"); } }catch(const std::exception &e){ - throw std::runtime_error(str(boost::format( + throw uhd::value_error(str(boost::format( "Validate %s subdev spec failed: %s\n %s" ) % xx_type % subdev_spec.to_string() % e.what())); } @@ -196,11 +196,11 @@ static void verify_xx_subdev_spec( wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)]; BOOST_FOREACH(const std::string &sd_name, dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>()){ try{ - bool enable = std::has(subdev_spec, subdev_spec_pair_t(db_name, sd_name)); + bool enable = uhd::has(subdev_spec, subdev_spec_pair_t(db_name, sd_name)); dboard[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)][SUBDEV_PROP_ENABLED] = enable; } catch(const std::exception &e){ - throw std::runtime_error(str(boost::format( + throw uhd::runtime_error(str(boost::format( "Cannot set enabled property on subdevice %s:%s\n %s" ) % db_name % sd_name % e.what())); } diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 73bac029d..83cbf339b 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -15,10 +15,10 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#include "wrapper_utils.hpp" #include <uhd/usrp/multi_usrp.hpp> #include <uhd/usrp/tune_helper.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/usrp/mboard_iface.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/warning.hpp> #include <uhd/utils/gain_group.hpp> #include <uhd/usrp/subdev_props.hpp> @@ -29,8 +29,8 @@ #include <boost/thread.hpp> #include <boost/foreach.hpp> #include <boost/format.hpp> -#include <stdexcept> #include <iostream> +#include <cmath> using namespace uhd; using namespace uhd::usrp; @@ -38,7 +38,48 @@ using namespace uhd::usrp; const std::string multi_usrp::ALL_GAINS = ""; /*********************************************************************** - * Simple USRP Implementation + * Helper methods + **********************************************************************/ +static inline uhd::freq_range_t add_dsp_shift( + const uhd::freq_range_t &range, + wax::obj dsp +){ + double codec_rate = dsp[uhd::usrp::DSP_PROP_CODEC_RATE].as<double>(); + return uhd::freq_range_t(range.start() - codec_rate/2.0, range.stop() + codec_rate/2.0); +} + +static inline void do_samp_rate_warning_message( + double target_rate, + double actual_rate, + const std::string &xx +){ + static const double max_allowed_error = 1.0; //Sps + if (std::abs(target_rate - actual_rate) > max_allowed_error){ + uhd::warning::post(str(boost::format( + "The hardware does not support the requested %s sample rate:\n" + "Target sample rate: %f MSps\n" + "Actual sample rate: %f MSps\n" + ) % xx % (target_rate/1e6) % (actual_rate/1e6))); + } +} + +static inline void do_tune_freq_warning_message( + double target_freq, + double actual_freq, + const std::string &xx +){ + static const double max_allowed_error = 1.0; //Hz + if (std::abs(target_freq - actual_freq) > max_allowed_error){ + uhd::warning::post(str(boost::format( + "The hardware does not support the requested %s frequency:\n" + "Target frequency: %f MHz\n" + "Actual frequency: %f MHz\n" + ) % xx % (target_freq/1e6) % (actual_freq/1e6))); + } +} + +/*********************************************************************** + * Multi USRP Implementation **********************************************************************/ class multi_usrp_impl : public multi_usrp{ public: @@ -85,17 +126,14 @@ public: //----------- rx side of life ---------------------------------- for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ - buff += str(boost::format( - " RX DSP %d: %s\n" - ) % m - % _rx_dsp(m)[DSP_PROP_NAME].as<std::string>() - ); for (; chan < (m + 1)*get_rx_subdev_spec(m).size(); chan++){ buff += str(boost::format( " RX Channel: %u\n" + " RX DSP: %s\n" " RX Dboard: %s\n" " RX Subdev: %s\n" ) % chan + % _rx_dsp(chan)[DSP_PROP_NAME].as<std::string>() % _rx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>() % _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>() ); @@ -104,17 +142,14 @@ public: //----------- tx side of life ---------------------------------- for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ - buff += str(boost::format( - " TX DSP %d: %s\n" - ) % m - % _tx_dsp(m)[DSP_PROP_NAME].as<std::string>() - ); for (; chan < (m + 1)*get_tx_subdev_spec(m).size(); chan++){ buff += str(boost::format( " TX Channel: %u\n" + " TX DSP: %s\n" " TX Dboard: %s\n" " TX Subdev: %s\n" ) % chan + % _tx_dsp(chan)[DSP_PROP_NAME].as<std::string>() % _tx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>() % _tx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>() ); @@ -159,7 +194,7 @@ public: while(true){ if (get_time_last_pps() != time_start_last_pps) break; if ((get_time_now() - time_start) > time_spec_t(1.1)){ - throw std::runtime_error( + throw uhd::runtime_error( "Board 0 may not be getting a PPS signal!\n" "No PPS detected within the time interval.\n" "See the application notes for your device.\n" @@ -194,9 +229,13 @@ public: return true; } - void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - for (size_t m = 0; m < get_num_mboards(); m++){ - _mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd; + void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan){ + if (chan != ALL_CHANS){ + _rx_dsp(chan)[DSP_PROP_STREAM_CMD] = stream_cmd; + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + issue_stream_cmd(stream_cmd, c); } } @@ -221,6 +260,10 @@ public: std::vector<std::string> get_mboard_sensor_names(size_t mboard){ return _mboard(mboard)[MBOARD_PROP_SENSOR_NAMES].as<prop_names_t>(); } + + mboard_iface::sptr get_mboard_iface(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_IFACE].as<mboard_iface::sptr>(); + } /******************************************************************* * RX methods @@ -240,36 +283,44 @@ public: } size_t get_rx_num_channels(void){ - return rx_cpm()*get_num_mboards(); //total num channels + size_t sum = 0; + for (size_t m = 0; m < get_num_mboards(); m++){ + sum += get_rx_subdev_spec(m).size(); + } + return sum; } std::string get_rx_subdev_name(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>(); } - void set_rx_rate(double rate){ - for (size_t m = 0; m < get_num_mboards(); m++){ - _rx_dsp(m)[DSP_PROP_HOST_RATE] = rate; + void set_rx_rate(double rate, size_t chan){ + if (chan != ALL_CHANS){ + _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + do_samp_rate_warning_message(rate, get_rx_rate(chan), "RX"); + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + set_rx_rate(rate, c); } - do_samp_rate_warning_message(rate, get_rx_rate(), "RX"); } - double get_rx_rate(void){ - return _rx_dsp(0)[DSP_PROP_HOST_RATE].as<double>(); + double get_rx_rate(size_t chan){ + return _rx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>(); } tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), tune_request); + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); return r; } double get_rx_freq(size_t chan){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm()); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan)); } freq_range_t get_rx_freq_range(size_t chan){ - return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan/rx_cpm())); + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan)); } void set_rx_gain(double gain, const std::string &name, size_t chan){ @@ -342,32 +393,40 @@ public: } size_t get_tx_num_channels(void){ - return tx_cpm()*get_num_mboards(); //total num channels + size_t sum = 0; + for (size_t m = 0; m < get_num_mboards(); m++){ + sum += get_tx_subdev_spec(m).size(); + } + return sum; } - void set_tx_rate(double rate){ - for (size_t m = 0; m < get_num_mboards(); m++){ - _tx_dsp(m)[DSP_PROP_HOST_RATE] = rate; + void set_tx_rate(double rate, size_t chan){ + if (chan != ALL_CHANS){ + _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + do_samp_rate_warning_message(rate, get_tx_rate(chan), "TX"); + return; + } + for (size_t c = 0; c < get_tx_num_channels(); c++){ + set_tx_rate(rate, c); } - do_samp_rate_warning_message(rate, get_tx_rate(), "TX"); } - double get_tx_rate(void){ - return _tx_dsp(0)[DSP_PROP_HOST_RATE].as<double>(); + double get_tx_rate(size_t chan){ + return _tx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>(); } tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), tune_request); + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); return r; } double get_tx_freq(size_t chan){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm()); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan)); } freq_range_t get_tx_freq_range(size_t chan){ - return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan/tx_cpm())); + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan)); } void set_tx_gain(double gain, const std::string &name, size_t chan){ @@ -421,58 +480,75 @@ public: private: device::sptr _dev; - size_t rx_cpm(void){ //channels per mboard - size_t nchan = get_rx_subdev_spec(0).size(); - for (size_t m = 1; m < get_num_mboards(); m++){ - if (nchan != get_rx_subdev_spec(m).size()){ - throw std::runtime_error("rx subdev spec size inconsistent across all mboards"); - } + struct mboard_chan_pair{ + size_t mboard, chan; + mboard_chan_pair(void): mboard(0), chan(0){} + }; + + mboard_chan_pair rx_chan_to_mcp(size_t chan){ + mboard_chan_pair mcp; + mcp.chan = chan; + for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){ + size_t sss = get_rx_subdev_spec(mcp.mboard).size(); + if (mcp.chan < sss) break; + mcp.chan -= sss; } - return nchan; + return mcp; } - size_t tx_cpm(void){ //channels per mboard - size_t nchan = get_tx_subdev_spec(0).size(); - for (size_t m = 1; m < get_num_mboards(); m++){ - if (nchan != get_tx_subdev_spec(m).size()){ - throw std::runtime_error("tx subdev spec size inconsistent across all mboards"); - } + mboard_chan_pair tx_chan_to_mcp(size_t chan){ + mboard_chan_pair mcp; + mcp.chan = chan; + for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){ + size_t sss = get_tx_subdev_spec(mcp.mboard).size(); + if (mcp.chan < sss) break; + mcp.chan -= sss; } - return nchan; + return mcp; } wax::obj _mboard(size_t mboard){ std::string mb_name = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>().at(mboard); return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, mb_name)]; } - wax::obj _rx_dsp(size_t mboard){ - return _mboard(mboard)[MBOARD_PROP_RX_DSP]; + wax::obj _rx_dsp(size_t chan){ + mboard_chan_pair mcp = rx_chan_to_mcp(chan); + prop_names_t dsp_names = _mboard(mcp.mboard)[MBOARD_PROP_RX_DSP_NAMES].as<prop_names_t>(); + return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_RX_DSP, dsp_names.at(mcp.chan))]; } - wax::obj _tx_dsp(size_t mboard){ - return _mboard(mboard)[MBOARD_PROP_TX_DSP]; + wax::obj _tx_dsp(size_t chan){ + mboard_chan_pair mcp = tx_chan_to_mcp(chan); + prop_names_t dsp_names = _mboard(mcp.mboard)[MBOARD_PROP_TX_DSP_NAMES].as<prop_names_t>(); + return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_TX_DSP, dsp_names.at(mcp.chan))]; } wax::obj _rx_dboard(size_t chan){ - std::string db_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).db_name; - return _mboard(chan/rx_cpm())[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + mboard_chan_pair mcp = rx_chan_to_mcp(chan); + std::string db_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).db_name; + return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; } wax::obj _tx_dboard(size_t chan){ - std::string db_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).db_name; - return _mboard(chan/tx_cpm())[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + mboard_chan_pair mcp = tx_chan_to_mcp(chan); + std::string db_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).db_name; + return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; } wax::obj _rx_subdev(size_t chan){ - std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name; + mboard_chan_pair mcp = rx_chan_to_mcp(chan); + std::string sd_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name; return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; } wax::obj _tx_subdev(size_t chan){ - std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name; + mboard_chan_pair mcp = tx_chan_to_mcp(chan); + std::string sd_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name; return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; } gain_group::sptr _rx_gain_group(size_t chan){ - std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name; + mboard_chan_pair mcp = rx_chan_to_mcp(chan); + std::string sd_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name; return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); } gain_group::sptr _tx_gain_group(size_t chan){ - std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name; + mboard_chan_pair mcp = tx_chan_to_mcp(chan); + std::string sd_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name; return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); } }; diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp index d5d950f1f..6912afec8 100644 --- a/host/lib/usrp/subdev_spec.cpp +++ b/host/lib/usrp/subdev_spec.cpp @@ -16,11 +16,11 @@ // #include <uhd/usrp/subdev_spec.hpp> +#include <uhd/exception.hpp> #include <boost/algorithm/string.hpp> //for split #include <boost/tokenizer.hpp> #include <boost/format.hpp> #include <boost/foreach.hpp> -#include <stdexcept> #include <sstream> #include <vector> @@ -51,7 +51,7 @@ subdev_spec_t::subdev_spec_t(const std::string &markup){ switch(db_sd.size()){ case 1: this->push_back(subdev_spec_pair_t("", db_sd.front())); break; case 2: this->push_back(subdev_spec_pair_t(db_sd.front(), db_sd.back())); break; - default: throw std::runtime_error("invalid subdev-spec markup string: "+markup); + default: throw uhd::value_error("invalid subdev-spec markup string: "+markup); } } } diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index eccee7f4b..ced80c187 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -30,12 +30,11 @@ using namespace uhd::usrp; **********************************************************************/ static tune_result_t tune_xx_subdev_and_dsp( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dsp, size_t chan, + wax::obj subdev, wax::obj dsp, const tune_request_t &tune_request ){ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; - std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan); - wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; + wax::obj dsp_freq_proxy = dsp[DSP_PROP_FREQ_SHIFT]; //------------------------------------------------------------------ //-- calculate the LO offset, only used with automatic policy @@ -105,13 +104,11 @@ static tune_result_t tune_xx_subdev_and_dsp( } static double derive_freq_from_xx_subdev_and_dsp( - dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dsp, size_t chan + dboard_iface::unit_t unit, wax::obj subdev, wax::obj dsp ){ //extract actual dsp and IF frequencies double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>(); - std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan); - double actual_dsp_freq = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as<double>(); + double actual_dsp_freq = dsp[DSP_PROP_FREQ_SHIFT].as<double>(); //invert the sign on the dsp freq given the following conditions if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0; @@ -123,30 +120,28 @@ static double derive_freq_from_xx_subdev_and_dsp( * RX Tune **********************************************************************/ tune_result_t usrp::tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, size_t chan, - const tune_request_t &tune_request + wax::obj subdev, wax::obj ddc, const tune_request_t &tune_request ){ - return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan, tune_request); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, tune_request); } double usrp::derive_freq_from_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, size_t chan + wax::obj subdev, wax::obj ddc ){ - return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc); } /*********************************************************************** * TX Tune **********************************************************************/ tune_result_t usrp::tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, size_t chan, - const tune_request_t &tune_request + wax::obj subdev, wax::obj duc, const tune_request_t &tune_request ){ - return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan, tune_request); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, tune_request); } double usrp::derive_freq_from_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, size_t chan + wax::obj subdev, wax::obj duc ){ - return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc); } diff --git a/host/lib/usrp/usrp1/clock_ctrl.cpp b/host/lib/usrp/usrp1/clock_ctrl.cpp index 156f2b0c4..df5353b54 100644 --- a/host/lib/usrp/usrp1/clock_ctrl.cpp +++ b/host/lib/usrp/usrp1/clock_ctrl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -16,13 +16,6 @@ // #include "clock_ctrl.hpp" -#include "fpga_regs_standard.h" -#include <uhd/utils/assert.hpp> -#include <boost/cstdint.hpp> -#include <boost/assign/list_of.hpp> -#include <boost/foreach.hpp> -#include <utility> -#include <iostream> using namespace uhd; diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index f3816b377..1b4411002 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -20,7 +20,7 @@ #include "clock_ctrl.hpp" #include "ad9862_regs.hpp" #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/utils/byteswap.hpp> #include <boost/cstdint.hpp> @@ -162,7 +162,7 @@ static const int mtpgw = 255; //maximum tx pga gain word void usrp1_codec_ctrl_impl::set_tx_pga_gain(double gain){ int gain_word = int(mtpgw*(gain - tx_pga_gain_range.start())/(tx_pga_gain_range.stop() - tx_pga_gain_range.start())); - _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw); + _ad9862_regs.tx_pga_gain = uhd::clip(gain_word, 0, mtpgw); this->send_reg(16); } @@ -174,7 +174,7 @@ static const int mrpgw = 0x14; //maximum rx pga gain word void usrp1_codec_ctrl_impl::set_rx_pga_gain(double gain, char which){ int gain_word = int(mrpgw*(gain - rx_pga_gain_range.start())/(rx_pga_gain_range.stop() - rx_pga_gain_range.start())); - gain_word = std::clip(gain_word, 0, mrpgw); + gain_word = uhd::clip(gain_word, 0, mrpgw); switch(which){ case 'A': _ad9862_regs.rx_pga_a = gain_word; @@ -264,7 +264,7 @@ void usrp1_codec_ctrl_impl::write_aux_dac(aux_dac_t which, double 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); + boost::uint16_t dac_word = uhd::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); @@ -273,7 +273,7 @@ void usrp1_codec_ctrl_impl::write_aux_dac(aux_dac_t which, double volts) } //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); + boost::uint8_t dac_word = uhd::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<boost::uint8_t*, boost::uint8_t> dac_params_t; @@ -303,8 +303,8 @@ void usrp1_codec_ctrl_impl::send_reg(boost::uint8_t addr) std::cout << "codec control write reg: 0x"; std::cout << std::setw(8) << std::hex << reg << std::endl; } - _iface->transact_spi(_spi_slave, - spi_config_t::EDGE_RISE, reg, 16, false); + _iface->write_spi(_spi_slave, + spi_config_t::EDGE_RISE, reg, 16); } void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr) @@ -317,8 +317,8 @@ void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr) std::cout << std::setw(8) << std::hex << reg << std::endl; } - boost::uint32_t ret = _iface->transact_spi(_spi_slave, - spi_config_t::EDGE_RISE, reg, 16, true); + boost::uint32_t ret = _iface->read_spi(_spi_slave, + spi_config_t::EDGE_RISE, reg, 16); if (codec_debug) { std::cout.fill('0'); diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp index 14ecd2d2e..7e4032131 100644 --- a/host/lib/usrp/usrp1/codec_impl.cpp +++ b/host/lib/usrp/usrp1/codec_impl.cpp @@ -16,7 +16,7 @@ // #include "usrp1_impl.hpp" -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/usrp/codec_props.hpp> #include <boost/bind.hpp> #include <boost/foreach.hpp> diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index eec4a52db..3f3a98b7a 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -24,7 +24,7 @@ #include "codec_ctrl.hpp" #include <uhd/usrp/dboard_iface.hpp> #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <boost/assign/list_of.hpp> #include <iostream> @@ -329,7 +329,7 @@ static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit, else break; } - throw std::invalid_argument("unknown unit type"); + UHD_THROW_INVALID_CODE_PATH(); } void usrp1_dboard_iface::write_spi(unit_t unit, @@ -337,8 +337,8 @@ void usrp1_dboard_iface::write_spi(unit_t unit, boost::uint32_t data, size_t num_bits) { - _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot), - config, data, num_bits, false); + _iface->write_spi(unit_to_otw_spi_dev(unit, _dboard_slot), + config, data, num_bits); } boost::uint32_t usrp1_dboard_iface::read_write_spi(unit_t unit, @@ -346,8 +346,8 @@ boost::uint32_t usrp1_dboard_iface::read_write_spi(unit_t unit, boost::uint32_t data, size_t num_bits) { - return _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot), - config, data, num_bits, true); + return _iface->read_spi(unit_to_otw_spi_dev(unit, _dboard_slot), + config, data, num_bits); } /*********************************************************************** diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index 2130960fb..02906fc45 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -19,7 +19,7 @@ #include "usrp_i2c_addr.h" #include <uhd/usrp/dsp_utils.hpp> #include <uhd/usrp/misc_utils.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/usrp/dboard_props.hpp> #include <uhd/usrp/subdev_props.hpp> #include <boost/bind.hpp> diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 370f4831f..8152c4e34 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -34,23 +34,25 @@ using namespace uhd::usrp; **********************************************************************/ void usrp1_impl::rx_dsp_init(void) { - _rx_dsp_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2), - boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2)); - - rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16); + for (size_t i = 0; i < this->get_num_ddcs(); i++){ + _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2, i), + boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2, i) + ); + rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16, i); + } } /*********************************************************************** * RX DDC Get **********************************************************************/ -void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){ +void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()){ case DSP_PROP_NAME: - val = str(boost::format("usrp1 ddc %uX %s") - % this->get_num_ddcs() + val = str(boost::format("usrp1 ddc%d %s") + % which_dsp % (this->has_rx_halfband()? "+ hb" : "") ); return; @@ -60,16 +62,7 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_FREQ_SHIFT: - val = _rx_dsp_freqs[key.name]; - return; - - case DSP_PROP_FREQ_SHIFT_NAMES:{ - prop_names_t names; - for(size_t i = 0; i < this->get_num_ddcs(); i++){ - names.push_back(boost::lexical_cast<std::string>(i)); - } - val = names; - } + val = _rx_dsp_freqs[which_dsp]; return; case DSP_PROP_CODEC_RATE: @@ -88,7 +81,7 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * RX DDC Set **********************************************************************/ -void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ +void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()) { @@ -97,16 +90,17 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ boost::uint32_t reg_word = dsp_type1::calc_cordic_word_and_update( new_freq, _clock_ctrl->get_master_clock_freq()); - static const uhd::dict<std::string, boost::uint32_t> - freq_name_to_reg_val = boost::assign::map_list_of - ("0", FR_RX_FREQ_0) ("1", FR_RX_FREQ_1) - ("2", FR_RX_FREQ_2) ("3", FR_RX_FREQ_3) - ; - _iface->poke32(freq_name_to_reg_val[key.name], ~reg_word + 1); - _rx_dsp_freqs[key.name] = new_freq; + static const boost::uint32_t dsp_index_to_reg_val[4] = { + FR_RX_FREQ_0, FR_RX_FREQ_1, FR_RX_FREQ_2, FR_RX_FREQ_3 + }; + _iface->poke32(dsp_index_to_reg_val[which_dsp], ~reg_word + 1); + _rx_dsp_freqs[which_dsp] = new_freq; return; } - case DSP_PROP_HOST_RATE: { + + case DSP_PROP_HOST_RATE: + if (which_dsp != 0) return; //only for dsp[0] as this is vectorized + { size_t rate = size_t(_clock_ctrl->get_master_clock_freq() / val.as<double>()); if ((rate & 0x01) || (rate < 4) || (rate > 256)) { @@ -123,6 +117,11 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ } return; + case DSP_PROP_STREAM_CMD: + if (which_dsp != 0) return; //only for dsp[0] as this is vectorized + _soft_time_ctrl->issue_stream_cmd(val.as<stream_cmd_t>()); + return; + default: UHD_THROW_PROP_SET_ERROR(); } @@ -133,24 +132,25 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ **********************************************************************/ void usrp1_impl::tx_dsp_init(void) { - _tx_dsp_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2), - boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2)); - - //initial config and update - tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() * 2 / 16); + for (size_t i = 0; i < this->get_num_ducs(); i++){ + _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2, i), + boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2, i) + ); + tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16, i); + } } /*********************************************************************** * TX DUC Get **********************************************************************/ -void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){ +void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()) { case DSP_PROP_NAME: - val = str(boost::format("usrp1 duc %uX %s") - % this->get_num_ducs() + val = str(boost::format("usrp1 duc%d %s") + % which_dsp % (this->has_tx_halfband()? "+ hb" : "") ); return; @@ -160,16 +160,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_FREQ_SHIFT: - val = _tx_dsp_freqs[key.name]; - return; - - case DSP_PROP_FREQ_SHIFT_NAMES:{ - prop_names_t names; - for(size_t i = 0; i < this->get_num_ducs(); i++){ - names.push_back(boost::lexical_cast<std::string>(i)); - } - val = names; - } + val = _tx_dsp_freqs[which_dsp]; return; case DSP_PROP_CODEC_RATE: @@ -188,7 +179,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){ /*********************************************************************** * TX DUC Set **********************************************************************/ -void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){ +void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()) { @@ -197,15 +188,17 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){ double new_freq = val.as<double>(); //map the freq shift key to a subdev spec to a particular codec chip - std::string db_name = _tx_subdev_spec.at(boost::lexical_cast<size_t>(key.name)).db_name; + std::string db_name = _tx_subdev_spec.at(which_dsp).db_name; if (db_name == "A") _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); if (db_name == "B") _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq); - _tx_dsp_freqs[key.name] = new_freq; + _tx_dsp_freqs[which_dsp] = new_freq; return; } - case DSP_PROP_HOST_RATE: { + case DSP_PROP_HOST_RATE: + if (which_dsp != 0) return; //only for dsp[0] as this is vectorized + { size_t rate = size_t(_clock_ctrl->get_master_clock_freq() * 2 / val.as<double>()); if ((rate & 0x01) || (rate < 8) || (rate > 512)) { diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 8beeccf8f..b3268298e 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -18,6 +18,7 @@ #include "../../transport/vrt_packet_handler.hpp" #include "usrp_commands.h" #include "usrp1_impl.hpp" +#include <uhd/utils/safe_call.hpp> #include <uhd/utils/thread_priority.hpp> #include <uhd/transport/bounded_buffer.hpp> #include <boost/bind.hpp> @@ -114,7 +115,7 @@ struct usrp1_impl::io_impl{ } ~io_impl(void){ - flush_send_buff(); + UHD_SAFE_CALL(flush_send_buff();) } zero_copy_if::sptr data_transport; diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 6d5bf466d..4e2fad6e5 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -25,7 +25,7 @@ #include <uhd/usrp/dboard_props.hpp> #include <uhd/usrp/subdev_props.hpp> #include <uhd/utils/warning.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/utils/images.hpp> #include <boost/assign/list_of.hpp> #include <boost/foreach.hpp> @@ -161,7 +161,7 @@ static boost::uint32_t calc_tx_mux( //sanity check, only 1 channel per slot slot_to_chan_count[pair.db_name]++; if (slot_to_chan_count[pair.db_name] > 1){ - throw std::runtime_error(str(boost::format( + throw uhd::value_error(str(boost::format( "dboard slot %s assigned to multiple channels in subdev spec %s" ) % pair.db_name % subdev_spec.to_string())); } @@ -280,21 +280,19 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) return; case MBOARD_PROP_RX_DSP: - UHD_ASSERT_THROW(key.name == ""); - val = _rx_dsp_proxy->get_link(); + val = _rx_dsp_proxies.get(key.name)->get_link(); return; case MBOARD_PROP_RX_DSP_NAMES: - val = prop_names_t(1, ""); + val = _rx_dsp_proxies.keys(); return; case MBOARD_PROP_TX_DSP: - UHD_ASSERT_THROW(key.name == ""); - val = _tx_dsp_proxy->get_link(); + val = _tx_dsp_proxies.get(key.name)->get_link(); return; case MBOARD_PROP_TX_DSP_NAMES: - val = prop_names_t(1, ""); + val = _tx_dsp_proxies.keys(); return; case MBOARD_PROP_CLOCK_CONFIG: @@ -342,14 +340,10 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) //handle the get request conditioned on the key switch(key.as<mboard_prop_t>()){ - case MBOARD_PROP_STREAM_CMD: - _soft_time_ctrl->issue_stream_cmd(val.as<stream_cmd_t>()); - return; - case MBOARD_PROP_RX_SUBDEV_SPEC: _rx_subdev_spec = val.as<subdev_spec_t>(); if (_rx_subdev_spec.size() > this->get_num_ddcs()){ - throw std::runtime_error(str(boost::format( + throw uhd::value_error(str(boost::format( "USRP1 suports up to %u RX channels.\n" "However, this RX subdev spec requires %u channels\n" ) % this->get_num_ddcs() % _rx_subdev_spec.size())); @@ -362,7 +356,7 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) case MBOARD_PROP_TX_SUBDEV_SPEC: _tx_subdev_spec = val.as<subdev_spec_t>(); if (_tx_subdev_spec.size() > this->get_num_ducs()){ - throw std::runtime_error(str(boost::format( + throw uhd::value_error(str(boost::format( "USRP1 suports up to %u TX channels.\n" "However, this TX subdev spec requires %u channels\n" ) % this->get_num_ducs() % _tx_subdev_spec.size())); diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 09f854813..3fa6cb8b7 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -16,7 +16,8 @@ // #include "usrp1_ctrl.hpp" -#include "usrp_commands.h" +#include "usrp_commands.h" +#include <uhd/exception.hpp> #include <uhd/transport/usb_control.hpp> #include <boost/functional/hash.hpp> #include <boost/thread/thread.hpp> @@ -29,13 +30,6 @@ using namespace uhd; -enum firmware_code { - USRP_FPGA_LOAD_SUCCESS, - USRP_FPGA_ALREADY_LOADED, - USRP_FIRMWARE_LOAD_SUCCESS, - USRP_FIRMWARE_ALREADY_LOADED -}; - #define FX2_FIRMWARE_LOAD 0xa0 static const bool load_img_msg = true; @@ -45,15 +39,16 @@ static const bool load_img_msg = true; **********************************************************************/ /*! * Create a file hash - * The hash will be used to identify the loaded firmware and fpga image + * The hash will be used to identify the loaded firmware and fpga image * \param filename file used to generate hash value * \return hash value in a size_t type */ static size_t generate_hash(const char *filename) { std::ifstream file(filename); - if (!file) - std::cerr << "error: cannot open input file " << filename << std::endl; + if (not file){ + throw uhd::io_error(std::string("cannot open input file ") + filename); + } size_t hash = 0; @@ -62,18 +57,19 @@ static size_t generate_hash(const char *filename) boost::hash_combine(hash, ch); } - if (!file.eof()) - std::cerr << "error: file error " << filename << std::endl; + if (not file.eof()){ + throw uhd::io_error(std::string("file error ") + filename); + } - file.close(); - return hash; + file.close(); + return hash; } /*! - * Verify checksum of a Intel HEX record + * Verify checksum of a Intel HEX record * \param record a line from an Intel HEX file - * \return true if record is valid, false otherwise + * \return true if record is valid, false otherwise */ static bool checksum(std::string *record) { @@ -123,7 +119,7 @@ bool parse_record(std::string *record, unsigned int &len, for (i = 0; i < len; i++) { std::istringstream(record->substr(9 + 2 * i, 2)) >> std::hex >> val; data[i] = (unsigned char) val; - } + } return true; } @@ -139,20 +135,15 @@ public: _ctrl_transport = ctrl_transport; } - int usrp_load_firmware(std::string filestring, bool force) + void usrp_load_firmware(std::string filestring, bool force) { const char *filename = filestring.c_str(); size_t hash = generate_hash(filename); - size_t loaded_hash; - if (usrp_get_firmware_hash(loaded_hash) < 0) { - std::cerr << "firmware hash retrieval failed" << std::endl; - return -1; - } + size_t loaded_hash; usrp_get_firmware_hash(loaded_hash); - if (!force && (hash == loaded_hash)) - return USRP_FIRMWARE_ALREADY_LOADED; + if (not force and (hash == loaded_hash)) return; //FIXME: verify types unsigned int len; @@ -160,13 +151,11 @@ public: unsigned int type; unsigned char data[512]; - int ret; std::ifstream file; file.open(filename, std::ifstream::in); if (!file.good()) { - std::cerr << "cannot open firmware input file" << std::endl; - return -1; + throw uhd::io_error("usrp_load_firmware: cannot open firmware input file"); } unsigned char reset_y = 1; @@ -174,56 +163,41 @@ public: //hit the reset line if (load_img_msg) std::cout << "Loading firmware image: " << filestring << "..." << std::flush; - usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, - &reset_y, 1); - + usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1); + while (!file.eof()) { std::string record; file >> record; - - //check for valid record - if (!checksum(&record) || - !parse_record(&record, len, addr, type, data)) { - std::cerr << "error: bad record" << std::endl; - file.close(); - return -1; + + //check for valid record + if (not checksum(&record) or not parse_record(&record, len, addr, type, data)) { + throw uhd::io_error("usrp_load_firmware: bad record checksum"); } //type 0x00 is data if (type == 0x00) { - ret = usrp_control_write(FX2_FIRMWARE_LOAD, addr, 0, - data, len); - if (ret < 0) { - std::cerr << "error: usrp_control_write failed: "; - std::cerr << ret << std::endl; - file.close(); - return -1; - } - } - //type 0x01 is end + int ret = usrp_control_write(FX2_FIRMWARE_LOAD, addr, 0, data, len); + if (ret < 0) throw uhd::io_error("usrp_load_firmware: usrp_control_write failed"); + } + //type 0x01 is end else if (type == 0x01) { usrp_set_firmware_hash(hash); //set hash before reset - usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, - &reset_n, 1); + usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1); file.close(); //wait for things to settle boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); if (load_img_msg) std::cout << " done" << std::endl; - return USRP_FIRMWARE_LOAD_SUCCESS; + return; } //type anything else is unhandled else { - std::cerr << "error: unsupported record" << std::endl; - file.close(); - return -1; + throw uhd::io_error("usrp_load_firmware: unsupported record"); } } - //file did not end - std::cerr << "error: bad record" << std::endl; - file.close(); - return -1; + //file did not end + throw uhd::io_error("usrp_load_firmware: bad record"); } void usrp_init(void){ @@ -241,64 +215,48 @@ public: usrp_tx_enable(true); } - int usrp_load_fpga(std::string filestring) + void usrp_load_fpga(std::string filestring) { const char *filename = filestring.c_str(); size_t hash = generate_hash(filename); - size_t loaded_hash; - if (usrp_get_fpga_hash(loaded_hash) < 0) { - std::cerr << "fpga hash retrieval failed" << std::endl; - return -1; - } + size_t loaded_hash; usrp_get_fpga_hash(loaded_hash); - if (hash == loaded_hash) - return USRP_FPGA_ALREADY_LOADED; + if (hash == loaded_hash) return; const int ep0_size = 64; unsigned char buf[ep0_size]; - int ret; if (load_img_msg) std::cout << "Loading FPGA image: " << filestring << "..." << std::flush; std::ifstream file; file.open(filename, std::ios::in | std::ios::binary); if (not file.good()) { - std::cerr << "cannot open fpga input file" << std::endl; - file.close(); - return -1; + throw uhd::io_error("usrp_load_fpga: cannot open fpga input file"); } if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_BEGIN) < 0) { - std::cerr << "fpga load error" << std::endl; - file.close(); - return -1; + throw uhd::io_error("usrp_load_fpga: fpga load error"); } while (not file.eof()) { file.read((char *)buf, sizeof(buf)); size_t n = file.gcount(); - ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, - buf, n); + int ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, buf, n); if (ret < 0 or size_t(ret) != n) { - std::cerr << "fpga load error " << ret << std::endl; - file.close(); - return -1; + throw uhd::io_error("usrp_load_fpga: fpga load error"); } } - + if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_END) < 0) { - std::cerr << "fpga load error" << std::endl; - file.close(); - return -1; + throw uhd::io_error("usrp_load_fpga: fpga load error"); } usrp_set_fpga_hash(hash); file.close(); if (load_img_msg) std::cout << " done" << std::endl; - return 0; } - int usrp_load_eeprom(std::string filestring) + void usrp_load_eeprom(std::string filestring) { const char *filename = filestring.c_str(); const boost::uint16_t i2c_addr = 0x50; @@ -309,100 +267,92 @@ public: unsigned char data[256]; unsigned char sendbuf[17]; - int ret; std::ifstream file; file.open(filename, std::ifstream::in); - if (!file.good()) { - std::cerr << "cannot open EEPROM input file" << std::endl; - return -1; + if (not file.good()) { + throw uhd::io_error("usrp_load_eeprom: cannot open EEPROM input file"); } file.read((char *)data, 256); len = file.gcount(); if(len == 256) { - std::cerr << "error: image size too large" << std::endl; - file.close(); - return -1; + throw uhd::io_error("usrp_load_eeprom: image size too large"); } const int pagesize = 16; addr = 0; while(len > 0) { - sendbuf[0] = addr; - memcpy(sendbuf+1, &data[addr], len > pagesize ? pagesize : len); - ret = usrp_i2c_write(i2c_addr, sendbuf, (len > pagesize ? pagesize : len)+1); - if (ret < 0) { - std::cerr << "error: usrp_i2c_write failed: "; - std::cerr << ret << std::endl; - file.close(); - return -1; - } - addr += pagesize; - len -= pagesize; - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + sendbuf[0] = addr; + memcpy(sendbuf+1, &data[addr], len > pagesize ? pagesize : len); + int ret = usrp_i2c_write(i2c_addr, sendbuf, (len > pagesize ? pagesize : len)+1); + if (ret < 0) { + throw uhd::io_error("usrp_load_eeprom: usrp_i2c_write failed"); + } + addr += pagesize; + len -= pagesize; + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } file.close(); - return 0; } - int usrp_set_led(int led_num, bool on) + void usrp_set_led(int led_num, bool on) { - return usrp_control_write_cmd(VRQ_SET_LED, on, led_num); + UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_SET_LED, on, led_num) >= 0); } - int usrp_get_firmware_hash(size_t &hash) + void usrp_get_firmware_hash(size_t &hash) { - return usrp_control_read(0xa0, USRP_HASH_SLOT_0_ADDR, 0, - (unsigned char*) &hash, sizeof(size_t)); + UHD_ASSERT_THROW(usrp_control_read(0xa0, USRP_HASH_SLOT_0_ADDR, 0, + (unsigned char*) &hash, sizeof(size_t)) >= 0); } - int usrp_set_firmware_hash(size_t hash) + void usrp_set_firmware_hash(size_t hash) { - return usrp_control_write(0xa0, USRP_HASH_SLOT_0_ADDR, 0, - (unsigned char*) &hash, sizeof(size_t)); + UHD_ASSERT_THROW(usrp_control_write(0xa0, USRP_HASH_SLOT_0_ADDR, 0, + (unsigned char*) &hash, sizeof(size_t)) >= 0); } - int usrp_get_fpga_hash(size_t &hash) + void usrp_get_fpga_hash(size_t &hash) { - return usrp_control_read(0xa0, USRP_HASH_SLOT_1_ADDR, 0, - (unsigned char*) &hash, sizeof(size_t)); + UHD_ASSERT_THROW(usrp_control_read(0xa0, USRP_HASH_SLOT_1_ADDR, 0, + (unsigned char*) &hash, sizeof(size_t)) >= 0); } - int usrp_set_fpga_hash(size_t hash) + void usrp_set_fpga_hash(size_t hash) { - return usrp_control_write(0xa0, USRP_HASH_SLOT_1_ADDR, 0, - (unsigned char*) &hash, sizeof(size_t)); + UHD_ASSERT_THROW(usrp_control_write(0xa0, USRP_HASH_SLOT_1_ADDR, 0, + (unsigned char*) &hash, sizeof(size_t)) >= 0); } - int usrp_tx_enable(bool on) + void usrp_tx_enable(bool on) { - return usrp_control_write_cmd(VRQ_FPGA_SET_TX_ENABLE, on, 0); + UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_TX_ENABLE, on, 0) >= 0); } - int usrp_rx_enable(bool on) + void usrp_rx_enable(bool on) { - return usrp_control_write_cmd(VRQ_FPGA_SET_RX_ENABLE, on, 0); + UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_RX_ENABLE, on, 0) >= 0); } - int usrp_tx_reset(bool on) + void usrp_tx_reset(bool on) { - return usrp_control_write_cmd(VRQ_FPGA_SET_TX_RESET, on, 0); + UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_TX_RESET, on, 0) >= 0); } - int usrp_rx_reset(bool on) + void usrp_rx_reset(bool on) { - return usrp_control_write_cmd(VRQ_FPGA_SET_RX_RESET, on, 0); + UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_RX_RESET, on, 0) >= 0); } @@ -417,7 +367,7 @@ public: value, // wValue index, // wIndex buff, // data - length); // wLength + length); // wLength } diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.hpp b/host/lib/usrp/usrp1/usrp1_ctrl.hpp index 8ccfacab7..ee68f8401 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.hpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.hpp @@ -40,60 +40,21 @@ public: * Load firmware in Intel HEX Format onto device * \param filename name of firmware file * \param force reload firmware if already loaded - * \return 0 on success, error code otherwise */ - virtual int usrp_load_firmware(std::string filename, + virtual void usrp_load_firmware(std::string filename, bool force = false) = 0; /*! * Load fpga file onto usrp * \param filename name of fpga image - * \return 0 on success, error code otherwise */ - virtual int usrp_load_fpga(std::string filename) = 0; + virtual void usrp_load_fpga(std::string filename) = 0; /*! * Load USB descriptor file in Intel HEX format into EEPROM - * \param filename name of EEPROM image - * \return 0 on success, error code otherwise + * \param filename name of EEPROM image */ - virtual int usrp_load_eeprom(std::string filestring) = 0; - - /*! - * Set led usrp - * \param led_num which LED to control (0 or 1) - * \param on turn LED on or off - * \return 0 on success, error code otherwise - */ - virtual int usrp_set_led(int led_num, bool on) = 0; - - /*! - * Get firmware hash - * \param hash a size_t hash value - * \return 0 on success, error code otherwise - */ - virtual int usrp_get_firmware_hash(size_t &hash) = 0; - - /*! - * Set firmware hash - * \param hash a size_t hash value - * \return 0 on success, error code otherwise - */ - virtual int usrp_set_firmware_hash(size_t hash) = 0; - - /*! - * Get fpga hash - * \param hash a size_t hash value - * \return 0 on success, error code otherwise - */ - virtual int usrp_get_fpga_hash(size_t &hash) = 0; - - /*! - * Set fpga hash - * \param hash a size_t hash value - * \return 0 on success, error code otherwise - */ - virtual int usrp_set_fpga_hash(size_t hash) = 0; + virtual void usrp_load_eeprom(std::string filestring) = 0; /*! * Submit an IN transfer diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index 63fcd5777..0c37610ce 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -17,7 +17,7 @@ #include "usrp1_iface.hpp" #include "usrp_commands.h" -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/byteswap.hpp> #include <boost/format.hpp> #include <stdexcept> @@ -70,8 +70,7 @@ public: (unsigned char*) &swapped, sizeof(boost::uint32_t)); - if (ret < 0) - std::cerr << "USRP: failed memory write: " << ret << std::endl; + if (ret < 0) throw uhd::io_error("USRP1: failed control write"); } boost::uint32_t peek32(boost::uint32_t addr) @@ -88,11 +87,27 @@ public: (unsigned char*) &value_out, sizeof(boost::uint32_t)); - if (ret < 0) - std::cerr << "USRP: failed memory read: " << ret << std::endl; + if (ret < 0) throw uhd::io_error("USRP1: failed control read"); return uhd::ntohx(value_out); } + + void poke16(boost::uint32_t, boost::uint16_t) { + throw uhd::not_implemented_error("Unhandled command poke16()"); + } + + boost::uint16_t peek16(boost::uint32_t) { + throw uhd::not_implemented_error("Unhandled command peek16()"); + return 0; + } + + void write_uart(boost::uint8_t, const std::string &) { + throw uhd::not_implemented_error("Unhandled command write_uart()"); + } + + std::string read_uart(boost::uint8_t) { + throw uhd::not_implemented_error("Unhandled command read_uart()"); + } /******************************************************************* * I2C @@ -176,10 +191,7 @@ public: buff, (w_len_h << 8) | (w_len_l << 0)); - if (ret < 0) { - std::cout << "USRP: failed SPI readback transaction: " - << std::dec << ret << std::endl; - } + if (ret < 0) throw uhd::io_error("USRP1: failed SPI readback transaction"); boost::uint32_t val = (((boost::uint32_t)buff[0]) << 0) | (((boost::uint32_t)buff[1]) << 8) | @@ -197,10 +209,7 @@ public: (w_index_h << 8) | (w_index_l << 0), buff, num_bytes); - if (ret < 0) { - std::cout << "USRP: failed SPI transaction: " - << std::dec << ret << std::endl; - } + if (ret < 0) throw uhd::io_error("USRP1: failed SPI transaction"); return 0; } @@ -234,8 +243,7 @@ public: length); } - if (ret < 0) - std::cerr << "USRP: failed firmware command: " << ret << std::endl; + if (ret < 0) throw uhd::io_error("USRP1: failed firmware command"); } private: diff --git a/host/lib/usrp/usrp1/usrp1_iface.hpp b/host/lib/usrp/usrp1/usrp1_iface.hpp index 34a2330b5..fdb7464ce 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.hpp +++ b/host/lib/usrp/usrp1/usrp1_iface.hpp @@ -18,8 +18,7 @@ #ifndef INCLUDED_USRP1_IFACE_HPP #define INCLUDED_USRP1_IFACE_HPP -#include <uhd/usrp/mboard_eeprom.hpp> -#include <uhd/types/serial.hpp> +#include <uhd/usrp/mboard_iface.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include "usrp1_ctrl.hpp" @@ -29,10 +28,13 @@ * Provides a set of functions to implementation layer. * Including spi, peek, poke, control... */ -class usrp1_iface : boost::noncopyable, public uhd::i2c_iface{ +class usrp1_iface : public uhd::usrp::mboard_iface, boost::noncopyable{ public: typedef boost::shared_ptr<usrp1_iface> sptr; + //motherboard eeprom map structure + uhd::usrp::mboard_eeprom_t mb_eeprom; + /*! * Make a new usrp1 interface with the control transport. * \param ctrl_transport the usrp controller object @@ -41,35 +43,6 @@ public: static sptr make(usrp_ctrl::sptr ctrl_transport); /*! - * 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; - - /*! - * 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; - - /*! * Perform a general USB firmware OUT operation * \param request * \param value @@ -82,8 +55,6 @@ public: boost::uint16_t index, unsigned char* buff, boost::uint16_t length) = 0; - - uhd::usrp::mboard_eeprom_t mb_eeprom; }; #endif /* INCLUDED_USRP1_IFACE_HPP */ diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 918032037..7005c59f2 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -19,11 +19,12 @@ #include "usrp1_ctrl.hpp" #include "fpga_regs_standard.h" #include "usrp_spi_defs.h" +#include <uhd/utils/safe_call.hpp> #include <uhd/transport/usb_control.hpp> #include <uhd/usrp/device_props.hpp> #include <uhd/usrp/mboard_props.hpp> #include <uhd/utils/warning.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/images.hpp> #include <boost/format.hpp> @@ -199,7 +200,16 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, } usrp1_impl::~usrp1_impl(void){ - /* NOP */ + //Safely destruct all RAII objects in a device. + //This prevents the mboard deconstructor from throwing, + //which allows the device to be safely deconstructed. + BOOST_FOREACH(dboard_slot_t slot, _dboard_slots){ + UHD_SAFE_CALL(_dboard_managers[slot].reset();) + UHD_SAFE_CALL(_dboard_ifaces[slot].reset();) + UHD_SAFE_CALL(_codec_ctrls[slot].reset();) + } + UHD_SAFE_CALL(_clock_ctrl.reset();) + UHD_SAFE_CALL(_io_impl.reset();) } bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, double timeout){ diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 1d9f6709f..9755c466d 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -182,19 +182,19 @@ private: //rx dsp functions and settings void rx_dsp_init(void); - void rx_dsp_get(const wax::obj &, wax::obj &); - void rx_dsp_set(const wax::obj &, const wax::obj &); - uhd::dict<std::string, double> _rx_dsp_freqs; + void rx_dsp_get(const wax::obj &, wax::obj &, size_t); + void rx_dsp_set(const wax::obj &, const wax::obj &, size_t); + uhd::dict<size_t, double> _rx_dsp_freqs; size_t _rx_dsp_decim; - wax_obj_proxy::sptr _rx_dsp_proxy; + uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies; //tx dsp functions and settings void tx_dsp_init(void); - void tx_dsp_get(const wax::obj &, wax::obj &); - void tx_dsp_set(const wax::obj &, const wax::obj &); - uhd::dict<std::string, double> _tx_dsp_freqs; + void tx_dsp_get(const wax::obj &, wax::obj &, size_t); + void tx_dsp_set(const wax::obj &, const wax::obj &, size_t); + uhd::dict<size_t, double> _tx_dsp_freqs; size_t _tx_dsp_interp; - wax_obj_proxy::sptr _tx_dsp_proxy; + uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies; //transports uhd::transport::usb_zero_copy::sptr _data_transport; diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 27ccefb2b..abda53bf2 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -19,7 +19,7 @@ #include "ad9510_regs.hpp" #include "usrp2_regs.hpp" //spi slave constants #include "usrp2_clk_regs.hpp" -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <boost/cstdint.hpp> #include <boost/lexical_cast.hpp> #include <boost/math/special_functions/round.hpp> @@ -305,7 +305,7 @@ private: */ void write_reg(boost::uint8_t addr){ boost::uint32_t data = _ad9510_regs.get_write_reg(addr); - _iface->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); + _iface->write_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24); } /*! diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index 890969b5a..0fdcedf62 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -19,10 +19,10 @@ #include "ad9777_regs.hpp" #include "ads62p44_regs.hpp" #include "usrp2_regs.hpp" +#include <uhd/exception.hpp> #include <boost/cstdint.hpp> #include <boost/foreach.hpp> #include <iostream> -#include <uhd/utils/exception.hpp> static const bool codec_ctrl_debug = false; @@ -118,7 +118,7 @@ public: case 2: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_2; break; case 4: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_4; break; case 8: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_8; break; - default: throw std::runtime_error("unknown modulation mode for ad9777"); + default: throw uhd::value_error("unknown modulation mode for ad9777"); } this->send_ad9777_reg(0x01); //set the register @@ -168,17 +168,17 @@ private: void send_ad9777_reg(boost::uint8_t addr){ boost::uint16_t reg = _ad9777_regs.get_write_reg(addr); if (codec_ctrl_debug) std::cout << "send_ad9777_reg: " << std::hex << reg << std::endl; - _iface->transact_spi( + _iface->write_spi( SPI_SS_AD9777, spi_config_t::EDGE_RISE, - reg, 16, false /*no rb*/ + reg, 16 ); } void send_ads62p44_reg(boost::uint8_t addr) { boost::uint16_t reg = _ads62p44_regs.get_write_reg(addr); - _iface->transact_spi( + _iface->write_spi( SPI_SS_ADS62P44, spi_config_t::EDGE_FALL, - reg, 16, false /*no rb*/ + reg, 16 ); } }; diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index 09bec6db2..50320773f 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -16,13 +16,13 @@ // #include "usrp2_impl.hpp" +#include <uhd/utils/assert_has.hpp> +#include <uhd/exception.hpp> #include <uhd/usrp/codec_props.hpp> #include <uhd/types/dict.hpp> #include <uhd/types/ranges.hpp> #include <boost/bind.hpp> #include <boost/assign/list_of.hpp> -#include <uhd/utils/assert.hpp> -#include <uhd/utils/exception.hpp> using namespace uhd; using namespace uhd::usrp; diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index c539b0058..924a6e901 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -20,7 +20,7 @@ #include "usrp2_regs.hpp" //wishbone address constants #include <uhd/usrp/dboard_iface.hpp> #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/algorithm.hpp> #include <boost/assign/list_of.hpp> #include <boost/asio.hpp> //htonl and ntohl @@ -257,7 +257,7 @@ void usrp2_dboard_iface::write_spi( boost::uint32_t data, size_t num_bits ){ - _iface->transact_spi(unit_to_spi_dev[unit], config, data, num_bits, false /*no rb*/); + _iface->write_spi(unit_to_spi_dev[unit], config, data, num_bits); } boost::uint32_t usrp2_dboard_iface::read_write_spi( @@ -266,7 +266,7 @@ boost::uint32_t usrp2_dboard_iface::read_write_spi( boost::uint32_t data, size_t num_bits ){ - return _iface->transact_spi(unit_to_spi_dev[unit], config, data, num_bits, true /*rb*/); + return _iface->read_spi(unit_to_spi_dev[unit], config, data, num_bits); } /*********************************************************************** @@ -288,9 +288,9 @@ void usrp2_dboard_iface::_write_aux_dac(unit_t unit){ (UNIT_RX, SPI_SS_RX_DAC) (UNIT_TX, SPI_SS_TX_DAC) ; - _iface->transact_spi( + _iface->write_spi( unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, - _dac_regs[unit].get_reg(), 24, false /*no rb*/ + _dac_regs[unit].get_reg(), 24 ); } @@ -336,13 +336,13 @@ double usrp2_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which){ } ad7922_regs.chn = ad7922_regs.mod; //normal mode: mod == chn //write and read spi - _iface->transact_spi( + _iface->write_spi( unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16, false /*no rb*/ + ad7922_regs.get_reg(), 16 ); - ad7922_regs.set_reg(boost::uint16_t(_iface->transact_spi( + ad7922_regs.set_reg(boost::uint16_t(_iface->read_spi( unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16, true /*rb*/ + ad7922_regs.get_reg(), 16 ))); //convert to voltage and return diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 4f1dcc46b..3f41cddcf 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -22,7 +22,7 @@ #include <uhd/usrp/dsp_utils.hpp> #include <uhd/usrp/subdev_props.hpp> #include <uhd/usrp/dboard_props.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <boost/format.hpp> #include <boost/bind.hpp> #include <boost/asio.hpp> //htonl and ntohl diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 8340f7cdd..cdd559e94 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -28,12 +28,79 @@ using namespace uhd; using namespace uhd::usrp; -static const size_t default_decim = 16; -static const size_t default_interp = 16; - /*********************************************************************** - * DDC Helper Methods + * DSP impl and methods **********************************************************************/ +struct usrp2_mboard_impl::dsp_impl{ + uhd::dict<size_t, size_t> ddc_decim; + uhd::dict<size_t, double> ddc_freq; + uhd::dict<size_t, size_t> duc_interp; + uhd::dict<size_t, double> duc_freq; + std::vector<size_t> decim_and_interp_rates; + uhd::dict<size_t, bool> continuous_streaming; +}; + +void usrp2_mboard_impl::dsp_init(void){ + //create new dsp impl + _dsp_impl = UHD_PIMPL_MAKE(dsp_impl, ()); + + //load the allowed decim/interp rates + //range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) + for (size_t i = 4; i <= 128; i+=1){ + _dsp_impl->decim_and_interp_rates.push_back(i); + } + for (size_t i = 130; i <= 256; i+=2){ + _dsp_impl->decim_and_interp_rates.push_back(i); + } + for (size_t i = 260; i <= 512; i+=4){ + _dsp_impl->decim_and_interp_rates.push_back(i); + } + + //bind and initialize the rx dsps + for (size_t i = 0; i < NUM_RX_DSPS; i++){ + _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( + boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2, i), + boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2, i) + ); + + //initial config and update + ddc_set(DSP_PROP_FREQ_SHIFT, double(0), i); + ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i); + + //setup the rx control registers + _iface->poke32(_iface->regs.rx_ctrl[i].clear_overrun, 1); //reset + _iface->poke32(_iface->regs.rx_ctrl[i].nsamps_per_pkt, _device.get_max_recv_samps_per_packet()); + _iface->poke32(_iface->regs.rx_ctrl[i].nchannels, 1); + _iface->poke32(_iface->regs.rx_ctrl[i].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[i].vrt_stream_id, usrp2_impl::RECV_SID); + _iface->poke32(_iface->regs.rx_ctrl[i].vrt_trailer, 0); + _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq())); + } + + //bind and initialize the tx dsps + for (size_t i = 0; i < NUM_TX_DSPS; i++){ + _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( + boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2, i), + boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2, i) + ); + + //initial config and update + duc_set(DSP_PROP_FREQ_SHIFT, double(0), i); + duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i); + + //init the tx control registers + _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset + _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); + } +} + template <typename rate_type> static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_type> &rates){ unsigned closest_match = rates.front(); @@ -44,27 +111,28 @@ static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_typ return closest_match; } -void usrp2_mboard_impl::init_ddc_config(void){ - //create the ddc in the rx dsp dict - _rx_dsp_proxy = wax_obj_proxy::make( - boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2), - boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2) - ); +void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd, size_t which_dsp){ + _dsp_impl->continuous_streaming[which_dsp] = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS; + _iface->poke32(_iface->regs.rx_ctrl[which_dsp].stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd)); + _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_secs, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); + _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); +} - //initial config and update - ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); - ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_decim)); +void usrp2_mboard_impl::handle_overflow(size_t which_dsp){ + if (_dsp_impl->continuous_streaming[which_dsp]){ //re-issue the stream command if already continuous + this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS, which_dsp); + } } /*********************************************************************** * DDC Properties **********************************************************************/ -void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()){ case DSP_PROP_NAME: - val = _iface->get_cname() + " ddc0"; + val = str(boost::format("%s ddc%d") % _iface->get_cname() % which_dsp); return; case DSP_PROP_OTHERS: @@ -72,11 +140,7 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_FREQ_SHIFT: - val = _ddc_freq; - return; - - case DSP_PROP_FREQ_SHIFT_NAMES: - val = prop_names_t(1, ""); + val = _dsp_impl->ddc_freq[which_dsp]; return; case DSP_PROP_CODEC_RATE: @@ -84,37 +148,41 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_HOST_RATE: - val = get_master_clock_freq()/_ddc_decim; + val = get_master_clock_freq()/_dsp_impl->ddc_decim[which_dsp]; return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){ +void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()){ + case DSP_PROP_STREAM_CMD: + issue_ddc_stream_cmd(val.as<stream_cmd_t>(), which_dsp); + return; + case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as<double>(); - _iface->poke32(_iface->regs.dsp_rx_freq, + _iface->poke32(_iface->regs.dsp_rx[which_dsp].freq, dsp_type1::calc_cordic_word_and_update(new_freq, get_master_clock_freq()) ); - _ddc_freq = new_freq; //shadow + _dsp_impl->ddc_freq[which_dsp] = new_freq; //shadow } return; case DSP_PROP_HOST_RATE:{ double extact_rate = get_master_clock_freq()/val.as<double>(); - _ddc_decim = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates); + _dsp_impl->ddc_decim[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates); //set the decimation - _iface->poke32(_iface->regs.dsp_rx_decim_rate, dsp_type1::calc_cic_filter_word(_ddc_decim)); + _iface->poke32(_iface->regs.dsp_rx[which_dsp].decim_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->ddc_decim[which_dsp])); //set the scaling static const boost::int16_t default_rx_scale_iq = 1024; - _iface->poke32(_iface->regs.dsp_rx_scale_iq, + _iface->poke32(_iface->regs.dsp_rx[which_dsp].scale_iq, dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) ); } @@ -125,29 +193,14 @@ void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){ } /*********************************************************************** - * DUC Helper Methods - **********************************************************************/ -void usrp2_mboard_impl::init_duc_config(void){ - //create the duc in the tx dsp dict - _tx_dsp_proxy = wax_obj_proxy::make( - boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2), - boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2) - ); - - //initial config and update - duc_set(DSP_PROP_FREQ_SHIFT, double(0)); - duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_interp)); -} - -/*********************************************************************** * DUC Properties **********************************************************************/ -void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()){ case DSP_PROP_NAME: - val = _iface->get_cname() + " duc0"; + val = str(boost::format("%s duc%d") % _iface->get_cname() % which_dsp); return; case DSP_PROP_OTHERS: @@ -155,11 +208,7 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_FREQ_SHIFT: - val = _duc_freq; - return; - - case DSP_PROP_FREQ_SHIFT_NAMES: - val = prop_names_t(1, ""); + val = _dsp_impl->duc_freq[which_dsp]; return; case DSP_PROP_CODEC_RATE: @@ -167,14 +216,14 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_HOST_RATE: - val = get_master_clock_freq()/_duc_interp; + val = get_master_clock_freq()/_dsp_impl->duc_interp[which_dsp]; return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){ +void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){ named_prop_t key = named_prop_t::extract(key_); switch(key.as<dsp_prop_t>()){ @@ -196,19 +245,19 @@ void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){ _iface->poke32(_iface->regs.dsp_tx_freq, dsp_type1::calc_cordic_word_and_update(new_freq, codec_rate) ); - _duc_freq = new_freq + dac_shift; //shadow + _dsp_impl->duc_freq[which_dsp] = new_freq + dac_shift; //shadow } return; case DSP_PROP_HOST_RATE:{ double extact_rate = get_master_clock_freq()/val.as<double>(); - _duc_interp = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates); + _dsp_impl->duc_interp[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates); //set the interpolation - _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_duc_interp)); + _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->duc_interp[which_dsp])); //set the scaling - _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_duc_interp)); + _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_dsp_impl->duc_interp[which_dsp])); } return; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index a22f805e1..68c49cafc 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -30,8 +30,8 @@ extern "C" { #endif //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 4 -#define USRP2_FW_COMPAT_NUM 8 +#define USRP2_FPGA_COMPAT_NUM 5 +#define USRP2_FW_COMPAT_NUM 9 //used to differentiate control packets over data port #define USRP2_INVALID_VRT_HEADER 0 @@ -40,8 +40,9 @@ extern "C" { // Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 //#define USRP2_UDP_UPDATE_PORT 49154 -#define USRP2_UDP_DATA_PORT 49156 +#define USRP2_UDP_DSP0_PORT 49156 #define USRP2_UDP_ERR0_PORT 49157 +#define USRP2_UDP_DSP1_PORT 49158 //////////////////////////////////////////////////////////////////////// // I2C addresses @@ -88,6 +89,9 @@ typedef enum{ USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO = 'v', USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE = 'V', + USRP2_CTRL_ID_HOLLER_AT_ME_BRO = 'l', + USRP2_CTRL_ID_HOLLER_BACK_DUDE = 'L', + USRP2_CTRL_ID_PEACE_OUT = '~' } usrp2_ctrl_id_t; @@ -132,6 +136,9 @@ typedef struct{ uint8_t bytes; uint8_t data[20]; } uart_args; + struct { + uint32_t len; + } echo_args; } data; } usrp2_ctrl_data_t; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index a22482271..340e9d155 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -18,6 +18,8 @@ #include "../../transport/vrt_packet_handler.hpp" #include "usrp2_impl.hpp" #include "usrp2_regs.hpp" +#include <uhd/exception.hpp> +#include <uhd/usrp/mboard_props.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/thread_priority.hpp> #include <uhd/transport/bounded_buffer.hpp> @@ -136,27 +138,26 @@ private: size_t _indexes; **********************************************************************/ struct usrp2_impl::io_impl{ - io_impl(size_t send_frame_size, const std::vector<zero_copy_if::sptr> &xports): - xports(xports), + io_impl(std::vector<zero_copy_if::sptr> &dsp_xports): + dsp_xports(dsp_xports), //the assumption is that all data transports should be identical get_recv_buffs_fcn(boost::bind(&usrp2_impl::io_impl::get_recv_buffs, this, _1)), get_send_buffs_fcn(boost::bind(&usrp2_impl::io_impl::get_send_buffs, this, _1)), - packet_handler_recv_state(xports.size()), - packet_handler_send_state(xports.size()), async_msg_fifo(100/*messages deep*/) { - for (size_t i = 0; i < xports.size(); i++){ - fc_mons.push_back(flow_control_monitor::sptr( - new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size) - )); - //init empty packet infos - vrt::if_packet_info_t packet_info; - packet_info.packet_count = 0xf; - packet_info.has_tsi = true; - packet_info.tsi = 0; - packet_info.has_tsf = true; - packet_info.tsf = 0; - prev_infos.push_back(packet_info); + for (size_t i = 0; i < dsp_xports.size(); i++){ + fc_mons.push_back(flow_control_monitor::sptr(new flow_control_monitor( + usrp2_impl::sram_bytes/dsp_xports.front()->get_send_frame_size() + )));; } + + //init empty packet infos + vrt::if_packet_info_t packet_info = vrt::if_packet_info_t(); + packet_info.packet_count = 0xf; + packet_info.has_tsi = true; + packet_info.tsi = 0; + packet_info.has_tsf = true; + packet_info.tsf = 0; + prev_infos.resize(dsp_xports.size(), packet_info); } ~io_impl(void){ @@ -166,15 +167,15 @@ struct usrp2_impl::io_impl{ } bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &buffs){ - UHD_ASSERT_THROW(xports.size() == buffs.size()); + UHD_ASSERT_THROW(send_map.size() == buffs.size()); //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(fc_word32, send_timeout)) return false; - buffs[i] = xports[i]->get_send_buff(send_timeout); + if (not fc_mons[send_map[i]]->check_fc_condition(fc_word32, send_timeout)) return false; + buffs[i] = dsp_xports[send_map[i]]->get_send_buff(send_timeout); if (not buffs[i].get()) return false; buffs[i]->cast<boost::uint32_t *>()[0] = uhd::htonx(fc_word32); } @@ -182,9 +183,13 @@ struct usrp2_impl::io_impl{ } alignment_indexes indexes_to_do; //used in alignment logic + time_spec_t expected_time; //used in alignment logic bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs); - const std::vector<zero_copy_if::sptr> &xports; + std::vector<zero_copy_if::sptr> &dsp_xports; + + //mappings from channel index to dsp xport + std::vector<size_t> send_map, recv_map; //timeouts set on calls to recv/send (passed into get buffs methods) double recv_timeout, send_timeout; @@ -204,7 +209,7 @@ struct usrp2_impl::io_impl{ vrt_packet_handler::send_state packet_handler_send_state; //methods and variables for the pirate crew - void recv_pirate_loop(zero_copy_if::sptr, usrp2_mboard_impl::sptr, size_t); + void recv_pirate_loop(usrp2_mboard_impl::sptr, zero_copy_if::sptr, size_t); boost::thread_group recv_pirate_crew; bool recv_pirate_crew_raiding; bounded_buffer<async_metadata_t> async_msg_fifo; @@ -218,17 +223,18 @@ struct usrp2_impl::io_impl{ * - put async message packets into queue **********************************************************************/ void usrp2_impl::io_impl::recv_pirate_loop( - zero_copy_if::sptr zc_if_err0, - usrp2_mboard_impl::sptr mboard, - size_t index + usrp2_mboard_impl::sptr mboard, zero_copy_if::sptr err_xport, size_t index ){ set_thread_priority_safe(); recv_pirate_crew_raiding = true; spawn_mutex.unlock(); + //store a reference to the flow control monitor (offset by max dsps) + flow_control_monitor &fc_mon = *(this->fc_mons[index*usrp2_mboard_impl::MAX_NUM_DSPS]); + while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = zc_if_err0->get_recv_buff(); + managed_recv_buffer::sptr buff = err_xport->get_recv_buff(); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -253,7 +259,7 @@ 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 = (vrt_hdr + if_packet_info.num_header_words32)[1]; - this->fc_mons[index]->update_fc_condition(uhd::ntohx(fc_word32)); + fc_mon.update_fc_condition(uhd::ntohx(fc_word32)); continue; } @@ -276,27 +282,52 @@ void usrp2_impl::io_impl::recv_pirate_loop( **********************************************************************/ void usrp2_impl::io_init(void){ - //the assumption is that all data transports should be identical - const size_t send_frame_size = _data_transports.front()->get_send_frame_size(); - //create new io impl - _io_impl = UHD_PIMPL_MAKE(io_impl, (send_frame_size, _data_transports)); + _io_impl = UHD_PIMPL_MAKE(io_impl, (dsp_xports)); //create a new pirate thread for each zc if (yarr!!) - for (size_t i = 0; i < _data_transports.size(); i++){ + for (size_t i = 0; i < _mboards.size(); i++){ //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( &usrp2_impl::io_impl::recv_pirate_loop, - _io_impl.get(), _err0_transports.at(i), - _mboards.at(i), i + _io_impl.get(), _mboards.at(i), err_xports.at(i), i )); //block here until the spawned thread unlocks _io_impl->spawn_mutex.lock(); //exit loop iteration in an unlocked condition _io_impl->spawn_mutex.unlock(); } + + //update mapping here since it didnt b4 when io init not called first + update_xport_channel_mapping(); +} + +void usrp2_impl::update_xport_channel_mapping(void){ + if (_io_impl.get() == NULL) return; //not inited yet + + _io_impl->recv_map.clear(); + _io_impl->send_map.clear(); + + for (size_t i = 0; i < _mboards.size(); i++){ + + subdev_spec_t rx_subdev_spec = _mboards[i]->get_link()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>(); + for (size_t j = 0; j < rx_subdev_spec.size(); j++){ + _io_impl->recv_map.push_back(i*usrp2_mboard_impl::MAX_NUM_DSPS+j); + //std::cout << "recv_map.back() " << _io_impl->recv_map.back() << std::endl; + } + + subdev_spec_t tx_subdev_spec = _mboards[i]->get_link()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>(); + for (size_t j = 0; j < tx_subdev_spec.size(); j++){ + _io_impl->send_map.push_back(i*usrp2_mboard_impl::MAX_NUM_DSPS+j); + //std::cout << "send_map.back() " << _io_impl->send_map.back() << std::endl; + } + + } + + _io_impl->packet_handler_recv_state = vrt_packet_handler::recv_state(_io_impl->recv_map.size()); + _io_impl->packet_handler_send_state = vrt_packet_handler::send_state(_io_impl->send_map.size()); } /*********************************************************************** @@ -318,7 +349,7 @@ size_t usrp2_impl::get_max_send_samps_per_packet(void) const{ + 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; + const size_t bpp = dsp_xports.front()->get_send_frame_size() - hdr_size; return bpp/_tx_otw_type.get_sample_size(); } @@ -388,49 +419,50 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs( vrt_packet_handler::managed_recv_buffs_t &buffs ){ if (buffs.size() == 1){ - buffs[0] = xports[0]->get_recv_buff(recv_timeout); + buffs[0] = dsp_xports[recv_map[0]]->get_recv_buff(recv_timeout); if (buffs[0].get() == NULL) return false; bool clear, msg; time_spec_t time; //unused variables //call extract_packet_info to handle printing the overflows - extract_packet_info(buffs[0], this->prev_infos[0], time, clear, msg); + extract_packet_info(buffs[0], this->prev_infos[recv_map[0]], time, clear, msg); return true; } //-------------------- begin alignment logic ---------------------// + UHD_ASSERT_THROW(recv_map.size() == buffs.size()); boost::system_time exit_time = boost::get_system_time() + to_time_dur(recv_timeout); managed_recv_buffer::sptr buff_tmp; bool clear, msg; - time_spec_t expected_time; + size_t index; //If we did not enter this routine with an empty indexes set, //jump to after the clear so we can preserve the previous state. //This saves buffers from being lost when using non-blocking recv. - if (not indexes_to_do.empty()) goto skip_reset; + if (not indexes_to_do.empty()) goto skip_pop_initial; //respond to a clear by starting from scratch got_clear: indexes_to_do.reset(buffs.size()); - skip_reset: clear = false; //do an initial pop to load an initial sequence id - size_t index = indexes_to_do.front(); - buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); + index = indexes_to_do.front(); + buff_tmp = dsp_xports[recv_map[index]]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); if (buff_tmp.get() == NULL) return false; - extract_packet_info(buff_tmp, this->prev_infos[index], expected_time, clear, msg); + extract_packet_info(buff_tmp, this->prev_infos[recv_map[index]], expected_time, clear, msg); if (clear) goto got_clear; buffs[index] = buff_tmp; if (msg) return handle_msg_packet(buffs, index); indexes_to_do.remove(index); + skip_pop_initial: //get an aligned set of elements from the buffers: while(not indexes_to_do.empty()){ //pop an element off for this index index = indexes_to_do.front(); - buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); + buff_tmp = dsp_xports[recv_map[index]]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time())); if (buff_tmp.get() == NULL) return false; time_spec_t this_time; - extract_packet_info(buff_tmp, this->prev_infos[index], this_time, clear, msg); + extract_packet_info(buff_tmp, this->prev_infos[recv_map[index]], this_time, clear, msg); if (clear) goto got_clear; buffs[index] = buff_tmp; if (msg) return handle_msg_packet(buffs, index); @@ -468,13 +500,14 @@ size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - const size_t bpp = _data_transports.front()->get_recv_frame_size() - hdr_size; + const size_t bpp = dsp_xports.front()->get_recv_frame_size() - hdr_size; return bpp/_rx_otw_type.get_sample_size(); } -static void handle_overflow(std::vector<usrp2_mboard_impl::sptr> &mboards, size_t chan){ +void usrp2_impl::handle_overflow(size_t chan){ std::cerr << "O" << std::flush; - mboards.at(chan/mboards.size())->handle_overflow(); + ldiv_t indexes = ldiv(chan, usrp2_mboard_impl::NUM_RX_DSPS); + _mboards.at(indexes.quot)->handle_overflow(indexes.rem); } size_t usrp2_impl::recv( @@ -491,6 +524,6 @@ size_t usrp2_impl::recv( _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_be, _io_impl->get_recv_buffs_fcn, - boost::bind(&handle_overflow, boost::ref(_mboards), _1) + boost::bind(&usrp2_impl::handle_overflow, this, _1) ); } diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 92a7b2f93..40fc5098b 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -19,11 +19,11 @@ #include "usrp2_regs.hpp" #include "fw_common.h" #include <uhd/utils/safe_call.hpp> +#include <uhd/exception.hpp> #include <uhd/usrp/gps_ctrl.hpp> #include <uhd/usrp/misc_utils.hpp> #include <uhd/usrp/dsp_utils.hpp> #include <uhd/usrp/mboard_props.hpp> -#include <uhd/utils/assert.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/algorithm.hpp> #include <boost/bind.hpp> @@ -35,35 +35,55 @@ static const size_t mimo_clock_sync_delay_cycles = 137; using namespace uhd; using namespace uhd::usrp; +using namespace uhd::transport; /*********************************************************************** - * Structors + * Helpers **********************************************************************/ -usrp2_mboard_impl::usrp2_mboard_impl( - size_t index, - transport::udp_simple::sptr ctrl_transport, - transport::zero_copy_if::sptr data_transport, - transport::zero_copy_if::sptr err0_transport, - const device_addr_t &device_args, - size_t recv_samps_per_packet -): - _index(index), - _iface(usrp2_iface::make(ctrl_transport)) -{ +static void init_xport(zero_copy_if::sptr xport){ //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; 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)) }; - send_buff = data_transport->get_send_buff(); - std::memcpy(send_buff->cast<void*>(), &data, sizeof(data)); - send_buff->commit(sizeof(data)); - send_buff = err0_transport->get_send_buff(); + + transport::managed_send_buffer::sptr send_buff = xport->get_send_buff(); std::memcpy(send_buff->cast<void*>(), &data, sizeof(data)); send_buff->commit(sizeof(data)); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp2_mboard_impl::usrp2_mboard_impl( + const device_addr_t &device_addr, + size_t index, usrp2_impl &device +): + _index(index), _device(device), + _iface(usrp2_iface::make(udp_simple::make_connected( + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) + ))) +{ + //construct transports for dsp and async errors + std::cout << "Making transport for DSP0..." << std::endl; + device.dsp_xports.push_back(udp_zero_copy::make( + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_DSP0_PORT), device_addr + )); + init_xport(device.dsp_xports.back()); + + std::cout << "Making transport for DSP1..." << std::endl; + device.dsp_xports.push_back(udp_zero_copy::make( + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_DSP1_PORT), device_addr + )); + init_xport(device.dsp_xports.back()); + + std::cout << "Making transport for ERR0..." << std::endl; + device.err_xports.push_back(udp_zero_copy::make( + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_ERR0_PORT), device_addr_t() + )); + init_xport(device.err_xports.back()); //contruct the interfaces to mboard perifs _clock_ctrl = usrp2_clock_ctrl::make(_iface); @@ -74,69 +94,33 @@ usrp2_mboard_impl::usrp2_mboard_impl( //if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl; - //TODO move to dsp impl... - //load the allowed decim/interp rates - //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) - _allowed_decim_and_interp_rates.clear(); - for (size_t i = 4; i <= 128; i+=1){ - _allowed_decim_and_interp_rates.push_back(i); - } - for (size_t i = 130; i <= 256; i+=2){ - _allowed_decim_and_interp_rates.push_back(i); - } - for (size_t i = 260; i <= 512; i+=4){ - _allowed_decim_and_interp_rates.push_back(i); - } - - //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_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, 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_clear_state, 1); //reset - _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); + //init the dsp stuff (before setting update packets) + dsp_init(); //setting the cycles per update (disabled by default) - const double ups_per_sec = device_args.cast<double>("ups_per_sec", 0.0); + const double ups_per_sec = device_addr.cast<double>("ups_per_sec", 0.0); if (ups_per_sec > 0.0){ const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec); _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up); } //setting the packets per update (enabled by default) - const double ups_per_fifo = device_args.cast<double>("ups_per_fifo", 8.0); + size_t send_frame_size = device.dsp_xports[0]->get_send_frame_size(); + const double ups_per_fifo = device_addr.cast<double>("ups_per_fifo", 8.0); if (ups_per_fifo > 0.0){ - const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size()); + const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/send_frame_size); _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up); } - //init the ddc - init_ddc_config(); - - //init the duc - init_duc_config(); - //initialize the clock configuration - if (device_args.has_key("mimo_mode")){ - if (device_args["mimo_mode"] == "master"){ + if (device_addr.has_key("mimo_mode")){ + if (device_addr["mimo_mode"] == "master"){ _mimo_clocking_mode_is_master = true; } - else if (device_args["mimo_mode"] == "slave"){ + else if (device_addr["mimo_mode"] == "slave"){ _mimo_clocking_mode_is_master = false; } - else throw std::runtime_error( + else throw uhd::value_error( "mimo_mode must be set to master or slave" ); } @@ -160,13 +144,18 @@ usrp2_mboard_impl::usrp2_mboard_impl( (*this)[MBOARD_PROP_RX_SUBDEV_SPEC] = subdev_spec_t(); (*this)[MBOARD_PROP_TX_SUBDEV_SPEC] = subdev_spec_t(); + //------------------------------------------------------------------ //This is a hack/fix for the lingering packet problem. stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); - stream_cmd.num_samps = 1; - this->issue_ddc_stream_cmd(stream_cmd); - data_transport->get_recv_buff().get(); //recv with timeout for lingering - data_transport->get_recv_buff().get(); //recv with timeout for expected - _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //resets sequence + for (size_t i = 0; i < NUM_RX_DSPS; i++){ + size_t index = device.dsp_xports.size() - NUM_RX_DSPS + i; + stream_cmd.num_samps = 1; + this->issue_ddc_stream_cmd(stream_cmd, i); + device.dsp_xports.at(index)->get_recv_buff(0.01).get(); //recv with timeout for lingering + device.dsp_xports.at(index)->get_recv_buff(0.01).get(); //recv with timeout for expected + _iface->poke32(_iface->regs.rx_ctrl[i].clear_overrun, 1); //resets sequence + } + //------------------------------------------------------------------ } usrp2_mboard_impl::~usrp2_mboard_impl(void){ @@ -191,14 +180,14 @@ void usrp2_mboard_impl::update_clock_config(void){ //translate pps source enums switch(_clock_config.pps_source){ case clock_config_t::PPS_SMA: pps_flags |= U2_FLAG_TIME64_PPS_SMA; break; - default: throw std::runtime_error("unhandled clock configuration pps source"); + default: throw uhd::value_error("unhandled clock configuration pps source"); } //translate pps polarity enums switch(_clock_config.pps_polarity){ case clock_config_t::PPS_POS: pps_flags |= U2_FLAG_TIME64_PPS_POSEDGE; break; case clock_config_t::PPS_NEG: pps_flags |= U2_FLAG_TIME64_PPS_NEGEDGE; break; - default: throw std::runtime_error("unhandled clock configuration pps polarity"); + default: throw uhd::value_error("unhandled clock configuration pps polarity"); } //set the pps flags @@ -211,7 +200,7 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; - default: throw std::runtime_error("unhandled clock configuration reference source"); + default: throw uhd::value_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO break; @@ -221,7 +210,7 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; - default: throw std::runtime_error("unhandled clock configuration reference source"); + default: throw uhd::value_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(_clock_config.ref_source != clock_config_t::REF_INT); break; @@ -275,19 +264,6 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ _iface->poke32(_iface->regs.time64_secs, boost::uint32_t(time_spec.get_full_secs())); } -void usrp2_mboard_impl::handle_overflow(void){ - if (_continuous_streaming){ //re-issue the stream command if already continuous - this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - } -} - -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(_iface->regs.rx_ctrl_stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd)); - _iface->poke32(_iface->regs.rx_ctrl_time_secs, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); - _iface->poke32(_iface->regs.rx_ctrl_time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); -} - /*********************************************************************** * MBoard Get Properties **********************************************************************/ @@ -324,21 +300,19 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DSP: - UHD_ASSERT_THROW(key.name == ""); - val = _rx_dsp_proxy->get_link(); + val = _rx_dsp_proxies[key.name]->get_link(); return; case MBOARD_PROP_RX_DSP_NAMES: - val = prop_names_t(1, ""); + val = _rx_dsp_proxies.keys(); return; case MBOARD_PROP_TX_DSP: - UHD_ASSERT_THROW(key.name == ""); - val = _tx_dsp_proxy->get_link(); + val = _tx_dsp_proxies[key.name]->get_link(); return; case MBOARD_PROP_TX_DSP_NAMES: - val = prop_names_t(1, ""); + val = _tx_dsp_proxies.keys(); return; case MBOARD_PROP_CLOCK_CONFIG: @@ -401,30 +375,32 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){ set_time_spec(val.as<time_spec_t>(), false); return; - case MBOARD_PROP_STREAM_CMD: - issue_ddc_stream_cmd(val.as<stream_cmd_t>()); - return; - case MBOARD_PROP_RX_SUBDEV_SPEC: _rx_subdev_spec = val.as<subdev_spec_t>(); verify_rx_subdev_spec(_rx_subdev_spec, this->get_link()); //sanity check - UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); + UHD_ASSERT_THROW(_rx_subdev_spec.size() <= NUM_RX_DSPS); //set the mux - _iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word( - _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() - )); + for (size_t i = 0; i < _rx_subdev_spec.size(); i++){ + if (_rx_subdev_spec.size() >= 1) _iface->poke32(_iface->regs.dsp_rx[i].mux, dsp_type1::calc_rx_mux_word( + _dboard_manager->get_rx_subdev(_rx_subdev_spec[i].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() + )); + } + _device.update_xport_channel_mapping(); return; case MBOARD_PROP_TX_SUBDEV_SPEC: _tx_subdev_spec = val.as<subdev_spec_t>(); verify_tx_subdev_spec(_tx_subdev_spec, this->get_link()); //sanity check - UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); + UHD_ASSERT_THROW(_tx_subdev_spec.size() <= NUM_TX_DSPS); //set the mux - _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word( - _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() - )); + for (size_t i = 0; i < _rx_subdev_spec.size(); i++){ + _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word( + _dboard_manager->get_tx_subdev(_tx_subdev_spec[i].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() + )); + } + _device.update_xport_channel_mapping(); return; case MBOARD_PROP_EEPROM_MAP: diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index bd1f5ccb5..e3827233b 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -18,8 +18,7 @@ #include "usrp2_regs.hpp" #include "fw_common.h" #include "usrp2_iface.hpp" -#include <uhd/utils/exception.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/types/dict.hpp> #include <boost/thread.hpp> #include <boost/foreach.hpp> @@ -27,7 +26,6 @@ #include <boost/assign/list_of.hpp> #include <boost/format.hpp> #include <boost/tokenizer.hpp> -#include <stdexcept> #include <algorithm> using namespace uhd; @@ -65,17 +63,13 @@ public: //check the fpga compatibility number const boost::uint32_t fpga_compat_num = this->peek32(this->regs.compat_num_rb); if (fpga_compat_num != USRP2_FPGA_COMPAT_NUM){ - throw std::runtime_error(str(boost::format( + throw uhd::runtime_error(str(boost::format( "Expected fpga compatibility number %d, but got %d:\n" "The fpga build is not compatible with the host code build." ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num)); } } - ~usrp2_iface_impl(void){ - /* NOP */ - } - /*********************************************************************** * Peek and Poke **********************************************************************/ @@ -247,7 +241,7 @@ public: while(true){ size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem), CTRL_RECV_TIMEOUT); if(len >= sizeof(boost::uint32_t) and ntohl(ctrl_data_in->proto_ver) != USRP2_FW_COMPAT_NUM){ - throw std::runtime_error(str(boost::format( + throw uhd::runtime_error(str(boost::format( "Expected protocol compatibility number %d, but got %d:\n" "The firmware build is not compatible with the host code build." ) % int(USRP2_FW_COMPAT_NUM) % ntohl(ctrl_data_in->proto_ver))); @@ -258,7 +252,7 @@ public: if (len == 0) break; //timeout //didnt get seq or bad packet, continue looking... } - throw std::runtime_error("no control response"); + throw uhd::runtime_error("no control response"); } rev_type get_rev(void){ diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index ea42d019f..df53ec66a 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -19,8 +19,7 @@ #define INCLUDED_USRP2_IFACE_HPP #include <uhd/transport/udp_simple.hpp> -#include <uhd/types/serial.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> +#include <uhd/usrp/mboard_iface.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include <boost/cstdint.hpp> @@ -39,10 +38,9 @@ typedef boost::function<std::string(void)> gps_recv_fn_t; * Provides a set of functions to implementation layer. * Including spi, peek, poke, control... */ -class usrp2_iface : public uhd::i2c_iface, boost::noncopyable{ +class usrp2_iface : public uhd::usrp::mboard_iface, boost::noncopyable{ public: typedef boost::shared_ptr<usrp2_iface> sptr; - /*! * Make a new usrp2 interface with the control transport. * \param ctrl_transport the udp transport object @@ -50,55 +48,6 @@ public: */ static sptr make(uhd::transport::udp_simple::sptr ctrl_transport); - /*! - * 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; - - virtual void write_uart(boost::uint8_t dev, const std::string &buf) = 0; - - virtual std::string read_uart(boost::uint8_t dev) = 0; - virtual gps_recv_fn_t get_gps_read_fn(void) = 0; virtual gps_send_fn_t get_gps_write_fn(void) = 0; diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 8fd88e01d..96552929a 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -17,20 +17,21 @@ #include "usrp2_impl.hpp" #include "fw_common.h" +#include <uhd/exception.hpp> #include <uhd/transport/if_addrs.hpp> #include <uhd/transport/udp_zero_copy.hpp> #include <uhd/usrp/device_props.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/warning.hpp> -#include <boost/algorithm/string.hpp> //for split +#include <uhd/utils/byteswap.hpp> #include <boost/assign/list_of.hpp> #include <boost/format.hpp> #include <boost/foreach.hpp> #include <boost/lexical_cast.hpp> -#include <boost/regex.hpp> #include <boost/bind.hpp> -#include <boost/asio.hpp> //htonl and ntohl +#include <boost/asio/ip/address_v4.hpp> +#include <boost/asio.hpp> //used for htonl and ntohl #include <iostream> #include <vector> @@ -40,76 +41,21 @@ using namespace uhd::transport; namespace asio = boost::asio; /*********************************************************************** - * Helper Functions - **********************************************************************/ -template <class T> std::string num2str(T num){ - return boost::lexical_cast<std::string>(num); -} - -//! separate indexed device addresses into a vector of device addresses -device_addrs_t sep_indexed_dev_addrs(const device_addr_t &dev_addr){ - //------------ support old deprecated way and print warning -------- - if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){ - std::vector<std::string> addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" ")); - if (addrs.size() > 1){ - device_addr_t fixed_dev_addr = dev_addr; - fixed_dev_addr.pop("addr"); - for (size_t i = 0; i < addrs.size(); i++){ - fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i]; - } - uhd::warning::post( - "addr = <space separated list of ip addresses> is deprecated.\n" - "To address a multi-device, use multiple <key><index> = <val>.\n" - "See the USRP-NXXX application notes. Two device example:\n" - " addr0 = 192.168.10.2\n" - " addr1 = 192.168.10.3\n" - ); - return sep_indexed_dev_addrs(fixed_dev_addr); - } - } - //------------------------------------------------------------------ - device_addrs_t dev_addrs; - BOOST_FOREACH(const std::string &key, dev_addr.keys()){ - boost::cmatch matches; - if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){ - throw std::runtime_error("unknown key format: " + key); - } - std::string key_part(matches[1].first, matches[1].second); - std::string num_part(matches[2].first, matches[2].second); - size_t num = (num_part.empty())? 0 : boost::lexical_cast<size_t>(num_part); - dev_addrs.resize(std::max(num+1, dev_addrs.size())); - dev_addrs[num][key_part] = dev_addr[key]; - } - return dev_addrs; -} - -//! combine a vector in device addresses into an indexed device address -device_addr_t combine_dev_addr_vector(const device_addrs_t &dev_addrs){ - device_addr_t dev_addr; - for (size_t i = 0; i < dev_addrs.size(); i++){ - BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){ - dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key]; - } - } - return dev_addr; -} - -/*********************************************************************** * Discovery over the udp transport **********************************************************************/ static device_addrs_t usrp2_find(const device_addr_t &hint_){ //handle the multi-device discovery - device_addrs_t hints = sep_indexed_dev_addrs(hint_); + device_addrs_t hints = separate_device_addr(hint_); if (hints.size() > 1){ device_addrs_t found_devices; BOOST_FOREACH(const device_addr_t &hint_i, hints){ device_addrs_t found_devices_i = usrp2_find(hint_i); - if (found_devices_i.size() != 1) throw std::runtime_error(str(boost::format( + if (found_devices_i.size() != 1) throw uhd::value_error(str(boost::format( "Could not resolve device hint \"%s\" to a single device." ) % hint_i.to_string())); found_devices.push_back(found_devices_i[0]); } - return device_addrs_t(1, combine_dev_addr_vector(found_devices)); + return device_addrs_t(1, combine_device_addrs(found_devices)); } //initialize the hint for a single device case @@ -148,8 +94,8 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){ //send a hello control packet usrp2_ctrl_data_t ctrl_data_out; - ctrl_data_out.proto_ver = htonl(USRP2_FW_COMPAT_NUM); - ctrl_data_out.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO); + ctrl_data_out.proto_ver = uhd::htonx<boost::uint32_t>(USRP2_FW_COMPAT_NUM); + ctrl_data_out.id = uhd::htonx<boost::uint32_t>(USRP2_CTRL_ID_WAZZUP_BRO); udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); //loop and recieve until the timeout @@ -168,9 +114,9 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){ //This operation can throw due to compatibility mismatch. //In this case, the discovered device will be ignored. try{ - mboard_eeprom_t mb_eeprom = usrp2_iface::make( - udp_simple::make_connected(new_addr["addr"], num2str(USRP2_UDP_CTRL_PORT)) - )->mb_eeprom; + mboard_eeprom_t mb_eeprom = usrp2_iface::make(udp_simple::make_connected( + new_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT) + ))->mb_eeprom; new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = mb_eeprom["serial"]; if ( @@ -199,57 +145,111 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){ * Make **********************************************************************/ static device::sptr usrp2_make(const device_addr_t &device_addr){ + return device::sptr(new usrp2_impl(device_addr)); +} - //setup the dsp transport hints (default to a large recv buff) - device_addr_t dsp_xport_hints = device_addr; - if (not dsp_xport_hints.has_key("recv_buff_size")){ - //only enable on platforms that are happy with the large buffer resize - #if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) - //set to half-a-second of buffering at max rate - dsp_xport_hints["recv_buff_size"] = "50e6"; - #endif /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/ - } +UHD_STATIC_BLOCK(register_usrp2_device){ + device::register_device(&usrp2_find, &usrp2_make); +} - //create a ctrl and data transport for each address - std::vector<udp_simple::sptr> ctrl_transports; - std::vector<zero_copy_if::sptr> data_transports; - std::vector<zero_copy_if::sptr> err0_transports; - const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr); +/*********************************************************************** + * MTU Discovery + **********************************************************************/ +struct mtu_result_t{ + size_t recv_mtu, send_mtu; +}; + +static mtu_result_t determine_mtu(const std::string &addr){ + udp_simple::sptr udp_sock = udp_simple::make_connected( + addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) + ); + + //The FPGA offers 4K buffers, and the user may manually request this. + //However, multiple simultaneous receives (2DSP slave + 2DSP master), + //require that buffering to be used internally, and this is a safe setting. + boost::uint8_t buffer[2000]; + usrp2_ctrl_data_t *ctrl_data = reinterpret_cast<usrp2_ctrl_data_t *>(buffer); + static const double echo_timeout = 0.020; //20 ms + + size_t min_recv_mtu = sizeof(usrp2_ctrl_data_t), max_recv_mtu = sizeof(buffer); + size_t min_send_mtu = sizeof(usrp2_ctrl_data_t), max_send_mtu = sizeof(buffer); + + while (min_recv_mtu < max_recv_mtu){ + + size_t test_mtu = (max_recv_mtu/2 + min_recv_mtu/2 + 3) & ~3; + //std::cout << "recv_mtu " << mtu.recv_mtu << std::endl; + + ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO); + ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM); + ctrl_data->data.echo_args.len = htonl(test_mtu); + udp_sock->send(boost::asio::buffer(buffer, sizeof(usrp2_ctrl_data_t))); + + size_t len = udp_sock->recv(boost::asio::buffer(buffer), echo_timeout); + + if (len >= test_mtu) min_recv_mtu = test_mtu; + else max_recv_mtu = test_mtu - 4; - BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){ - ctrl_transports.push_back(udp_simple::make_connected( - dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT) - )); - data_transports.push_back(udp_zero_copy::make( - dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), dsp_xport_hints - )); - err0_transports.push_back(udp_zero_copy::make( - dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr_t() - )); } - //create the usrp2 implementation guts - return device::sptr(new usrp2_impl( - ctrl_transports, data_transports, err0_transports, device_addrs - )); -} + while (min_send_mtu < max_send_mtu){ -UHD_STATIC_BLOCK(register_usrp2_device){ - device::register_device(&usrp2_find, &usrp2_make); + size_t test_mtu = (max_send_mtu/2 + min_send_mtu/2 + 3) & ~3; + //std::cout << "send_mtu " << mtu.send_mtu << std::endl; + + ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO); + ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM); + ctrl_data->data.echo_args.len = htonl(sizeof(usrp2_ctrl_data_t)); + udp_sock->send(boost::asio::buffer(buffer, test_mtu)); + + size_t len = udp_sock->recv(boost::asio::buffer(buffer), echo_timeout); + if (len >= sizeof(usrp2_ctrl_data_t)) len = ntohl(ctrl_data->data.echo_args.len); + + if (len >= test_mtu) min_send_mtu = test_mtu; + else max_send_mtu = test_mtu - 4; + } + + mtu_result_t mtu; + mtu.recv_mtu = min_recv_mtu; + mtu.send_mtu = min_send_mtu; + return mtu; } /*********************************************************************** * Structors **********************************************************************/ -usrp2_impl::usrp2_impl( - std::vector<udp_simple::sptr> ctrl_transports, - std::vector<zero_copy_if::sptr> data_transports, - std::vector<zero_copy_if::sptr> err0_transports, - const device_addrs_t &device_args -): - _data_transports(data_transports), - _err0_transports(err0_transports) -{ +usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ + device_addr_t device_addr = _device_addr; + + //setup the dsp transport hints (default to a large recv buff) + if (not device_addr.has_key("recv_buff_size")){ + #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) + //limit buffer resize on macos or it will error + device_addr["recv_buff_size"] = "1e6"; + #elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) + //set to half-a-second of buffering at max rate + device_addr["recv_buff_size"] = "50e6"; + #endif + } + + device_addrs_t device_args = separate_device_addr(device_addr); + + //calculate the minimum send and recv mtu of all devices + mtu_result_t mtu = determine_mtu(device_args[0]["addr"]); + for (size_t i = 1; i < device_args.size(); i++){ + mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"]); + mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu); + mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu); + } + + std::cout << "mtu recv bytes " << mtu.recv_mtu << std::endl; + std::cout << "mtu send bytes " << mtu.send_mtu << std::endl; + + //use the discovered mtu if not specified by the user + if (not device_addr.has_key("recv_frame_size")) + device_addr["recv_frame_size"] = boost::lexical_cast<std::string>(mtu.recv_mtu); + if (not device_addr.has_key("send_frame_size")) + device_addr["send_frame_size"] = boost::lexical_cast<std::string>(mtu.send_mtu); + //setup rx otw type _rx_otw_type.width = 16; _rx_otw_type.shift = 0; @@ -264,13 +264,16 @@ usrp2_impl::usrp2_impl( //create a new mboard handler for each control transport for(size_t i = 0; i < device_args.size(); i++){ - _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( - i, ctrl_transports[i], data_transports[i], - err0_transports[i], device_args[i], - this->get_max_recv_samps_per_packet() - ))); + device_addr_t dev_addr_i = device_args[i]; + BOOST_FOREACH(const std::string &key, device_addr.keys()){ + if (dev_addr_i.has_key(key)) continue; + dev_addr_i[key] = device_addr[key]; + } + _mboards.push_back(usrp2_mboard_impl::sptr( + new usrp2_mboard_impl(dev_addr_i, i, *this) + )); //use an empty name when there is only one mboard - std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : ""; + std::string name = (device_args.size() > 1)? boost::lexical_cast<std::string>(i) : ""; _mboard_dict[name] = _mboards.back(); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 337f842d6..0676cecf2 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -71,6 +71,8 @@ private: void set(const wax::obj &key, const wax::obj &val){return _set(key, val);} }; +class usrp2_impl; + /*! * USRP2 mboard implementation guts: * The implementation details are encapsulated here. @@ -80,14 +82,14 @@ class usrp2_mboard_impl : public wax::obj{ public: typedef boost::shared_ptr<usrp2_mboard_impl> sptr; + static const size_t NUM_RX_DSPS = 2; + static const size_t NUM_TX_DSPS = 1; + static const size_t MAX_NUM_DSPS = 2; + //structors usrp2_mboard_impl( - size_t index, - uhd::transport::udp_simple::sptr, - uhd::transport::zero_copy_if::sptr, - uhd::transport::zero_copy_if::sptr, - const uhd::device_addr_t &device_args, - size_t recv_samps_per_packet + const uhd::device_addr_t &device_addr, + size_t index, usrp2_impl &device ); ~usrp2_mboard_impl(void); @@ -95,11 +97,11 @@ public: return _clock_ctrl->get_master_clock_rate(); } - void handle_overflow(void); + void handle_overflow(size_t); private: size_t _index; - bool _continuous_streaming; + usrp2_impl &_device; bool _mimo_clocking_mode_is_master; //interfaces @@ -147,27 +149,20 @@ private: wax_obj_proxy::sptr _tx_dboard_proxy; uhd::usrp::dboard_eeprom_t _tx_db_eeprom; - //methods and shadows for the ddc dsp - std::vector<size_t> _allowed_decim_and_interp_rates; - size_t _ddc_decim; - double _ddc_freq; - void init_ddc_config(void); - void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd); - - //methods and shadows for the duc dsp - size_t _duc_interp; - double _duc_freq; - void init_duc_config(void); + //methods and shadows for the dsps + UHD_PIMPL_DECL(dsp_impl) _dsp_impl; + void dsp_init(void); + void issue_ddc_stream_cmd(const uhd::stream_cmd_t &, size_t); //properties interface for ddc - void ddc_get(const wax::obj &, wax::obj &); - void ddc_set(const wax::obj &, const wax::obj &); - wax_obj_proxy::sptr _rx_dsp_proxy; + void ddc_get(const wax::obj &, wax::obj &, size_t); + void ddc_set(const wax::obj &, const wax::obj &, size_t); + uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies; //properties interface for duc - void duc_get(const wax::obj &, wax::obj &); - void duc_set(const wax::obj &, const wax::obj &); - wax_obj_proxy::sptr _tx_dsp_proxy; + void duc_get(const wax::obj &, wax::obj &, size_t); + void duc_set(const wax::obj &, const wax::obj &, size_t); + uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies; }; @@ -182,19 +177,7 @@ public: static const boost::uint32_t RECV_SID = 1; static const boost::uint32_t ASYNC_SID = 2; - /*! - * Create a new usrp2 impl base. - * \param ctrl_transports the udp transports for control - * \param data_transports the udp transports for data - * \param err0_transports the udp transports for error - * \param device_args optional misc device parameters - */ - usrp2_impl( - std::vector<uhd::transport::udp_simple::sptr> ctrl_transports, - std::vector<uhd::transport::zero_copy_if::sptr> data_transports, - std::vector<uhd::transport::zero_copy_if::sptr> err0_transports, - const uhd::device_addrs_t &device_args - ); + usrp2_impl(const uhd::device_addr_t &); ~usrp2_impl(void); @@ -213,6 +196,14 @@ public: size_t get_max_recv_samps_per_packet(void) const; bool recv_async_msg(uhd::async_metadata_t &, double); + void update_xport_channel_mapping(void); + + //public frame sizes, set by mboard, used by io impl + size_t recv_frame_size, send_frame_size; + + std::vector<uhd::transport::zero_copy_if::sptr> dsp_xports; + std::vector<uhd::transport::zero_copy_if::sptr> err_xports; + private: //device properties interface void get(const wax::obj &, wax::obj &); @@ -223,11 +214,10 @@ private: uhd::dict<std::string, usrp2_mboard_impl::sptr> _mboard_dict; //io impl methods and members - std::vector<uhd::transport::zero_copy_if::sptr> _data_transports; - std::vector<uhd::transport::zero_copy_if::sptr> _err0_transports; uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); + void handle_overflow(size_t); }; #endif /* INCLUDED_USRP2_IMPL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index 84907c32e..66c3ac137 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -38,8 +38,10 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) { x.sr_udp_sm = 96; x.sr_tx_dsp = 208; x.sr_tx_ctrl = 224; - x.sr_rx_dsp = 160; - x.sr_rx_ctrl = 176; + x.sr_rx_dsp0 = 160; + x.sr_rx_ctrl0 = 176; + x.sr_rx_dsp1 = 240; + x.sr_rx_ctrl1 = 32; x.sr_time64 = 192; x.sr_simtimer = 198; x.sr_last = 255; @@ -68,12 +70,18 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) { x.dsp_tx_scale_iq = sr_addr(misc_output_base, x.sr_tx_dsp + 1); x.dsp_tx_interp_rate = sr_addr(misc_output_base, x.sr_tx_dsp + 2); x.dsp_tx_mux = sr_addr(misc_output_base, x.sr_tx_dsp + 4); - x.dsp_rx_freq = sr_addr(misc_output_base, x.sr_rx_dsp + 0); - x.dsp_rx_scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp + 1); - x.dsp_rx_decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp + 2); - x.dsp_rx_dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp + 3); - x.dsp_rx_dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp + 4); - x.dsp_rx_mux = sr_addr(misc_output_base, x.sr_rx_dsp + 5); + x.dsp_rx[0].freq = sr_addr(misc_output_base, x.sr_rx_dsp0 + 0); + x.dsp_rx[0].scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp0 + 1); + x.dsp_rx[0].decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp0 + 2); + x.dsp_rx[0].dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp0 + 3); + x.dsp_rx[0].dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp0 + 4); + x.dsp_rx[0].mux = sr_addr(misc_output_base, x.sr_rx_dsp0 + 5); + x.dsp_rx[1].freq = sr_addr(misc_output_base, x.sr_rx_dsp1 + 0); + x.dsp_rx[1].scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp1 + 1); + x.dsp_rx[1].decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp1 + 2); + x.dsp_rx[1].dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp1 + 3); + x.dsp_rx[1].dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp1 + 4); + x.dsp_rx[1].mux = sr_addr(misc_output_base, x.sr_rx_dsp1 + 5); x.gpio_io = gpio_base + 0; x.gpio_ddr = gpio_base + 4; x.gpio_tx_sel = gpio_base + 8; @@ -86,15 +94,24 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) { x.atr_inrx_rxside = atr_base + 10; x.atr_full_txside = atr_base + 12; x.atr_full_rxside = atr_base + 14; - x.rx_ctrl_stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl + 0); - x.rx_ctrl_time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl + 1); - x.rx_ctrl_time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl + 2); - x.rx_ctrl_clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl + 3); - x.rx_ctrl_vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl + 4); - x.rx_ctrl_vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl + 5); - x.rx_ctrl_vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl + 6); - x.rx_ctrl_nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl + 7); - x.rx_ctrl_nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl + 8); + x.rx_ctrl[0].stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 0); + x.rx_ctrl[0].time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 1); + x.rx_ctrl[0].time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 2); + x.rx_ctrl[0].clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 3); + x.rx_ctrl[0].vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 4); + x.rx_ctrl[0].vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 5); + x.rx_ctrl[0].vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 6); + x.rx_ctrl[0].nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 7); + x.rx_ctrl[0].nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 8); + x.rx_ctrl[1].stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 0); + x.rx_ctrl[1].time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 1); + x.rx_ctrl[1].time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 2); + x.rx_ctrl[1].clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 3); + x.rx_ctrl[1].vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 4); + x.rx_ctrl[1].vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 5); + x.rx_ctrl[1].vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 6); + x.rx_ctrl[1].nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 7); + x.rx_ctrl[1].nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 8); x.tx_ctrl_num_chan = sr_addr(misc_output_base, x.sr_tx_ctrl + 0); x.tx_ctrl_clear_state = sr_addr(misc_output_base, x.sr_tx_ctrl + 1); x.tx_ctrl_report_sid = sr_addr(misc_output_base, x.sr_tx_ctrl + 2); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 977b342cb..01f5ee65a 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -38,8 +38,10 @@ typedef struct { int sr_udp_sm; int sr_tx_dsp; int sr_tx_ctrl; - int sr_rx_dsp; - int sr_rx_ctrl; + int sr_rx_dsp0; + int sr_rx_ctrl0; + int sr_rx_dsp1; + int sr_rx_ctrl1; int sr_time64; int sr_simtimer; int sr_last; @@ -68,12 +70,14 @@ typedef struct { int dsp_tx_scale_iq; int dsp_tx_interp_rate; int dsp_tx_mux; - int dsp_rx_freq; - int dsp_rx_scale_iq; - int dsp_rx_decim_rate; - int dsp_rx_dcoffset_i; - int dsp_rx_dcoffset_q; - int dsp_rx_mux; + struct{ + int freq; + int scale_iq; + int decim_rate; + int dcoffset_i; + int dcoffset_q; + int mux; + } dsp_rx[2]; int gpio_base; int gpio_io; int gpio_ddr; @@ -88,15 +92,17 @@ typedef struct { int atr_inrx_rxside; int atr_full_txside; int atr_full_rxside; - int rx_ctrl_stream_cmd; - int rx_ctrl_time_secs; - int rx_ctrl_time_ticks; - int rx_ctrl_clear_overrun; - int rx_ctrl_vrt_header; - int rx_ctrl_vrt_stream_id; - int rx_ctrl_vrt_trailer; - int rx_ctrl_nsamps_per_pkt; - int rx_ctrl_nchannels; + struct{ + int stream_cmd; + int time_secs; + int time_ticks; + int clear_overrun; + int vrt_header; + int vrt_stream_id; + int vrt_trailer; + int nsamps_per_pkt; + int nchannels; + } rx_ctrl[2]; int tx_ctrl_num_chan; int tx_ctrl_clear_state; int tx_ctrl_report_sid; diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index e29fe18ce..aba630d88 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -17,7 +17,7 @@ #include "clock_ctrl.hpp" #include "ad9522_regs.hpp" -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <boost/cstdint.hpp> #include "usrp_e100_regs.hpp" //spi slave constants #include <boost/assign/list_of.hpp> @@ -158,7 +158,7 @@ static clock_settings_type get_clock_settings(double rate){ } } - throw std::runtime_error(str(boost::format( + throw uhd::value_error(str(boost::format( "USRP-E100 clock control: could not calculate settings for clock rate %fMHz" ) % (rate/1e6))); } @@ -302,7 +302,7 @@ public: _ad9522_regs.out4_cmos_configuration = (enb)? ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; - this->send_reg(0x0F0); + this->send_reg(0x0F4); this->latch_regs(); } @@ -409,10 +409,10 @@ private: 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( + _iface->write_spi( UE_SPI_SS_AD9522, spi_config_t::EDGE_RISE, - reg, 24, false /*no rb*/ + reg, 24 ); } @@ -427,9 +427,9 @@ private: //wait for calibration done: static const boost::uint8_t addr = 0x01F; for (size_t ms10 = 0; ms10 < 100; ms10++){ - boost::uint32_t reg = _iface->transact_spi( + boost::uint32_t reg = _iface->read_spi( UE_SPI_SS_AD9522, spi_config_t::EDGE_RISE, - _ad9522_regs.get_read_reg(addr), 24, true /*rb*/ + _ad9522_regs.get_read_reg(addr), 24 ); _ad9522_regs.set_reg(addr, reg); if (_ad9522_regs.vco_calibration_finished) return; diff --git a/host/lib/usrp/usrp_e100/codec_ctrl.cpp b/host/lib/usrp/usrp_e100/codec_ctrl.cpp index b33c8ae65..50442546a 100644 --- a/host/lib/usrp/usrp_e100/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/codec_ctrl.cpp @@ -18,7 +18,7 @@ #include "codec_ctrl.hpp" #include "ad9862_regs.hpp" #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/algorithm.hpp> #include <boost/cstdint.hpp> #include <boost/tuple/tuple.hpp> @@ -137,7 +137,7 @@ static const int mtpgw = 255; //maximum tx pga gain word void usrp_e100_codec_ctrl_impl::set_tx_pga_gain(double gain){ int gain_word = int(mtpgw*(gain - tx_pga_gain_range.start())/(tx_pga_gain_range.stop() - tx_pga_gain_range.start())); - _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw); + _ad9862_regs.tx_pga_gain = uhd::clip(gain_word, 0, mtpgw); this->send_reg(16); } @@ -149,7 +149,7 @@ static const int mrpgw = 0x14; //maximum rx pga gain word void usrp_e100_codec_ctrl_impl::set_rx_pga_gain(double gain, char which){ int gain_word = int(mrpgw*(gain - rx_pga_gain_range.start())/(rx_pga_gain_range.stop() - rx_pga_gain_range.start())); - gain_word = std::clip(gain_word, 0, mrpgw); + gain_word = uhd::clip(gain_word, 0, mrpgw); switch(which){ case 'A': _ad9862_regs.rx_pga_a = gain_word; @@ -227,7 +227,7 @@ double usrp_e100_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ 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); + UHD_THROW_INVALID_CODE_PATH(); } /*********************************************************************** @@ -236,7 +236,7 @@ double usrp_e100_codec_ctrl_impl::read_aux_adc(aux_adc_t which){ void usrp_e100_codec_ctrl_impl::write_aux_dac(aux_dac_t which, double 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); + boost::uint16_t dac_word = uhd::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); @@ -245,7 +245,7 @@ void usrp_e100_codec_ctrl_impl::write_aux_dac(aux_dac_t which, double volts){ } //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); + boost::uint8_t dac_word = uhd::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<boost::uint8_t*, boost::uint8_t> dac_params_t; @@ -269,20 +269,20 @@ void usrp_e100_codec_ctrl_impl::write_aux_dac(aux_dac_t which, double volts){ 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( + _iface->write_spi( UE_SPI_SS_AD9862, spi_config_t::EDGE_RISE, - reg, 16, false /*no rb*/ + reg, 16 ); } 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( + boost::uint32_t ret = _iface->read_spi( UE_SPI_SS_AD9862, spi_config_t::EDGE_RISE, - reg, 16, true /*rb*/ + reg, 16 ); 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_e100/codec_impl.cpp b/host/lib/usrp/usrp_e100/codec_impl.cpp index 0d91fb42c..ae198aaa5 100644 --- a/host/lib/usrp/usrp_e100/codec_impl.cpp +++ b/host/lib/usrp/usrp_e100/codec_impl.cpp @@ -16,7 +16,7 @@ // #include "usrp_e100_impl.hpp" -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/usrp/codec_props.hpp> #include <boost/bind.hpp> diff --git a/host/lib/usrp/usrp_e100/dboard_iface.cpp b/host/lib/usrp/usrp_e100/dboard_iface.cpp index e4c3856c9..4ee354486 100644 --- a/host/lib/usrp/usrp_e100/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e100/dboard_iface.cpp @@ -21,7 +21,7 @@ #include "codec_ctrl.hpp" #include <uhd/usrp/dboard_iface.hpp> #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <boost/assign/list_of.hpp> #include <linux/usrp_e.h> //i2c and spi constants @@ -235,7 +235,7 @@ static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t 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"); + UHD_THROW_INVALID_CODE_PATH(); } void usrp_e100_dboard_iface::write_spi( @@ -244,7 +244,7 @@ void usrp_e100_dboard_iface::write_spi( boost::uint32_t data, size_t num_bits ){ - _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); + _iface->write_spi(unit_to_otw_spi_dev(unit), config, data, num_bits); } boost::uint32_t usrp_e100_dboard_iface::read_write_spi( @@ -253,7 +253,7 @@ boost::uint32_t usrp_e100_dboard_iface::read_write_spi( boost::uint32_t data, size_t num_bits ){ - return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); + return _iface->read_spi(unit_to_otw_spi_dev(unit), config, data, num_bits); } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e100/dboard_impl.cpp b/host/lib/usrp/usrp_e100/dboard_impl.cpp index b533c2657..0b89fed9f 100644 --- a/host/lib/usrp/usrp_e100/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/dboard_impl.cpp @@ -17,7 +17,7 @@ #include "usrp_e100_impl.hpp" #include "usrp_e100_regs.hpp" -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/usrp/dboard_props.hpp> #include <uhd/usrp/subdev_props.hpp> #include <uhd/usrp/misc_utils.hpp> diff --git a/host/lib/usrp/usrp_e100/dsp_impl.cpp b/host/lib/usrp/usrp_e100/dsp_impl.cpp index 7d358a607..8d084f066 100644 --- a/host/lib/usrp/usrp_e100/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e100/dsp_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -60,10 +60,6 @@ void usrp_e100_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 = _clock_ctrl->get_fpga_clock_rate(); return; @@ -84,6 +80,10 @@ void usrp_e100_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ switch(key.as<dsp_prop_t>()){ + case DSP_PROP_STREAM_CMD: + issue_stream_cmd(val.as<stream_cmd_t>()); + return; + case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as<double>(); _iface->poke32(UE_REG_DSP_RX_FREQ, @@ -143,10 +143,6 @@ void usrp_e100_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 = _clock_ctrl->get_fpga_clock_rate(); return; diff --git a/host/lib/usrp/usrp_e100/fpga_downloader.cpp b/host/lib/usrp/usrp_e100/fpga_downloader.cpp index c0013fcbd..018a120d6 100644 --- a/host/lib/usrp/usrp_e100/fpga_downloader.cpp +++ b/host/lib/usrp/usrp_e100/fpga_downloader.cpp @@ -16,14 +16,21 @@ // #include <uhd/config.hpp> -#include <uhd/utils/assert.hpp> +#ifdef UHD_DLL_EXPORTS +#include <uhd/exception.hpp> +#else //special case when this file is externally included +#include <stdexcept> +namespace uhd{ + typedef std::runtime_error os_error; + typedef std::runtime_error io_error; +} +#endif #include <iostream> #include <sstream> #include <fstream> #include <string> #include <cstdlib> -#include <stdexcept> #include <fcntl.h> #include <sys/types.h> @@ -88,7 +95,7 @@ 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( + if (not export_file.is_open()) throw uhd::os_error( "Failed to open gpio export file." ); @@ -212,7 +219,7 @@ static void send_file_to_fpga(const std::string &file_name, gpio &error, gpio &d std::ifstream bitstream; bitstream.open(file_name.c_str(), std::ios::binary); - if (!bitstream.is_open()) throw std::runtime_error( + if (!bitstream.is_open()) throw uhd::os_error( "Coult not open the file: " + file_name ); diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index 0e08cd435..cec4fd0ad 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -17,9 +17,9 @@ #include "usrp_e100_impl.hpp" #include "usrp_e100_regs.hpp" +#include <uhd/exception.hpp> #include <uhd/usrp/dsp_utils.hpp> #include <uhd/usrp/misc_utils.hpp> -#include <uhd/utils/assert.hpp> #include <uhd/usrp/mboard_props.hpp> #include <boost/bind.hpp> #include <iostream> @@ -53,7 +53,7 @@ void usrp_e100_impl::update_clock_config(void){ 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"); + default: throw uhd::value_error("unhandled clock configuration pps polarity"); } //set the pps flags @@ -64,7 +64,7 @@ void usrp_e100_impl::update_clock_config(void){ case clock_config_t::REF_AUTO: _clock_ctrl->use_auto_ref(); break; case clock_config_t::REF_INT: _clock_ctrl->use_internal_ref(); break; case clock_config_t::REF_SMA: _clock_ctrl->use_auto_ref(); break; - default: throw std::runtime_error("unhandled clock configuration ref source"); + default: throw uhd::value_error("unhandled clock configuration ref source"); } } @@ -167,10 +167,6 @@ 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<mboard_prop_t>()){ - case MBOARD_PROP_STREAM_CMD: - issue_stream_cmd(val.as<stream_cmd_t>()); - return; - case MBOARD_PROP_TIME_NOW: case MBOARD_PROP_TIME_PPS:{ time_spec_t time_spec = val.as<time_spec_t>(); diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp index c13e880f3..ec0baf490 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp @@ -17,7 +17,7 @@ #include "usrp_e100_iface.hpp" #include "usrp_e100_regs.hpp" -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <sys/ioctl.h> //ioctl #include <fcntl.h> //open, close #include <linux/usrp_e.h> //ioctl structures and constants @@ -37,7 +37,7 @@ 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); + throw uhd::io_error("Failed to open " + node); } } @@ -106,12 +106,9 @@ public: { //open the device node and check file descriptor if ((_node_fd = ::open(node.c_str(), O_RDWR)) < 0){ - throw std::runtime_error("Failed to open " + node); + throw uhd::io_error("Failed to open " + node); } - //very first thing, reset all the wishbone, always do first! - //disabled for now: this->poke32(UE_REG_CLEAR_GLOBAL, 0); - mb_eeprom = mboard_eeprom_t(get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100); } @@ -127,7 +124,7 @@ public: boost::mutex::scoped_lock lock(_ctrl_mutex); if (::ioctl(_node_fd, request, mem) < 0){ - throw std::runtime_error(str( + throw uhd::os_error(str( boost::format("ioctl failed with request %d") % request )); } @@ -257,6 +254,14 @@ public: //unload the data return data.data; } + + void write_uart(boost::uint8_t, const std::string &) { + throw uhd::not_implemented_error("Unhandled command write_uart()"); + } + + std::string read_uart(boost::uint8_t) { + throw uhd::not_implemented_error("Unhandled command read_uart()"); + } private: int _node_fd; diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp index 12283fb52..cb0ca2dd4 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp @@ -24,6 +24,7 @@ #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include <boost/cstdint.hpp> +#include <uhd/usrp/mboard_iface.hpp> //////////////////////////////////////////////////////////////////////// // I2C addresses @@ -39,7 +40,7 @@ * Provides a set of functions to implementation layer. * Including spi, peek, poke, control... */ -class usrp_e100_iface : boost::noncopyable, public uhd::i2c_iface{ +class usrp_e100_iface : boost::noncopyable, public uhd::usrp::mboard_iface{ public: typedef boost::shared_ptr<usrp_e100_iface> sptr; @@ -67,51 +68,6 @@ public: //! 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 - * \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; - //motherboard eeprom map structure uhd::usrp::mboard_eeprom_t mb_eeprom; }; diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 40ea56466..a120c3303 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ #include "usrp_e100_regs.hpp" #include <uhd/usrp/device_props.hpp> #include <uhd/usrp/mboard_props.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/images.hpp> #include <uhd/utils/warning.hpp> @@ -53,7 +53,7 @@ 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"] = fs::system_complete(fs::path(hint["node"])).file_string(); + new_addr["node"] = fs::system_complete(fs::path(hint["node"])).string(); try{ usrp_e100_iface::sptr iface = usrp_e100_iface::make(new_addr["node"]); new_addr["name"] = iface->mb_eeprom["name"]; @@ -103,7 +103,7 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){ size_t fpga_hash = 0; { std::ifstream file(usrp_e100_fpga_image.c_str()); - if (not file.good()) throw std::runtime_error( + if (not file.good()) throw uhd::io_error( "cannot open fpga file for read: " + usrp_e100_fpga_image ); do{ @@ -132,7 +132,7 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){ //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( + throw uhd::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)); 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 index c155d426a..f4274dc5a 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp @@ -17,7 +17,7 @@ #include "usrp_e100_iface.hpp" #include <uhd/transport/zero_copy.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <linux/usrp_e.h> #include <sys/mman.h> //mmap #include <unistd.h> //getpagesize diff --git a/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp index a030462d0..1bcae64c7 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp @@ -131,7 +131,6 @@ #define UE_REG_CLEAR_ADDR(n) (UE_REG_SETTINGS_BASE_ADDR(48) + (4*(n))) #define UE_REG_CLEAR_RX UE_REG_CLEAR_ADDR(0) #define UE_REG_CLEAR_TX UE_REG_CLEAR_ADDR(1) -#define UE_REG_CLEAR_GLOBAL UE_REG_CLEAR_ADDR(2) ///////////////////////////////////////////////// // DSP RX Regs diff --git a/host/lib/usrp/wrapper_utils.hpp b/host/lib/usrp/wrapper_utils.hpp deleted file mode 100644 index a7b5c5da6..000000000 --- a/host/lib/usrp/wrapper_utils.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_LIBUHD_USRP_WRAPPER_UTILS_HPP -#define INCLUDED_LIBUHD_USRP_WRAPPER_UTILS_HPP - -#include <uhd/wax.hpp> -#include <uhd/types/ranges.hpp> -#include <uhd/usrp/dsp_props.hpp> -#include <uhd/utils/warning.hpp> -#include <boost/format.hpp> -#include <cmath> - -static inline uhd::freq_range_t add_dsp_shift( - const uhd::freq_range_t &range, - wax::obj dsp -){ - double codec_rate = dsp[uhd::usrp::DSP_PROP_CODEC_RATE].as<double>(); - return uhd::freq_range_t(range.start() - codec_rate/2.0, range.stop() + codec_rate/2.0); -} - -static inline void do_samp_rate_warning_message( - double target_rate, - double actual_rate, - const std::string &xx -){ - static const double max_allowed_error = 1.0; //Sps - if (std::abs(target_rate - actual_rate) > max_allowed_error){ - uhd::warning::post(str(boost::format( - "The hardware does not support the requested %s sample rate:\n" - "Target sample rate: %f MSps\n" - "Actual sample rate: %f MSps\n" - ) % xx % (target_rate/1e6) % (actual_rate/1e6))); - } -} - -static inline void do_tune_freq_warning_message( - double target_freq, - double actual_freq, - const std::string &xx -){ - static const double max_allowed_error = 1.0; //Hz - if (std::abs(target_freq - actual_freq) > max_allowed_error){ - uhd::warning::post(str(boost::format( - "The hardware does not support the requested %s frequency:\n" - "Target frequency: %f MHz\n" - "Actual frequency: %f MHz\n" - ) % xx % (target_freq/1e6) % (actual_freq/1e6))); - } -} - -#endif /* INCLUDED_LIBUHD_USRP_WRAPPER_UTILS_HPP */ diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index a4d3b2db2..c0d99b37e 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -110,7 +110,6 @@ SET_SOURCE_FILES_PROPERTIES( # Append sources ######################################################################## LIBUHD_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/assert.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp ${CMAKE_CURRENT_SOURCE_DIR}/images.cpp ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp diff --git a/host/lib/utils/assert.cpp b/host/lib/utils/assert.cpp deleted file mode 100644 index 7ace9024c..000000000 --- a/host/lib/utils/assert.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// - -#include <uhd/utils/assert.hpp> - -using namespace uhd; - -assert_error::assert_error(const std::string &what) : std::runtime_error(what){ - /* NOP */ -} diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp index 07aa21115..3af8a543d 100644 --- a/host/lib/utils/gain_group.cpp +++ b/host/lib/utils/gain_group.cpp @@ -18,7 +18,7 @@ #include <uhd/utils/gain_group.hpp> #include <uhd/types/dict.hpp> #include <uhd/utils/algorithm.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> #include <boost/foreach.hpp> #include <boost/bind.hpp> #include <algorithm> @@ -107,7 +107,7 @@ public: double gain_left_to_distribute = gain; BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){ const gain_range_t range = fcns.get_range(); - gain_bucket.push_back(floor_step(std::clip( + gain_bucket.push_back(floor_step(uhd::clip( gain_left_to_distribute, range.start(), range.stop() ), max_step)); gain_left_to_distribute -= gain_bucket.back(); @@ -131,7 +131,7 @@ public: //fill in the largest step sizes first that are less than the remainder BOOST_FOREACH(size_t i, indexes_step_size_dec){ const gain_range_t range = all_fcns.at(i).get_range(); - double additional_gain = floor_step(std::clip( + double additional_gain = floor_step(uhd::clip( gain_bucket.at(i) + gain_left_to_distribute, range.start(), range.stop() ), range.step()) - gain_bucket.at(i); gain_bucket.at(i) += additional_gain; @@ -167,7 +167,7 @@ private: //! get the gain function sets in order (highest priority first) std::vector<gain_fcns_t> get_all_fcns(void){ std::vector<gain_fcns_t> all_fcns; - BOOST_FOREACH(size_t key, std::sorted(_registry.keys())){ + BOOST_FOREACH(size_t key, uhd::sorted(_registry.keys())){ const std::vector<gain_fcns_t> &fcns = _registry[key]; all_fcns.insert(all_fcns.begin(), fcns.begin(), fcns.end()); } diff --git a/host/lib/utils/images.cpp b/host/lib/utils/images.cpp index 395e542c1..2b6c02772 100644 --- a/host/lib/utils/images.cpp +++ b/host/lib/utils/images.cpp @@ -16,9 +16,9 @@ // #include <uhd/utils/images.hpp> +#include <uhd/exception.hpp> #include <boost/foreach.hpp> #include <boost/filesystem.hpp> -#include <stdexcept> #include <vector> namespace fs = boost::filesystem; @@ -30,11 +30,11 @@ std::vector<fs::path> get_image_paths(void); //defined in paths.cpp **********************************************************************/ std::string uhd::find_image_path(const std::string &image_name){ if (fs::exists(image_name)){ - return fs::system_complete(image_name).file_string(); + return fs::system_complete(image_name).string(); } BOOST_FOREACH(const fs::path &path, get_image_paths()){ fs::path image_path = path / image_name; - if (fs::exists(image_path)) return image_path.file_string(); + if (fs::exists(image_path)) return image_path.string(); } - throw std::runtime_error("Could not find path for image: " + image_name); + throw uhd::io_error("Could not find path for image: " + image_name); } diff --git a/host/lib/utils/load_modules.cpp b/host/lib/utils/load_modules.cpp index fa9b22438..bee0d5304 100644 --- a/host/lib/utils/load_modules.cpp +++ b/host/lib/utils/load_modules.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -16,11 +16,11 @@ // #include <uhd/utils/static.hpp> +#include <uhd/exception.hpp> #include <boost/format.hpp> #include <boost/foreach.hpp> #include <boost/filesystem.hpp> #include <iostream> -#include <stdexcept> #include <string> #include <vector> @@ -33,7 +33,7 @@ namespace fs = boost::filesystem; #include <dlfcn.h> static void load_module(const std::string &file_name){ if (dlopen(file_name.c_str(), RTLD_LAZY) == NULL){ - throw std::runtime_error(str( + throw uhd::os_error(str( boost::format("dlopen failed to load \"%s\"") % file_name )); } @@ -45,7 +45,7 @@ static void load_module(const std::string &file_name){ #include <windows.h> static void load_module(const std::string &file_name){ if (LoadLibrary(file_name.c_str()) == NULL){ - throw std::runtime_error(str( + throw uhd::os_error(str( boost::format("LoadLibrary failed to load \"%s\"") % file_name )); } @@ -55,7 +55,7 @@ static void load_module(const std::string &file_name){ #ifdef HAVE_LOAD_MODULES_DUMMY static void load_module(const std::string &file_name){ - throw std::runtime_error(str( + throw uhd::not_implemented_error(str( boost::format("Module loading not supported: Cannot load \"%s\"") % file_name )); } @@ -72,7 +72,7 @@ static void load_module(const std::string &file_name){ */ static void load_module_path(const fs::path &path){ if (not fs::exists(path)){ - //std::cerr << boost::format("Module path \"%s\" not found.") % path.file_string() << std::endl; + //std::cerr << boost::format("Module path \"%s\" not found.") % path.string() << std::endl; return; } @@ -90,7 +90,7 @@ static void load_module_path(const fs::path &path){ //its not a directory, try to load it try{ - load_module(path.file_string()); + load_module(path.string()); } catch(const std::exception &err){ std::cerr << boost::format("Error: %s") % err.what() << std::endl; diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 8d604d849..329695873 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -22,7 +22,6 @@ #include <boost/filesystem.hpp> #include <boost/foreach.hpp> #include <boost/bind.hpp> -#include <stdexcept> #include <string> #include <vector> diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp index 18f372ec0..bd34055e8 100644 --- a/host/lib/utils/thread_priority.cpp +++ b/host/lib/utils/thread_priority.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -17,8 +17,8 @@ #include <uhd/utils/thread_priority.hpp> #include <uhd/utils/warning.hpp> +#include <uhd/exception.hpp> #include <boost/format.hpp> -#include <stdexcept> #include <iostream> bool uhd::set_thread_priority_safe(float priority, bool realtime){ @@ -59,13 +59,13 @@ static void check_priority_range(float priority){ //get the priority bounds for the selected policy int min_pri = sched_get_priority_min(policy); int max_pri = sched_get_priority_max(policy); - if (min_pri == -1 or max_pri == -1) throw std::runtime_error("error in sched_get_priority_min/max"); + if (min_pri == -1 or max_pri == -1) throw uhd::os_error("error in sched_get_priority_min/max"); //set the new priority and policy sched_param sp; sp.sched_priority = int(priority*(max_pri - min_pri)) + min_pri; int ret = pthread_setschedparam(pthread_self(), policy, &sp); - if (ret != 0) throw std::runtime_error("error in pthread_setschedparam"); + if (ret != 0) throw uhd::os_error("error in pthread_setschedparam"); } #endif /* HAVE_PTHREAD_SETSCHEDPARAM */ @@ -81,7 +81,7 @@ static void check_priority_range(float priority){ //set the priority class on the process int pri_class = (realtime)? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; if (SetPriorityClass(GetCurrentProcess(), pri_class) == 0) - throw std::runtime_error("error in SetPriorityClass"); + throw uhd::os_error("error in SetPriorityClass"); //scale the priority value to the constants int priorities[] = { @@ -92,7 +92,7 @@ static void check_priority_range(float priority){ //set the thread priority on the thread if (SetThreadPriority(GetCurrentThread(), priorities[pri_index]) == 0) - throw std::runtime_error("error in SetThreadPriority"); + throw uhd::os_error("error in SetThreadPriority"); } #endif /* HAVE_WIN_SETTHREADPRIORITY */ @@ -101,7 +101,7 @@ static void check_priority_range(float priority){ **********************************************************************/ #ifdef HAVE_LOAD_MODULES_DUMMY void uhd::set_thread_priority(float, bool){ - throw std::runtime_error("set thread priority not implemented"); + throw uhd::not_implemented_error("set thread priority not implemented"); } #endif /* HAVE_LOAD_MODULES_DUMMY */ diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp index bc4c79b6e..6a94a0a2c 100644 --- a/host/lib/utils/warning.cpp +++ b/host/lib/utils/warning.cpp @@ -16,12 +16,12 @@ // #include <uhd/utils/warning.hpp> +#include <uhd/exception.hpp> #include <boost/tokenizer.hpp> #include <uhd/utils/static.hpp> #include <uhd/types/dict.hpp> #include <boost/foreach.hpp> #include <sstream> -#include <stdexcept> #include <iostream> #include <vector> @@ -76,7 +76,7 @@ void warning::register_handler( } warning::handler_t warning::unregister_handler(const std::string &name){ - if (not get_registry().has_key(name)) throw std::runtime_error( + if (not get_registry().has_key(name)) throw uhd::key_error( "The warning registry does not have a handler registered to " + name ); return get_registry().pop(name); diff --git a/host/lib/wax.cpp b/host/lib/wax.cpp index 0e2e82a3a..5f658acd8 100644 --- a/host/lib/wax.cpp +++ b/host/lib/wax.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -16,6 +16,7 @@ // #include <uhd/wax.hpp> +#include <uhd/exception.hpp> #include <boost/format.hpp> #include <stdexcept> @@ -97,7 +98,7 @@ wax::obj wax::obj::operator[](const obj &key){ return val.as<link_args_t>()()[key]; } //unknown obj - throw std::runtime_error("cannot use [] on non wax::obj link"); + throw uhd::type_error("cannot use [] on non wax::obj link"); } else{ return proxy_args_t(this, key); @@ -142,9 +143,9 @@ boost::any wax::obj::resolve(void) const{ } void wax::obj::get(const obj &, obj &){ - throw std::runtime_error("Cannot call get on wax obj base class"); + throw uhd::type_error("Cannot call get on wax obj base class"); } void wax::obj::set(const obj &, const obj &){ - throw std::runtime_error("Cannot call set on wax obj base class"); + throw uhd::type_error("Cannot call set on wax obj base class"); } diff --git a/host/tests/error_test.cpp b/host/tests/error_test.cpp index c76a15ab7..983f0150c 100644 --- a/host/tests/error_test.cpp +++ b/host/tests/error_test.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -16,19 +16,30 @@ // #include <boost/test/unit_test.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/exception.hpp> +#include <uhd/utils/assert_has.hpp> #include <vector> #include <iostream> +BOOST_AUTO_TEST_CASE(test_exception_methods){ + try{ + throw uhd::assertion_error("your assertion failed: 1 != 2"); + } + catch(const uhd::exception &e){ + std::cout << "what: " << e.what() << std::endl; + std::cout << "code: " << e.code() << std::endl; + } +} + BOOST_AUTO_TEST_CASE(test_assert_has){ std::vector<int> vec; vec.push_back(2); vec.push_back(3); vec.push_back(5); - //verify the std::has utility - BOOST_CHECK(std::has(vec, 2)); - BOOST_CHECK(not std::has(vec, 1)); + //verify the uhd::has utility + BOOST_CHECK(uhd::has(vec, 2)); + BOOST_CHECK(not uhd::has(vec, 1)); std::cout << "The output of the assert_has error:" << std::endl; try{ diff --git a/host/tests/tune_helper_test.cpp b/host/tests/tune_helper_test.cpp index 735e7e948..aabaaaf6e 100644 --- a/host/tests/tune_helper_test.cpp +++ b/host/tests/tune_helper_test.cpp @@ -153,10 +153,6 @@ private: val = _freq_shift; return; - case DSP_PROP_FREQ_SHIFT_NAMES: - val = prop_names_t(1, ""); - return; - default: UHD_THROW_PROP_GET_ERROR(); } } @@ -190,12 +186,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){ dummy_dsp dsp(100e6); std::cout << "Testing tune helper RX automatic IF offset" << std::endl; - tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); + tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance); - double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); + double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance); } @@ -204,12 +200,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){ dummy_dsp dsp(100e6); std::cout << "Testing tune helper TX automatic IF offset" << std::endl; - tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); + tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance); - double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); + double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance); } @@ -218,12 +214,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){ dummy_dsp dsp(100e6); std::cout << "Testing tune helper RX dummy basic board" << std::endl; - tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 55e6); + tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 0.0, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance); - double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); + double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance); } @@ -235,21 +231,21 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){ std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl; subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6); dsp[DSP_PROP_HOST_RATE] = double(4e6); - tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance); std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl; subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6); dsp[DSP_PROP_HOST_RATE] = double(25e6); - tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance); std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl; subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6); dsp[DSP_PROP_HOST_RATE] = double(25e6); - tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance); } diff --git a/host/tests/wax_test.cpp b/host/tests/wax_test.cpp index 731f470ed..18730e0c2 100644 --- a/host/tests/wax_test.cpp +++ b/host/tests/wax_test.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 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 @@ -25,7 +25,7 @@ enum opt_b_t{OPTION_B_0, OPTION_B_1}; BOOST_AUTO_TEST_CASE(test_enums){ wax::obj opta = OPTION_A_0; - BOOST_CHECK_THROW(opta.as<opt_b_t>(), wax::bad_cast); + BOOST_CHECK_THROW(opta.as<opt_b_t>(), std::exception); BOOST_CHECK_EQUAL(opta.as<opt_a_t>(), OPTION_A_0); } diff --git a/host/usrp_e_utils/CMakeLists.txt b/host/usrp_e_utils/CMakeLists.txt index 1ecd2ac46..f3537e542 100644 --- a/host/usrp_e_utils/CMakeLists.txt +++ b/host/usrp_e_utils/CMakeLists.txt @@ -37,6 +37,7 @@ IF(ENABLE_USRP_E_UTILS) usrp-e-timed.c usrp-e-wb-test.cpp usrp-e-debug-pins.c + usrp-e-gpio.c usrp-e-i2c.c usrp-e-spi.c ) diff --git a/host/apps/omap_debug/usrp-e-gpio.c b/host/usrp_e_utils/usrp-e-gpio.c index adef877d3..7e4bc4e13 100644 --- a/host/apps/omap_debug/usrp-e-gpio.c +++ b/host/usrp_e_utils/usrp-e-gpio.c @@ -6,8 +6,8 @@ #include <string.h> #include <sys/ioctl.h> -#include "usrp_e.h" -#include "usrp_e_regs.hpp" +#include "linux/usrp_e.h" +#include "usrp_e100_regs.hpp" // Usage: usrp_e_gpio <string> diff --git a/host/usrp_e_utils/usrp-e-loopback.c b/host/usrp_e_utils/usrp-e-loopback.c index a63882475..0bd3d3100 100644 --- a/host/usrp_e_utils/usrp-e-loopback.c +++ b/host/usrp_e_utils/usrp-e-loopback.c @@ -38,11 +38,15 @@ static int calc_checksum(struct pkt *p) i = 0; sum = 0; - for (i=0; i < p->len; i++) - sum += p->data[i]; - - sum += p->seq_num; - sum += p->len; + if (p->len < 1016) { + for (i=0; i < p->len; i++) + sum += p->data[i]; + + sum += p->seq_num; + sum += p->len; + } else { + printf("Bad packet length = %d received.\n", p->len); + } return sum; } @@ -212,6 +216,11 @@ int main(int argc, char *argv[]) packet_data_length = atoi(argv[1]); + if (packet_data_length > 1016) { + packet_data_length = 1016; + printf("Max data length = 1016, clamping.\n"); + } + fp = open("/dev/usrp_e0", O_RDWR); printf("fp = %d\n", fp); diff --git a/host/utils/usrp_burn_db_eeprom.cpp b/host/utils/usrp_burn_db_eeprom.cpp index ac5608f22..617417e09 100644 --- a/host/utils/usrp_burn_db_eeprom.cpp +++ b/host/utils/usrp_burn_db_eeprom.cpp @@ -19,7 +19,7 @@ #include <uhd/utils/safe_main.hpp> #include <uhd/device.hpp> #include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> +#include <uhd/utils/assert_has.hpp> #include <uhd/usrp/dboard_eeprom.hpp> #include <uhd/usrp/device_props.hpp> #include <uhd/usrp/mboard_props.hpp> |