diff options
| author | Thomas Tsou <ttsou@vt.edu> | 2010-08-26 12:33:06 -0700 | 
|---|---|---|
| committer | Thomas Tsou <ttsou@vt.edu> | 2010-08-26 12:33:06 -0700 | 
| commit | 4434e8233fadc4eec81d345a6c4e63922d8c01ab (patch) | |
| tree | 392a85fc9f11f230eeb0cc8d0a17fdaa819b74bd | |
| parent | 2f3269f359043290fcaa7659e90292919306a8bc (diff) | |
| parent | fe7df530e69834e974108d2c3e682f38b8a75524 (diff) | |
| download | uhd-4434e8233fadc4eec81d345a6c4e63922d8c01ab.tar.gz uhd-4434e8233fadc4eec81d345a6c4e63922d8c01ab.tar.bz2 uhd-4434e8233fadc4eec81d345a6c4e63922d8c01ab.zip | |
Merge branch 'usrp1_next' into usrp1
21 files changed, 741 insertions, 635 deletions
| diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index dd1a20eed..0f1cbf2a2 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -27,6 +27,7 @@ INSTALL(FILES      udp_zero_copy.hpp      usb_control.hpp      usb_zero_copy.hpp +    usb_device_handle.hpp      vrt_if_packet.hpp      zero_copy.hpp      DESTINATION ${INCLUDE_DIR}/uhd/transport diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp index 6b5591a21..6137ecf84 100644 --- a/host/include/uhd/transport/usb_control.hpp +++ b/host/include/uhd/transport/usb_control.hpp @@ -18,11 +18,7 @@  #ifndef INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP  #define INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP -#include <uhd/config.hpp> -#include <uhd/types/usb_descriptor.hpp> -#include <boost/utility.hpp> -#include <boost/shared_ptr.hpp> -#include <vector> +#include "usb_device_handle.hpp"  namespace uhd { namespace transport { @@ -35,9 +31,9 @@ public:       * This transport is for sending and receiving control information from       * the host to device using the Default Control Pipe.       * -     * \param descriptor a descriptor that identifies a USB device +     * \param handle a device handle that uniquely identifies a USB device       */ -    static sptr make(usb_descriptor_t descriptor); +    static sptr make(usb_device_handle::sptr handle);      /*!       * Submit a USB device request: @@ -62,13 +58,6 @@ public:                            boost::uint16_t index,                             unsigned char *buff,                            boost::uint16_t length) = 0;  - -    /*! -     * Get a vector of USB device descriptors  -     * -     * \return a vector of usb_descriptors -     */ -    static usb_descriptors_t get_device_list();  };  }} //namespace diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp new file mode 100644 index 000000000..78c78f6b5 --- /dev/null +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -0,0 +1,79 @@ +// +// 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_TRANSPORT_USB_DEVICE_HANDLE_HPP +#define INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP + +#include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/cstdint.hpp> +#include <vector> + +namespace uhd { namespace transport { + +/*! + * Device handle class that represents a USB device + * Used for identifying devices on the USB bus and selecting which device is + * used when creating a  USB transport. A minimal subset of USB descriptor + * fields are used. Fields can be found in the USB 2.0 specification Table + * 9-8 (Standard Device Descriptor). In addition to fields of the device + * descriptor, the interface returns the device's USB device address. + * + * Note: The USB 2.0 Standard Device Descriptor contains an index rather then + *       a true descriptor serial number string. This interface returns the + *       actual string descriptor. + */ +class UHD_API usb_device_handle : boost::noncopyable { +public: +    typedef boost::shared_ptr<usb_device_handle> sptr; + +    /*! +     * Return the device's serial number  +     * \return a string describing the device's serial number +     */ +    virtual UHD_API std::string get_serial() const = 0; + +    /*! +     * Return the device's Vendor ID (usually assigned by the USB-IF) +     * \return a Vendor ID +     */ +    virtual UHD_API boost::uint16_t get_vendor_id() const = 0; + +    /*! +     * Return the device's Product ID (usually assigned by manufacturer) +     * \return a Product ID +     */ +    virtual UHD_API boost::uint16_t get_product_id() const = 0; + +    /*! +     * Return the device's USB address +     * \return a Product ID +     */ +    virtual UHD_API boost::uint16_t get_device_addr() const = 0; + +    /*! +     * Return a vector of USB devices on this host  +     * \return a vector of USB device handles +     */ +    static UHD_API std::vector<usb_device_handle::sptr> get_device_list(); + +}; //namespace usb + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP */ diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp index 7b9692fa5..2edd6d91d 100644 --- a/host/include/uhd/transport/usb_zero_copy.hpp +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -18,10 +18,8 @@  #ifndef INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP  #define INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP -#include <uhd/config.hpp> -#include <uhd/types/usb_descriptor.hpp> +#include "usb_device_handle.hpp"  #include <uhd/transport/zero_copy.hpp> -#include <boost/shared_ptr.hpp>  namespace uhd { namespace transport { @@ -46,13 +44,13 @@ public:       * The primary usage for this transport is data transactions.       * The underlying implementation may be platform specific.       * -     * \param descriptor a USB descriptor identifying the device +     * \param handle a device handle that uniquely identifying the device       * \param rx_endpoint an integer specifiying an IN endpoint number        * \param tx_endpoint an integer specifiying an OUT endpoint number       * \param buff_size total number of bytes of buffer space to allocate        * \param block_size number of bytes allocated for each I/O transaction        */ -    static sptr make(usb_descriptor_t descriptor, +    static sptr make(usb_device_handle::sptr handle,                       unsigned int rx_endpoint,                       unsigned int tx_endpoint,  		     size_t buff_size = 0,  diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 8e302eed2..dbce21c98 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -29,6 +29,5 @@ INSTALL(FILES      stream_cmd.hpp      time_spec.hpp      tune_result.hpp -    usb_descriptor.hpp      DESTINATION ${INCLUDE_DIR}/uhd/types  ) diff --git a/host/include/uhd/types/usb_descriptor.hpp b/host/include/uhd/types/usb_descriptor.hpp deleted file mode 100644 index 0e4c8c369..000000000 --- a/host/include/uhd/types/usb_descriptor.hpp +++ /dev/null @@ -1,49 +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_TYPES_USB_DESCRIPTOR_HPP -#define INCLUDED_UHD_TYPES_USB_DESCRIPTOR_HPP - -#include <uhd/config.hpp> -#include <boost/cstdint.hpp> -#include <vector> -#include <string> - -namespace uhd{ - -    /*! -     * The USB descriptor struct holds identity information for a USB device -     */ -    struct UHD_API usb_descriptor_t{ -        std::string serial; -        boost::uint16_t vendor_id; -        boost::uint16_t product_id; -        boost::uint16_t device_addr; - -        /*! -         * Create a pretty print string for this USB descriptor struct. -         * \return the printable string -         */ -        std::string to_pp_string(void) const; -    }; - -    //handy typde for a vector of usb descriptors -    typedef std::vector<usb_descriptor_t> usb_descriptors_t; - -} //namespace uhd - -#endif /* INCLUDED_UHD_TYPES_USB_DESCRIPTOR_HPP */ diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 627d2d806..753fd5e85 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -29,6 +29,8 @@ IF(LIBUSB_FOUND)      LIBUHD_APPEND_SOURCES(          ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_control.cpp          ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_zero_copy.cpp +        ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.cpp +        ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp      )      SET(HAVE_USB_SUPPORT TRUE)  ENDIF(LIBUSB_FOUND) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp new file mode 100644 index 000000000..6965de214 --- /dev/null +++ b/host/lib/transport/libusb1_base.cpp @@ -0,0 +1,118 @@ +// +// 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 "libusb1_base.hpp" +#include <iostream> + +using namespace uhd::transport; + +void libusb::init(libusb_context **ctx, int debug_level) +{ +    if (libusb_init(ctx) < 0) +        std::cerr << "error: libusb_init" << std::endl; + +    libusb_set_debug(*ctx, debug_level); +} + + +libusb_device_handle *libusb::open_device(libusb_context *ctx, +                                          usb_device_handle::sptr handle) +{ +    libusb_device **dev_list; +    libusb_device_handle *dev_handle; + +    ssize_t dev_cnt = libusb_get_device_list(ctx, &dev_list); + +    //find and open the receive device +    for (ssize_t i = 0; i < dev_cnt; i++) { +        libusb_device *dev = dev_list[i]; + +        if (compare_device(dev, handle)) { +            libusb_open(dev, &dev_handle); +            break; +        } +    } + +    libusb_free_device_list(dev_list, 0); + +    return dev_handle; +} + + +bool libusb::compare_device(libusb_device *dev, +                            usb_device_handle::sptr handle) +{ +    std::string serial         = handle->get_serial(); +    boost::uint16_t vendor_id  = handle->get_vendor_id(); +    boost::uint16_t product_id = handle->get_product_id(); +    boost::uint8_t device_addr = handle->get_device_addr(); + +    libusb_device_descriptor libusb_desc; +    if (libusb_get_device_descriptor(dev, &libusb_desc) < 0) +        return false; +    if (serial != get_serial(dev)) +        return false; +    if (vendor_id != libusb_desc.idVendor) +        return false; +    if (product_id != libusb_desc.idProduct) +        return false;  +    if (device_addr != libusb_get_device_address(dev)) +        return false; + +    return true; +} + + +bool libusb::open_interface(libusb_device_handle *dev_handle, +                            int interface) +{ +    int ret = libusb_claim_interface(dev_handle, interface); +    if (ret < 0) { +        std::cerr << "error: libusb_claim_interface() " << ret << std::endl; +        return false; +    } +    else { +        return true; +    } +} + + +std::string libusb::get_serial(libusb_device *dev) +{ +    unsigned char buff[32]; + +    libusb_device_descriptor desc; +    if (libusb_get_device_descriptor(dev, &desc) < 0) +        return ""; + +    if (desc.iSerialNumber == 0) +        return ""; + +    //open the device because we have to +    libusb_device_handle *dev_handle; +    if (libusb_open(dev, &dev_handle) < 0) +        return ""; + +    if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, +                                           buff, sizeof(buff)) < 0) { +        return ""; +    } + +    libusb_close(dev_handle); + +    return (char*) buff; +} diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp new file mode 100644 index 000000000..ae560cd52 --- /dev/null +++ b/host/lib/transport/libusb1_base.hpp @@ -0,0 +1,42 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_TRANSPORT_LIBUSB_HPP +#define INCLUDED_TRANSPORT_LIBUSB_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/usb_device_handle.hpp> +#include <libusb-1.0/libusb.h> + +namespace uhd { namespace transport { + +namespace libusb { +    void init(libusb_context **ctx, int debug_level); + +    libusb_device_handle *open_device(libusb_context *ctx, +                                      usb_device_handle::sptr handle); + +    bool compare_device(libusb_device *dev, usb_device_handle::sptr handle); + +    bool open_interface(libusb_device_handle *dev_handle, int interface); + +    std::string get_serial(libusb_device *dev); +} + +}} //namespace + +#endif /* INCLUDED_TRANSPORT_LIBUSB_HPP */ diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index c2f7060e8..8bf271256 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -15,24 +15,20 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#include <uhd/types/usb_descriptor.hpp> +#include "libusb1_base.hpp"  #include <uhd/transport/usb_control.hpp> -#include <libusb-1.0/libusb.h> -#include <boost/asio.hpp> -#include <stdexcept> -#include <iostream>  using namespace uhd::transport; -static int libusb_debug_level = 0; -static int libusb_timeout = 0; +const int libusb_debug_level = 3; +const int libusb_timeout = 0;  /***********************************************************************   * libusb-1.0 implementation of USB control transport   **********************************************************************/  class libusb_control_impl : public usb_control {  public: -    libusb_control_impl(uhd::usb_descriptor_t descriptor); +    libusb_control_impl(usb_device_handle::sptr handle);      ~libusb_control_impl();      size_t submit(boost::uint8_t request_type, @@ -42,34 +38,19 @@ public:                    unsigned char *buff,                    boost::uint16_t length);  -    static uhd::usb_descriptor_t create_descriptor(libusb_device *dev); -    static std::string get_serial(libusb_device *dev); -  private: -    uhd::usb_descriptor_t _descriptor; -      libusb_context       *_ctx;      libusb_device_handle *_dev_handle; - -    bool open_device(); -    bool open_interface(); -    bool compare_device(libusb_device *dev, uhd::usb_descriptor_t descriptor);  }; -libusb_control_impl::libusb_control_impl(uhd::usb_descriptor_t descriptor) - :  _descriptor(descriptor), _ctx(NULL), _dev_handle(NULL) +libusb_control_impl::libusb_control_impl(usb_device_handle::sptr handle)  { -    if (libusb_init(&_ctx) < 0) -        throw std::runtime_error("USB: failed to initialize libusb"); +    libusb::init(&_ctx, libusb_debug_level); -    libusb_set_debug(_ctx, libusb_debug_level); +    _dev_handle = libusb::open_device(_ctx, handle); -    if (!open_device()) -        throw std::runtime_error("USB: failed to open device"); - -    if (!open_interface()) -        throw std::runtime_error("USB: failed to open device interface"); +    libusb::open_interface(_dev_handle, 0);  } @@ -80,111 +61,6 @@ libusb_control_impl::~libusb_control_impl()  } -uhd::usb_descriptor_t libusb_control_impl::create_descriptor(libusb_device *dev) -{ -    libusb_device_descriptor desc; - -    if (libusb_get_device_descriptor(dev, &desc) < 0) -        throw std::runtime_error("USB: failed to get device descriptor"); - -    uhd::usb_descriptor_t descriptor; - -    descriptor.serial      = get_serial(dev);  -    descriptor.product_id  = desc.idProduct;    -    descriptor.vendor_id   = desc.idVendor; -    descriptor.device_addr = libusb_get_device_address(dev); - -    return descriptor; -} - - -std::string libusb_control_impl::get_serial(libusb_device *dev) -{ -    unsigned char buff[32]; - -    libusb_device_descriptor desc; -    if (libusb_get_device_descriptor(dev, &desc) < 0) -        return ""; - -    if (desc.iSerialNumber == 0) -        return ""; - -    //open the device because we have to -    libusb_device_handle *dev_handle; -    if (libusb_open(dev, &dev_handle) < 0) -        return ""; - -    if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, -                                           buff, sizeof(buff)) < 0) { -        return ""; -    } - -    libusb_close(dev_handle); - -    return (char*) buff; -} - - -bool libusb_control_impl::open_device() -{ -    libusb_device **list; -    libusb_device *dev; - -    ssize_t cnt = libusb_get_device_list(_ctx, &list); - -    if (cnt < 0) -        return cnt; - -    ssize_t i = 0; -    for (i = 0; i < cnt; i++) { -        dev = list[i]; -        if (compare_device(dev, _descriptor)) -            goto found; -    }  -    return false; - -found: -    int ret; -    if ((ret = libusb_open(dev, &_dev_handle)) < 0) -        return false; -    else  -        return true; -} - - -bool libusb_control_impl::compare_device(libusb_device *dev, -                                         uhd::usb_descriptor_t descriptor) -{ -    std::string serial         = descriptor.serial; -    boost::uint16_t vendor_id  = descriptor.vendor_id; -    boost::uint16_t product_id = descriptor.product_id; -    boost::uint8_t device_addr = descriptor.device_addr; - -    libusb_device_descriptor libusb_desc; -    if (libusb_get_device_descriptor(dev, &libusb_desc) < 0) -        return false; -    if (serial != get_serial(dev)) -        return false; -    if (vendor_id != libusb_desc.idVendor) -        return false; -    if (product_id != libusb_desc.idProduct) -        return false;  -    if (device_addr != libusb_get_device_address(dev)) -        return false; - -    return true; -} - - -bool libusb_control_impl::open_interface() -{ -    if (libusb_claim_interface(_dev_handle, 0) < 0) -        return false; -    else -        return true; -} - -  size_t libusb_control_impl::submit(boost::uint8_t request_type,                                     boost::uint8_t request,                                     boost::uint16_t value, @@ -206,33 +82,7 @@ size_t libusb_control_impl::submit(boost::uint8_t request_type,  /***********************************************************************   * USB control public make functions   **********************************************************************/ -usb_control::sptr usb_control::make(uhd::usb_descriptor_t descriptor) +usb_control::sptr usb_control::make(usb_device_handle::sptr handle)  { -    return sptr(new libusb_control_impl(descriptor)); +    return sptr(new libusb_control_impl(handle));  } - -uhd::usb_descriptors_t usb_control::get_device_list() -{ -    libusb_device **list; -    uhd::usb_descriptors_t descriptors; - -    if (libusb_init(NULL) < 0) -        throw std::runtime_error("USB: failed to initialize libusb"); - -    ssize_t cnt = libusb_get_device_list(NULL, &list); - -    if (cnt < 0) -        throw std::runtime_error("USB: failed to get device list"); - -    ssize_t i = 0; -    for (i = 0; i < cnt; i++) { -        libusb_device *dev = list[i]; -        descriptors.push_back(libusb_control_impl::create_descriptor(dev)); -    }  - -    libusb_free_device_list(list, 0); -    libusb_exit(NULL); -    return descriptors; -} - - diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp new file mode 100644 index 000000000..f80090f15 --- /dev/null +++ b/host/lib/transport/libusb1_device_handle.cpp @@ -0,0 +1,114 @@ +// +// 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 "libusb1_base.hpp" +#include <uhd/utils/assert.hpp> + +using namespace uhd::transport; + +const int libusb_debug_level = 3; + +class libusb1_device_handle_impl : public usb_device_handle { +public: +    libusb1_device_handle_impl(std::string serial, +                               boost::uint32_t product_id, +                               boost::uint32_t vendor_id, +                               boost::uint32_t device_addr) +      : _serial(serial), _product_id(product_id),  +        _vendor_id(vendor_id), _device_addr(device_addr) +    { +        /* NOP */ +    } + +    ~libusb1_device_handle_impl() +    { +        /* NOP */ +    } + +    std::string get_serial() const +    { +        return _serial; +    } + +    boost::uint16_t get_vendor_id() const +    { +        return _vendor_id; +    } + + +    boost::uint16_t get_product_id() const +    { +        return _product_id; +    } + +    boost::uint16_t get_device_addr() const +    { +        return _device_addr; +    } + +private: +    std::string     _serial; +    boost::uint32_t _product_id; +    boost::uint32_t _vendor_id; +    boost::uint32_t _device_addr; +}; + + +usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) +{ +    libusb_device_descriptor desc; + +    if (libusb_get_device_descriptor(dev, &desc) < 0) { +        UHD_ASSERT_THROW("USB: failed to get device descriptor"); +    } + +    std::string     serial      = libusb::get_serial(dev); +    boost::uint32_t product_id  = desc.idProduct; +    boost::uint32_t vendor_id   = desc.idVendor; +    boost::uint32_t device_addr = libusb_get_device_address(dev); + +    return usb_device_handle::sptr(new libusb1_device_handle_impl( +        serial, +        product_id, +        vendor_id, +        device_addr)); +} + + +std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list() +{ +    libusb_context *ctx = NULL; +    libusb_device **list; +    std::vector<usb_device_handle::sptr> device_list; + +    libusb::init(&ctx, libusb_debug_level); + +    ssize_t cnt = libusb_get_device_list(ctx, &list); + +    if (cnt < 0) +        throw std::runtime_error("USB: enumeration failed"); + +    ssize_t i = 0; +    for (i = 0; i < cnt; i++) { +        libusb_device *dev = list[i]; +        device_list.push_back(make_usb_device_handle(dev)); +    } + +    libusb_free_device_list(list, 0); +    libusb_exit(ctx); +    return device_list;  +} diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 39617e4dd..55aa10cbb 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -15,10 +15,9 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // - +#include "libusb1_base.hpp"  #include <uhd/transport/usb_zero_copy.hpp>  #include <uhd/utils/assert.hpp> -#include <libusb-1.0/libusb.h>  #include <boost/asio.hpp>  #include <boost/format.hpp>  #include <iostream> @@ -26,7 +25,8 @@  using namespace uhd::transport; -static int libusb_debug_level = 3; +const int libusb_debug_level = 3; +const int libusb_timeout = 0;  /***********************************************************************   * Helper functions @@ -347,7 +347,7 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut)          std::cerr << "USB: transfer timed out" << std::endl;          break;      case LIBUSB_TRANSFER_STALL: -        std::cerr << "USB: halt condition detected (endpoint stalled)" << std::endl; +        std::cerr << "USB: halt condition detected (stalled)" << std::endl;          break;      case LIBUSB_TRANSFER_ERROR:          std::cerr << "USB: transfer failed" << std::endl; @@ -606,26 +606,17 @@ private:      libusb_device_handle *_rx_dev_handle;      libusb_device_handle *_tx_dev_handle; -    int _rx_endpoint; -    int _tx_endpoint; -      size_t _recv_buff_size;      size_t _send_buff_size;      size_t _num_frames; -    bool open_device(uhd::usb_descriptor_t descriptor); -    bool open_interface(libusb_device_handle *dev_handle, int interface); -    bool compare_device(libusb_device *dev, uhd::usb_descriptor_t descriptor); - -    std::string get_serial(libusb_device *dev); -  public:      typedef boost::shared_ptr<libusb_zero_copy_impl> sptr;      /*       * Structors       */ -    libusb_zero_copy_impl(uhd::usb_descriptor_t descriptor, +    libusb_zero_copy_impl(usb_device_handle::sptr handle,                            unsigned int rx_endpoint,                            unsigned int tx_endpoint,                            size_t recv_buff_size, @@ -641,7 +632,7 @@ public:  }; -libusb_zero_copy_impl::libusb_zero_copy_impl(uhd::usb_descriptor_t descriptor, +libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle,                                               unsigned int rx_endpoint,                                               unsigned int tx_endpoint,                                               size_t buff_size, @@ -650,19 +641,16 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(uhd::usb_descriptor_t descriptor,     _recv_buff_size(block_size), _send_buff_size(block_size),     _num_frames(buff_size / block_size)  { -    if (libusb_init(&_rx_ctx) < 0) -        std::cerr << "error: libusb_init" << std::endl; +    libusb::init(&_rx_ctx, libusb_debug_level); +    libusb::init(&_tx_ctx, libusb_debug_level); -    if (libusb_init(&_tx_ctx) < 0) -        std::cerr << "error: libusb_init" << std::endl; +    UHD_ASSERT_THROW((_rx_ctx != NULL) && (_tx_ctx != NULL)); -    libusb_set_debug(_rx_ctx, libusb_debug_level); -    libusb_set_debug(_tx_ctx, libusb_debug_level); +    _rx_dev_handle = libusb::open_device(_rx_ctx, handle); +    _tx_dev_handle = libusb::open_device(_tx_ctx, handle); -    open_device(descriptor); - -    open_interface(_rx_dev_handle, 2); -    open_interface(_tx_dev_handle, 1); +    libusb::open_interface(_rx_dev_handle, 2); +    libusb::open_interface(_tx_dev_handle, 1);      _rx_ep = new usb_endpoint(_rx_dev_handle,                                _rx_ctx, @@ -693,117 +681,6 @@ libusb_zero_copy_impl::~libusb_zero_copy_impl()  } -bool libusb_zero_copy_impl::open_device(uhd::usb_descriptor_t descriptor) -{ -    libusb_device **rx_list; -    libusb_device **tx_list; - -    bool rx_found = false; -    bool tx_found = false; - -    ssize_t rx_cnt = libusb_get_device_list(_rx_ctx, &rx_list); -    ssize_t tx_cnt = libusb_get_device_list(_tx_ctx, &tx_list); - -    if ((rx_cnt < 0) | (tx_cnt < 0) | (rx_cnt != tx_cnt)) -        return false; - -    //find and open the receive device -    for (ssize_t i = 0; i < rx_cnt; i++) { -        libusb_device *dev = rx_list[i]; - -        if (compare_device(dev, descriptor)) { -            libusb_open(dev, &_rx_dev_handle); -            rx_found = true; -            break; -        } -    } - -    //find and open the transmit device -    for (ssize_t i = 0; i < tx_cnt; i++) { -        libusb_device *dev = tx_list[i]; - -        if (compare_device(dev, descriptor)) { -            libusb_open(dev, &_tx_dev_handle); -            tx_found = true; -        } -    } - -    libusb_free_device_list(rx_list, 0); -    libusb_free_device_list(tx_list, 0); - -    if (tx_found && rx_found) -        return true; -    else -        return false; -} - -bool libusb_zero_copy_impl::compare_device(libusb_device *dev, -                                        uhd::usb_descriptor_t descriptor) -{ -    std::string serial         = descriptor.serial; -    boost::uint16_t vendor_id  = descriptor.vendor_id; -    boost::uint16_t product_id = descriptor.product_id; -    boost::uint8_t device_addr = descriptor.device_addr; - -    libusb_device_descriptor desc; -    libusb_get_device_descriptor(dev, &desc); - -    if (serial.compare(get_serial(dev))) -        return false; -    if (vendor_id != desc.idVendor) -        return false; -    if (product_id != desc.idProduct) -        return false; -    if (device_addr != libusb_get_device_address(dev)) -        return false; - -    return true; -} - -bool libusb_zero_copy_impl::open_interface(libusb_device_handle *dev_handle, -                                           int interface) -{ -    int ret = libusb_claim_interface(dev_handle, interface); -    if (ret < 0) { -        std::cerr << "error: libusb_claim_interface() " << ret << std::endl; -        return false; -    } -    else { -        return true; -    } -} - -std::string libusb_zero_copy_impl::get_serial(libusb_device *dev) -{ -    unsigned char buff[32]; - -    libusb_device_descriptor desc; -    if (libusb_get_device_descriptor(dev, &desc) < 0) { -        std::cerr << "error: libusb_get_device_descriptor()" << std::endl; -        return ""; -    } - -    if (desc.iSerialNumber == 0) -        return ""; - -    //open the device because we have to -    libusb_device_handle *dev_handle; -    if (libusb_open(dev, &dev_handle) < 0) { -        return ""; -    } - -    if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, -                                           buff, sizeof(buff)) < 0) { -        std::cerr << "error: libusb_get_string_descriptor_ascii()" << std::endl; -        return ""; -    } - -    libusb_close(dev_handle); - -    return (char*) buff; -} - -  managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff()  {      libusb_transfer *lut = _rx_ep->get_completed_transfer(); @@ -836,14 +713,14 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff()  /***********************************************************************   * USB zero_copy make functions   **********************************************************************/ -usb_zero_copy::sptr usb_zero_copy::make(uhd::usb_descriptor_t descriptor, +usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle,                                          unsigned int rx_endpoint,                                          unsigned int tx_endpoint,                                          size_t buff_size,                                          size_t block_size)  { -    return sptr(new libusb_zero_copy_impl(descriptor, +    return sptr(new libusb_zero_copy_impl(handle,                                            rx_endpoint,                                            tx_endpoint,                                            buff_size,  diff --git a/host/lib/usrp/usrp1/clock_ctrl.cpp b/host/lib/usrp/usrp1/clock_ctrl.cpp index c83ad4c68..54f7b0b98 100644 --- a/host/lib/usrp/usrp1/clock_ctrl.cpp +++ b/host/lib/usrp/usrp1/clock_ctrl.cpp @@ -64,7 +64,7 @@ public:              rates.push_back(master_clock_rate / div);          return rates;  #else -        return std::vector<double>(1, 64e6); +        return std::vector<double>(1, master_clock_rate);  #endif      } diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 01617de94..6751b9b7e 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -17,6 +17,7 @@  #include "codec_ctrl.hpp"  #include "usrp_commands.h" +#include "clock_ctrl.hpp"  #include "ad9862_regs.hpp"  #include <uhd/types/dict.hpp>  #include <uhd/utils/assert.hpp> @@ -43,7 +44,9 @@ const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1);  class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl {  public:      //structors -    usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave); +    usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, +                          usrp1_clock_ctrl::sptr clock, +                          int spi_slave);      ~usrp1_codec_ctrl_impl(void);      //aux adc and dac control @@ -51,7 +54,7 @@ public:      void write_aux_dac(aux_dac_t which, float volts);      //duc control -    bool set_duc_freq(double freq); +    void set_duc_freq(double freq);      //pga gain control      void set_tx_pga_gain(float); @@ -61,25 +64,26 @@ public:  private:      usrp1_iface::sptr _iface; +    usrp1_clock_ctrl::sptr _clock_ctrl;      int _spi_slave;      ad9862_regs_t _ad9862_regs;      aux_adc_t _last_aux_adc_a, _last_aux_adc_b;      void send_reg(boost::uint8_t addr);      void recv_reg(boost::uint8_t addr); -    //FIXME: poison -    double _tx_freq[4]; -    unsigned int compute_freq_control_word_9862 (double master_freq, -                                                 double target_freq, -                                                 double *actual_freq); +    double coarse_tune(double codec_rate, double freq); +    double fine_tune(double codec_rate, double freq);  };  /***********************************************************************   * Codec Control Structors   **********************************************************************/ -usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, +                                             usrp1_clock_ctrl::sptr clock, +                                             int spi_slave)  {      _iface = iface; +    _clock_ctrl = clock;      _spi_slave = spi_slave;      //soft reset @@ -96,15 +100,15 @@ usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_sl      _ad9862_regs.byp_buffer_b = 1;      _ad9862_regs.buffer_a_pd = 1;      _ad9862_regs.buffer_b_pd = 1; -    _ad9862_regs.rx_pga_a = 0;//0x1f;  //TODO bring under api control -    _ad9862_regs.rx_pga_b = 0;//0x1f;  //TODO bring under api control +    _ad9862_regs.rx_pga_a = 0; +    _ad9862_regs.rx_pga_b = 0;      _ad9862_regs.rx_twos_comp = 1;      _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS;      //setup tx side of codec      _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH;      _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; -    _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control +    _ad9862_regs.tx_pga_gain = 199;      _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS;      _ad9862_regs.interp = ad9862_regs_t::INTERP_4;      _ad9862_regs.tx_twos_comp = 1; @@ -152,8 +156,8 @@ usrp1_codec_ctrl_impl::~usrp1_codec_ctrl_impl(void)   **********************************************************************/  void usrp1_codec_ctrl_impl::set_tx_pga_gain(float gain)  { -    int gain_word = int(63*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); -    _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 63); +    int gain_word = int(255*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); +    _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 255);      this->send_reg(16);  } @@ -324,118 +328,102 @@ void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr)  /***********************************************************************   * DUC tuning    **********************************************************************/ -unsigned int usrp1_codec_ctrl_impl::compute_freq_control_word_9862( -                    double master_freq, double target_freq, double *actual_freq) +double usrp1_codec_ctrl_impl::coarse_tune(double codec_rate, double freq)  { -    double sign = 1.0; -  -    if (target_freq < 0) -        sign = -1.0; -  -    int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0)); -    *actual_freq = v * master_freq / pow (2.0, 24.0) * sign; -  -    std::cout << boost::format( -       "compute_freq_control_word_9862: target = %g  actual = %g  delta = %g  v = %8d\n" -    ) % target_freq % *actual_freq % (*actual_freq - target_freq) % v; -  -    return (unsigned int) v; -} +    double coarse_freq; -bool usrp1_codec_ctrl_impl::set_duc_freq(double freq) -{ -    int channel = 0; -    float dac_rate = 128e6; -  -    double coarse; - -    std::cout << "duc_freq: " << freq << std::endl; - -    // First coarse frequency -    double coarse_freq_1 = dac_rate / 8; -    // Second coarse frequency -    double coarse_freq_2 = dac_rate / 4; -    // Midpoint of [0 , freq1] range +    double coarse_freq_1 = codec_rate / 8; +    double coarse_freq_2 = codec_rate / 4;      double coarse_limit_1 = coarse_freq_1 / 2; -    // Midpoint of [freq1 , freq2] range      double coarse_limit_2 = (coarse_freq_1 + coarse_freq_2) / 2; -    // Highest meaningful frequency -    double high_limit = (double) 44e6 / 128e6 * dac_rate; +    double max_freq = coarse_freq_2 + .09375 * codec_rate; -    if (freq < -high_limit) {              // too low +    if (freq < -max_freq) {          return false;      } -    else if (freq < -coarse_limit_2) {     // For 64MHz: [-44, -24) +    else if (freq < -coarse_limit_2) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; -        coarse = -coarse_freq_2; +        coarse_freq = -coarse_freq_2;      } -    else if (freq < -coarse_limit_1) {     // For 64MHz: [-24, -8) +    else if (freq < -coarse_limit_1) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; -        coarse = -coarse_freq_1; +        coarse_freq = -coarse_freq_1;      } -    else if (freq < coarse_limit_1) {      // For 64MHz: [-8, 8) +    else if (freq < coarse_limit_1) {          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; -        coarse = 0;  +        coarse_freq = 0;       } -    else if (freq < coarse_limit_2) {      // For 64MHz: [8, 24) +    else if (freq < coarse_limit_2) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; -        coarse = coarse_freq_1; +        coarse_freq = coarse_freq_1;      } -    else if (freq <= high_limit) {         // For 64MHz: [24, 44] +    else if (freq <= max_freq) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; -        coarse = coarse_freq_2; +        coarse_freq = coarse_freq_2;      } -    else {                                 // too high -        return false; +    else { +        return 0;       } -  -    double fine = freq - coarse; -  -    // Compute fine tuning word... -    // This assumes we're running the 4x on-chip interpolator. -    // (This is required to use the fine modulator.) -  -    unsigned int v = compute_freq_control_word_9862 (dac_rate / 4, fine, -                                                     &_tx_freq[channel]); - -    _tx_freq[channel] += coarse;         // adjust actual -     -    boost::uint8_t high; -    boost::uint8_t mid; -    boost::uint8_t low; -  -    high = (v >> 16) & 0xff; -    mid  = (v >>  8) & 0xff; -    low  = (v >>  0) & 0xff; -  -    // write the fine tuning word -    _ad9862_regs.ftw_23_16 = high; -    _ad9862_regs.ftw_15_8 = mid; -    _ad9862_regs.ftw_7_0 = low; -  -    _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; -  -    if (fine < 0) + +    return coarse_freq; +} + +double usrp1_codec_ctrl_impl::fine_tune(double codec_rate, double target_freq) +{ +    static const double scale_factor = std::pow(2.0, 24); + +    boost::uint32_t freq_word = boost::uint32_t( +        boost::math::round(abs((target_freq / codec_rate) * scale_factor))); + +    double actual_freq = freq_word * codec_rate / scale_factor; + +    if (target_freq < 0) {          _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_NEG_SHIFT; -    else +        actual_freq = -actual_freq;  +    } +    else {          _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_POS_SHIFT; -  +    }  + +    _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; +    _ad9862_regs.ftw_23_16 = (freq_word >> 16) & 0xff; +    _ad9862_regs.ftw_15_8  = (freq_word >>  8) & 0xff; +    _ad9862_regs.ftw_7_0   = (freq_word >>  0) & 0xff; + +    return actual_freq; +} + +void usrp1_codec_ctrl_impl::set_duc_freq(double freq) +{ +    double codec_rate = _clock_ctrl->get_master_clock_freq() * 2; +    double coarse_freq = coarse_tune(codec_rate, freq); +    double fine_freq = fine_tune(codec_rate / 4, freq - coarse_freq); + +    if (codec_debug) { +        std::cout << "ad9862 tuning result:" << std::endl; +        std::cout << "   requested:   " << freq << std::endl; +        std::cout << "   actual:      " << coarse_freq + fine_freq << std::endl; +        std::cout << "   coarse freq: " << coarse_freq << std::endl; +        std::cout << "   fine freq:   " << fine_freq << std::endl; +        std::cout << "   codec rate:  " << codec_rate << std::endl; +    }     +      this->send_reg(20);      this->send_reg(21);      this->send_reg(22);      this->send_reg(23); -  -    return true;   }  /***********************************************************************   * Codec Control Make   **********************************************************************/ -usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, +                                              usrp1_clock_ctrl::sptr clock, +                                              int spi_slave)  { -    return sptr(new usrp1_codec_ctrl_impl(iface, spi_slave)); +    return sptr(new usrp1_codec_ctrl_impl(iface, clock, spi_slave));  } diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 6440f97d1..259d10ef4 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -19,6 +19,7 @@  #define INCLUDED_USRP1_CODEC_CTRL_HPP  #include "usrp1_iface.hpp" +#include "clock_ctrl.hpp"  #include <uhd/types/ranges.hpp>  #include <boost/shared_ptr.hpp>  #include <boost/utility.hpp> @@ -41,7 +42,9 @@ public:       * \param spi_slave which spi device       * \return the clock control object       */ -    static sptr make(usrp1_iface::sptr iface, int spi_slave); +    static sptr make(usrp1_iface::sptr iface, +        usrp1_clock_ctrl::sptr clock, int spi_slave +    );      //! aux adc identifier constants      enum aux_adc_t{ @@ -87,7 +90,8 @@ public:      //! Get the RX PGA gain ('A' or 'B')      virtual float get_rx_pga_gain(char which) = 0; -    virtual bool set_duc_freq(double freq) = 0; +    //! Set the TX modulator frequency +    virtual void set_duc_freq(double freq) = 0;  };  #endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 0db3cb473..ddd1e811b 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -73,31 +73,13 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val)  /***********************************************************************   * RX DDC Set   **********************************************************************/ -unsigned int compute_freq_word(double master, double target) -{ -    static const int NBITS = 14; -    int   v = (int) rint (target / master * pow(2.0, 32.0)); -  -    if (0) -      v = (v >> (32 - NBITS)) << (32 - NBITS);    // keep only top NBITS -  -    double actual_freq = v * master / pow(2.0, 32.0); -  -    if (0) std::cerr << boost::format( -        "compute_freq_control_word_fpga: target = %g  actual = %g  delta = %g\n" -    ) % target % actual_freq % (actual_freq - target); -  -    return (unsigned int) v; -} -  void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val)  {      switch(key.as<dsp_prop_t>()) {      case DSP_PROP_FREQ_SHIFT: {              double new_freq = val.as<double>(); -            boost::uint32_t hw_freq_word = compute_freq_word( -                              _clock_ctrl->get_master_clock_freq(), new_freq); -            _iface->poke32(FR_RX_FREQ_0, hw_freq_word); +            _iface->poke32(FR_RX_FREQ_0, +                -dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_master_clock_freq()));              _tx_dsp_freq = new_freq;              return;          } @@ -113,6 +95,8 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val)              }              _rx_dsp_decim = rate; +            _rx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() / rate; +              _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1);          }          return; @@ -173,15 +157,15 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val)  {      switch(key.as<dsp_prop_t>()) { +    // TODO: Set both codec frequencies until we have duality properties       case DSP_PROP_FREQ_SHIFT: {              double new_freq = val.as<double>();              _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); +            _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq);              _tx_dsp_freq = new_freq;              return;          } -    //TODO freq prop secondary: DBOARD_SLOT_B codec... -      case DSP_PROP_HOST_RATE: {              unsigned int rate =                      _clock_ctrl->get_master_clock_freq() * 2 / val.as<double>(); @@ -193,6 +177,8 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val)              }              _tx_dsp_interp = rate; +            _tx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate; +              _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1);              return;          } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 3f3e74b80..5e206b3d5 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,37 +33,67 @@ using namespace uhd::usrp;  using namespace uhd::transport;  namespace asio = boost::asio; -/* - * The FX2 firmware bursts data to the FPGA in 512 byte chunks so - * maintain send state to make sure that happens. - */  struct usrp1_send_state {      uhd::transport::managed_send_buffer::sptr send_buff; -    size_t bytes_used; -    size_t bytes_free; +    size_t bytes_written; +    size_t underrun_poll_samp_count; + +    size_t bytes_free() +    { +        if (send_buff != NULL) +            return send_buff->size() - bytes_written; +        else +            return 0; +    } +}; + +struct usrp1_recv_state { +    uhd::transport::managed_recv_buffer::sptr recv_buff; +    size_t bytes_read; +    size_t overrun_poll_samp_count; + +    size_t bytes_avail() +    { +        if (recv_buff != NULL) +            return recv_buff->size() - bytes_read; +        else +            return 0; +    }  };  /***********************************************************************   * IO Implementation Details   **********************************************************************/  struct usrp1_impl::io_impl { -    io_impl(zero_copy_if::sptr zc_if); +    io_impl();      ~io_impl(void); -    bool get_recv_buff(managed_recv_buffer::sptr buff);  - -    //state management for the vrt packet handler code -    vrt_packet_handler::recv_state packet_handler_recv_state; +    //state handling for buffer management  +    usrp1_recv_state recv_state;      usrp1_send_state send_state; -    zero_copy_if::sptr data_transport; -    unsigned int count; +    //send transport management  +    bool get_send_buffer(zero_copy_if::sptr zc_if); +    size_t copy_convert_send_samps(const void *buff, size_t num_samps, +                              size_t sample_offset, const io_type_t io_type, +                              otw_type_t otw_type); +    bool conditional_buff_commit(bool force); +    bool check_underrun(usrp_ctrl::sptr ctrl_if, +                        size_t poll_interval, bool force); + +    //recv transport management  +    bool get_recv_buffer(zero_copy_if::sptr zc_if); +    size_t copy_convert_recv_samps(void *buff, size_t num_samps, +                              size_t sample_offset, const io_type_t io_type, +                              otw_type_t otw_type); +    bool check_overrun(usrp_ctrl::sptr ctrl_if, +                        size_t poll_interval, bool force);  }; -usrp1_impl::io_impl::io_impl(zero_copy_if::sptr zc_if) - : packet_handler_recv_state(1), data_transport(zc_if), count(0) +usrp1_impl::io_impl::io_impl()  { -    /* NOP */ +    send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); +    recv_state.recv_buff = uhd::transport::managed_recv_buffer::sptr();  }  usrp1_impl::io_impl::~io_impl(void) @@ -81,12 +111,92 @@ void usrp1_impl::io_init(void)      _tx_otw_type.shift = 0;      _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; -    _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); +    _io_impl = UHD_PIMPL_MAKE(io_impl, ());  }  /***********************************************************************   * Data Send   **********************************************************************/ +bool usrp1_impl::io_impl::get_send_buffer(zero_copy_if::sptr zc_if) +{ +    if (send_state.send_buff == NULL) { + +        send_state.send_buff = zc_if->get_send_buff(); +        if (send_state.send_buff == NULL) +            return false; + +        send_state.bytes_written = 0; +    } + +    return true; +} + +size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff, +                                                    size_t num_samps, +                                                    size_t sample_offset, +                                                    const io_type_t io_type, +                                                    otw_type_t otw_type) +{ +    UHD_ASSERT_THROW(send_state.bytes_free() % otw_type.get_sample_size() == 0); + +    size_t samps_free = send_state.bytes_free() / otw_type.get_sample_size(); +    size_t copy_samps = std::min(num_samps - sample_offset, samps_free);  + +    const boost::uint8_t *io_mem = +        reinterpret_cast<const boost::uint8_t *>(buff); + +    boost::uint8_t *otw_mem = send_state.send_buff->cast<boost::uint8_t *>(); + +    convert_io_type_to_otw_type(io_mem + sample_offset * io_type.size, +                                io_type, +                                otw_mem + send_state.bytes_written, +                                otw_type, +                                copy_samps); + +    send_state.bytes_written += copy_samps * otw_type.get_sample_size(); +    send_state.underrun_poll_samp_count += copy_samps; + +    return copy_samps; +} + +bool usrp1_impl::io_impl::conditional_buff_commit(bool force) +{ +    if (send_state.bytes_written % 512) +        return false; + +    if (force || send_state.bytes_free() == 0) { +        send_state.send_buff->commit(send_state.bytes_written); +        send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); +        return true; +    } +     +    return false; +} + +bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if, +                                         size_t poll_interval, +                                         bool force) +{ +    unsigned char underrun = 0; + +    bool ready_to_poll = send_state.underrun_poll_samp_count > poll_interval; + +    if (force || ready_to_poll) { +        int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, +                                             0, +                                             GS_TX_UNDERRUN, +                                             &underrun, sizeof(char)); +        if (ret < 0) +            std::cerr << "USRP: underrun check failed" << std::endl; +        if (underrun) +            std::cerr << "U" << std::endl; + +        send_state.underrun_poll_samp_count = 0; +    } + +    return (bool) underrun; +} +  size_t usrp1_impl::send(const std::vector<const void *> &buffs,                          size_t num_samps,                          const tx_metadata_t &, @@ -98,54 +208,21 @@ size_t usrp1_impl::send(const std::vector<const void *> &buffs,      size_t total_samps_sent = 0;      while (total_samps_sent < num_samps) { - -        if (_io_impl->send_state.send_buff == NULL) { -            _io_impl->send_state.send_buff = _data_transport->get_send_buff(); -            if (_io_impl->send_state.send_buff == NULL) { -                return 0; -            } -            _io_impl->send_state.bytes_used = 0; -            _io_impl->send_state.bytes_free = _io_impl->send_state.send_buff->size(); -        } - -        size_t copy_samps = -               std::min(num_samps - total_samps_sent, _io_impl->send_state.bytes_free / _tx_otw_type.get_sample_size()); - -        const boost::uint8_t *io_mem = -                             reinterpret_cast<const boost::uint8_t *>(buffs[0]); - -        boost::uint8_t *otw_mem = _io_impl->send_state.send_buff->cast<boost::uint8_t *>(); - -        // Type conversion and copy  -        convert_io_type_to_otw_type( -                     io_mem + total_samps_sent * io_type.size, -                     io_type, -                     otw_mem + _io_impl->send_state.bytes_used, -                     _tx_otw_type, -                     copy_samps); -  -        _io_impl->send_state.bytes_used += copy_samps * _tx_otw_type.get_sample_size(); -        _io_impl->send_state.bytes_free -= copy_samps * _tx_otw_type.get_sample_size(); - -        if (_io_impl->send_state.bytes_free == 0) { -            _io_impl->send_state.send_buff->commit(_io_impl->send_state.bytes_used); -            _io_impl->send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); -        } - -        total_samps_sent += copy_samps;  -  -        //check for underruns -        if (!(_io_impl->count++ % 1000)) { -            unsigned char underrun; -            int ret = _ctrl_transport->usrp_control_read(VRQ_GET_STATUS, -                                                         0, -                                                         GS_TX_UNDERRUN, -                                                         &underrun, sizeof(char)); -            if (ret < 0) -                std::cerr << "error: underrun check failed" << std::endl; -            if (underrun) -                std::cerr << "U" << std::endl; -        } +        if (!_io_impl->get_send_buffer(_data_transport)) +            return 0; + +        total_samps_sent += _io_impl->copy_convert_send_samps(buffs[0], +                                                              num_samps, +                                                              total_samps_sent, +                                                              io_type, +                                                              _tx_otw_type); +        if (total_samps_sent == num_samps) +            _io_impl->conditional_buff_commit(true); +        else +            _io_impl->conditional_buff_commit(false); + +        _io_impl->check_underrun(_ctrl_transport, +                                 _tx_samps_per_poll_interval, false);      }      return total_samps_sent; @@ -154,17 +231,70 @@ size_t usrp1_impl::send(const std::vector<const void *> &buffs,  /***********************************************************************   * Data Recv   **********************************************************************/ -void _recv_helper(vrt_packet_handler::recv_state &state) +bool usrp1_impl::io_impl::get_recv_buffer(zero_copy_if::sptr zc_if)  { -    size_t num_packet_words32 = -                       state.managed_buffs[0]->size() / sizeof(boost::uint32_t); +    if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail() == 0)) { -    const boost::uint32_t *data = -                        state.managed_buffs[0]->cast<const boost::uint32_t *>(); +        recv_state.recv_buff = zc_if->get_recv_buff(); +        if (recv_state.recv_buff == NULL) +            return false; + +        recv_state.bytes_read = 0; +    } -    state.copy_buffs[0] = reinterpret_cast<const boost::uint8_t *>(data); -    size_t num_payload_bytes = num_packet_words32 * sizeof(boost::uint32_t); -    state.size_of_copy_buffs = num_payload_bytes; +    return true; +} + +size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff, +                                                    size_t num_samps, +                                                    size_t sample_offset, +                                                    const io_type_t io_type, +                                                    otw_type_t otw_type) +{ +    UHD_ASSERT_THROW(recv_state.bytes_avail() % otw_type.get_sample_size() == 0); + +    size_t samps_avail = recv_state.bytes_avail() / otw_type.get_sample_size(); +    size_t copy_samps = std::min(num_samps - sample_offset, samps_avail);  + +    const boost::uint8_t *otw_mem = +        recv_state.recv_buff->cast<const boost::uint8_t *>(); + +    boost::uint8_t *io_mem = reinterpret_cast<boost::uint8_t *>(buff); + +    convert_otw_type_to_io_type(otw_mem + recv_state.bytes_read, +                                otw_type, +                                io_mem + sample_offset * io_type.size, +                                io_type, +                                copy_samps); + +    recv_state.bytes_read += copy_samps * otw_type.get_sample_size(); +    recv_state.overrun_poll_samp_count += copy_samps; + +    return copy_samps; +} + +bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if, +                                        size_t poll_interval, +                                        bool force) +{ +    unsigned char overrun = 0; + +    bool ready_to_poll = recv_state.overrun_poll_samp_count > poll_interval; + +    if (force || ready_to_poll) { +        int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, +                                             0, +                                             GS_RX_OVERRUN, +                                             &overrun, sizeof(char)); +        if (ret < 0) +            std::cerr << "USRP: overrrun check failed" << std::endl; +        if (overrun) +            std::cerr << "O" << std::endl; + +        recv_state.overrun_poll_samp_count = 0; +    } + +    return (bool) overrun;  }  size_t usrp1_impl::recv(const std::vector<void *> &buffs, @@ -174,56 +304,23 @@ size_t usrp1_impl::recv(const std::vector<void *> &buffs,                          recv_mode_t,                          size_t)  { -    UHD_ASSERT_THROW(_io_impl->packet_handler_recv_state.width == 1);      UHD_ASSERT_THROW(buffs.size() == 1); -    size_t sent_samps = 0; -    size_t nsamps_to_copy = 0;;  - -    while (sent_samps < num_samps) { -        if (_io_impl->packet_handler_recv_state.size_of_copy_buffs == 0) { -            _io_impl->packet_handler_recv_state.fragment_offset_in_samps = 0; -            _io_impl->packet_handler_recv_state.managed_buffs[0] = -                                          _io_impl->data_transport->get_recv_buff(); -  -            //timeout or something bad returns zero -            if (!_io_impl->packet_handler_recv_state.managed_buffs[0].get()) -                return 0; -  -            _recv_helper(_io_impl->packet_handler_recv_state); -        } - -        size_t bytes_per_item = _rx_otw_type.get_sample_size(); -        size_t nsamps_available = -            _io_impl->packet_handler_recv_state.size_of_copy_buffs / bytes_per_item; -        nsamps_to_copy = std::min(num_samps, nsamps_available); -        size_t bytes_to_copy = nsamps_to_copy * bytes_per_item; - -        convert_otw_type_to_io_type( -              _io_impl->packet_handler_recv_state.copy_buffs[0], -              _rx_otw_type, -              reinterpret_cast<boost::uint8_t *>(buffs[0]) + sent_samps * io_type.size, -              io_type, -              nsamps_to_copy); -  -        _io_impl->packet_handler_recv_state.copy_buffs[0] += bytes_to_copy;  -        _io_impl->packet_handler_recv_state.size_of_copy_buffs -= bytes_to_copy; - -        sent_samps += nsamps_to_copy; - -        //check for overruns -        if (!(_io_impl->count++ % 10000)) { -            unsigned char overrun; -            int ret = _ctrl_transport->usrp_control_read( -                                   VRQ_GET_STATUS, -                                   0, -                                   GS_RX_OVERRUN, -                                   &overrun, sizeof(char)); -            if (ret < 0) -                std::cerr << "error: overrun check failed" << std::endl; -            if (overrun) -                std::cerr << "O" << std::endl; -        } +    size_t total_samps_recv = 0; + +    while (total_samps_recv < num_samps) { + +        if (!_io_impl->get_recv_buffer(_data_transport)) +            return 0; + +        total_samps_recv += _io_impl->copy_convert_recv_samps(buffs[0], +                                                              num_samps, +                                                              total_samps_recv, +                                                              io_type, +                                                              _rx_otw_type); +        _io_impl->check_overrun(_ctrl_transport, +                                _rx_samps_per_poll_interval, false);      } -    return sent_samps;  + +    return total_samps_recv;   } diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index c3343f1f8..74ec514ff 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -114,7 +114,7 @@ static boost::uint32_t calc_tx_mux(      //calculate the channel flags      int channel_flags = 0, chan = 0;      BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){ -        wax::obj dboard = mboard[named_prop_t(MBOARD_PROP_RX_DBOARD, pair.db_name)]; +        wax::obj dboard = mboard[named_prop_t(MBOARD_PROP_TX_DBOARD, pair.db_name)];          wax::obj subdev = dboard[named_prop_t(DBOARD_PROP_SUBDEV, pair.sd_name)];          subdev_conn_t conn = subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>(); @@ -298,7 +298,7 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)      case MBOARD_PROP_RX_SUBDEV_SPEC:          _rx_subdev_spec = val.as<subdev_spec_t>(); -        verify_rx_subdev_spec(_rx_subdev_spec, this->get_link()); +        verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link());          //sanity check          UHD_ASSERT_THROW(_rx_subdev_spec.size() <= 2);          //set the mux and set the number of rx channels @@ -307,7 +307,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>(); -        verify_tx_subdev_spec(_tx_subdev_spec, this->get_link()); +        verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link());          //sanity check          UHD_ASSERT_THROW(_tx_subdev_spec.size() <= 2);          //set the mux and set the number of tx channels diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index b175ba21f..9d326d6bd 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -53,7 +53,8 @@ public:          if (iface_debug) {              std::cout.fill('0'); -            std::cout << "poke32(" << std::dec << addr << ", 0x"; +            std::cout << "poke32("; +            std::cout << std::dec << std::setw(2) << addr << ", 0x";              std::cout << std::hex << std::setw(8) << value << ")" << std::endl;          } @@ -129,11 +130,7 @@ public:      {          UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes); -        byte_vector_t out_bytes; -        byte_vector_t::iterator it = out_bytes.begin(); -          unsigned char buff[max_i2c_data_bytes]; -          int ret = _ctrl_transport->usrp_control_read(VRQ_I2C_READ,                                                       addr & 0xff,                                                       0, @@ -142,9 +139,10 @@ public:          if ((ret < 0) || (unsigned)ret < (num_bytes)) {              std::cerr << "USRP: failed i2c read: " << ret << std::endl; -            return out_bytes; +            return byte_vector_t(num_bytes, 0xff);           } +        byte_vector_t out_bytes;          for (size_t i = 0; i < num_bytes; i++)              out_bytes.push_back(buff[i]); @@ -168,7 +166,7 @@ public:                                   size_t num_bits,                                   bool readback)      { -        UHD_ASSERT_THROW((num_bits < 32) && !(num_bits % 8)); +        UHD_ASSERT_THROW((num_bits <= 32) && !(num_bits % 8));          size_t num_bytes = num_bits / 8;          // Byteswap on num_bytes diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 33a069bc6..a15d0a244 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -55,13 +55,15 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)      std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl;      //see what we got on the USB bus -    usb_descriptors_t usb_descriptors; -    usb_descriptors = usb_control::get_device_list(); +    std::vector<usb_device_handle::sptr> device_list = +        usb_device_handle::get_device_list();      //find the usrps and load firmware -    BOOST_FOREACH(usb_descriptor_t desc, usb_descriptors) { -        if (desc.vendor_id == 0xfffe && desc.product_id == 0x0002) { -            usb_control::sptr ctrl_transport = usb_control::make(desc); +    BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { +        if (handle->get_vendor_id() == 0xfffe && +            handle->get_product_id() == 0x0002) { + +            usb_control::sptr ctrl_transport = usb_control::make(handle);              usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport);              usrp_ctrl->usrp_load_firmware(usrp1_fw_image);          } @@ -71,13 +73,15 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)      boost::this_thread::sleep(boost::posix_time::milliseconds(500));      //get descriptors again with serial number -    usb_descriptors = usb_control::get_device_list(); +    device_list = usb_device_handle::get_device_list(); + +    BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { +        if (handle->get_vendor_id() == 0xfffe && +            handle->get_product_id() == 0x0002) { -    BOOST_FOREACH(usb_descriptor_t desc, usb_descriptors) { -        if (desc.vendor_id == 0xfffe && desc.product_id == 0x0002) {              device_addr_t new_addr;              new_addr["type"] = "usrp1"; -            new_addr["serial"] = desc.serial; +            new_addr["serial"] = handle->get_serial();              usrp1_addrs.push_back(new_addr);          }      } @@ -97,22 +101,23 @@ static device::sptr usrp1_make(const device_addr_t &device_addr)      std::cout << "USRP1 FPGA image: " << usrp1_fpga_image << std::endl;      //try to match the given device address with something on the USB bus -    usb_descriptors_t usb_descriptors; -    usb_descriptors = usb_control::get_device_list(); +    std::vector<usb_device_handle::sptr> device_list = +        usb_device_handle::get_device_list();      //create data and control transports      usb_zero_copy::sptr data_transport;      usrp_ctrl::sptr usrp_ctrl; -    BOOST_FOREACH(usb_descriptor_t desc, usb_descriptors) { -        if (desc.serial == device_addr["serial"] -            && desc.vendor_id == 0xfffe && desc.product_id == 0x0002) { +    BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { +        if (handle->get_vendor_id() == 0xfffe && +            handle->get_product_id() == 0x0002 && +            handle->get_serial() == device_addr["serial"]) { -            usb_control::sptr ctrl_transport = usb_control::make(desc); +            usb_control::sptr ctrl_transport = usb_control::make(handle);              usrp_ctrl = usrp_ctrl::make(ctrl_transport);              usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); -            data_transport = usb_zero_copy::make(desc,          // identifier +            data_transport = usb_zero_copy::make(handle,        // identifier                                                   6,             // IN endpoint                                                   2,             // OUT endpoint                                                   2 * (1 << 20), // buffer size @@ -142,8 +147,12 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport,      _clock_ctrl = usrp1_clock_ctrl::make(_iface);      //create codec interface -    _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_A); -    _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_B); +    _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make( +        _iface, _clock_ctrl, SPI_ENABLE_CODEC_A +    ); +    _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make( +        _iface, _clock_ctrl, SPI_ENABLE_CODEC_B +    );      //initialize the codecs      codec_init(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index cbd3d5315..4b4ac51dd 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -120,6 +120,10 @@ private:      void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd);      void handle_overrun(size_t); +    //underrun and overrun poll intervals +    size_t _rx_samps_per_poll_interval; +    size_t _tx_samps_per_poll_interval;  +      //otw types      uhd::otw_type_t _rx_otw_type;      uhd::otw_type_t _tx_otw_type; | 
