diff options
| author | Ashish Chaudhari <ashish@ettus.com> | 2015-04-30 18:02:02 -0700 | 
|---|---|---|
| committer | Ashish Chaudhari <ashish@ettus.com> | 2015-04-30 18:02:02 -0700 | 
| commit | f2337d6fe0cca7337e0678d8f3ee31f657b608f2 (patch) | |
| tree | 98c71da44375cc7c4a299e7ff1f2f70147526e8e | |
| parent | a7150e25f1ec5802963f44c5f748b211c6fcae8f (diff) | |
| parent | c6d0daaf034f3c1f20b8a0e6cd5c2555879760e2 (diff) | |
| download | uhd-f2337d6fe0cca7337e0678d8f3ee31f657b608f2.tar.gz uhd-f2337d6fe0cca7337e0678d8f3ee31f657b608f2.tar.bz2 uhd-f2337d6fe0cca7337e0678d8f3ee31f657b608f2.zip  | |
Merge branch 'master' into vivado
| -rw-r--r-- | firmware/fx3/README.md | 10 | ||||
| -rw-r--r-- | firmware/fx3/b200/b200_main.c | 35 | ||||
| -rw-r--r-- | firmware/fx3/b200/b200_main.h | 4 | ||||
| -rw-r--r-- | firmware/fx3/b200/b200_usb_descriptors.c | 84 | ||||
| m--------- | fpga-src | 0 | ||||
| -rw-r--r-- | host/CMakeLists.txt | 19 | ||||
| -rw-r--r-- | host/docs/CMakeLists.txt | 24 | ||||
| -rw-r--r-- | host/docs/Doxyfile.in | 6 | ||||
| -rw-r--r-- | host/docs/mainpage.dox.in (renamed from host/docs/mainpage.dox) | 1 | ||||
| -rw-r--r-- | host/include/uhd/utils/paths.hpp | 2 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_base.cpp | 1 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_iface.hpp | 44 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 138 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_impl.hpp | 16 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_io_impl.cpp | 57 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_ubx.cpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 3 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 25 | ||||
| -rw-r--r-- | host/lib/utils/paths.cpp | 6 | ||||
| -rw-r--r-- | host/utils/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | host/utils/uhd_usrp_probe.cpp | 21 | ||||
| -rw-r--r-- | host/utils/usrp_x3xx_fpga_burner.cpp | 4 | 
22 files changed, 389 insertions, 115 deletions
diff --git a/firmware/fx3/README.md b/firmware/fx3/README.md index 84a895059..29d72a9ad 100644 --- a/firmware/fx3/README.md +++ b/firmware/fx3/README.md @@ -19,16 +19,16 @@ distributed by the FX3 manufacturer, Cypress Semiconductor. You can download the  [FX3 SDK from here](http://www.cypress.com/?rID=57990).  *Note*: You *must* use SDK version 1.2.3! -Once you have downloaded it, extract the ARM cross-compiler sub-directory from -the zip file and put it somewhere useful. The highest level directory you need -is `arm-2011.03/`. +Once you have downloaded it, extract the ARM cross-compiler from the tarball +`ARM_GCC.tar.gz` and put it somewhere useful. The highest level directory you +need is `arm-2013.03/`.  Now that you have extracted the cross compilation toolchain, you need to set up  some environment variables to tell the B2xx `makefile` where to look for the  tools. These variables are:  ``` -    $ export ARMGCC_INSTALL_PATH=<your path>/arm-2011.03 +    $ export ARMGCC_INSTALL_PATH=<your path>/arm-2013.03      $ export ARMGCC_VERSION=4.5.2  ``` @@ -61,7 +61,7 @@ into the `common/` directory you just copied from the Cypress SDK, and apply the  patch `b200/fx3_mem_map.patch`.  ``` -    # cd uhd.git/firmware/common/ +    # cd uhd.git/firmware/fx3/common/      $ patch -p2 < ../b200/fx3_mem_map.patch  ``` diff --git a/firmware/fx3/b200/b200_main.c b/firmware/fx3/b200/b200_main.c index 077ee251b..cb0172af3 100644 --- a/firmware/fx3/b200/b200_main.c +++ b/firmware/fx3/b200/b200_main.c @@ -2034,6 +2034,7 @@ void b200_usb_init(void) {      /* Check to see if a VID/PID is in the EEPROM that we should use. */      uint8_t valid[4]; +    uint8_t vidpid[4];      CyU3PMemSet(valid, 0, 4);      CyFxUsbI2cTransfer(0x0, 0xA0, 4, valid, CyTrue);      if(*((uint32_t *) &(valid[0])) == 0xB2145943) { @@ -2041,7 +2042,6 @@ void b200_usb_init(void) {          /* Pull the programmed device serial out of the i2c EEPROM, and copy the           * characters into the device serial string, which is then advertised as           * part of the USB descriptors. */ -        uint8_t vidpid[4];          CyU3PMemSet(vidpid, 0, 4);          CyFxUsbI2cTransfer(0x4, 0xA0, 4, vidpid, CyTrue);          b200_usb2_dev_desc[8] = vidpid[2]; @@ -2055,6 +2055,35 @@ void b200_usb_init(void) {          b200_usb3_dev_desc[11] = vidpid[1];      } +    /* We support two VIDs: +     *  Ettus Research:         0x2500 +     *  National Instruments:   0x3923 +     * +     * We support three PIDs: +     *  Ettus B200/B210:        0x0020 +     *  NI USRP-2900:           0x7813 +     *  NI USRP-2901:           0x7814 +     */ +    uint8_t *mfr_string = NULL; +    uint8_t *product_string = NULL; +    if((vidpid[3] == 0x25) && (vidpid[2] == 0x00)) { +        mfr_string = b200_usb_manufacture_desc; +        product_string = b200_usb_product_desc; +    } else if((vidpid[3] == 0x39) && (vidpid[2] == 0x23)) { +        mfr_string = niusrp_usb_manufacture_desc; + +        if((vidpid[1] == 0x78) && (vidpid[0] == 0x13)) { +            product_string = niusrp_2900_usb_product_desc; +        } else if((vidpid[1] == 0x78) && (vidpid[0] == 0x14)) { +            product_string = niusrp_2901_usb_product_desc; +        } else { +            product_string = unknown_desc; +        } +    } else { +        mfr_string = unknown_desc; +        product_string = unknown_desc; +    } +      uint8_t ascii_serial[9];      CyU3PMemSet(ascii_serial, 0, 9);      CyFxUsbI2cTransfer(0x4f7, 0xA0, 9, ascii_serial, CyTrue); @@ -2101,10 +2130,10 @@ void b200_usb_init(void) {              (uint8_t *) b200_string_lang_id_desc);      CyU3PUsbSetDesc(CY_U3P_USB_SET_STRING_DESCR, 1, -            (uint8_t *) b200_usb_manufacture_desc); +            (uint8_t *) mfr_string);      CyU3PUsbSetDesc(CY_U3P_USB_SET_STRING_DESCR, 2, -            (uint8_t *) b200_usb_product_desc); +            (uint8_t *) product_string);      CyU3PUsbSetDesc(CY_U3P_USB_SET_STRING_DESCR, 3,              (uint8_t *) dev_serial); diff --git a/firmware/fx3/b200/b200_main.h b/firmware/fx3/b200/b200_main.h index 2c6f178ec..61048abc9 100644 --- a/firmware/fx3/b200/b200_main.h +++ b/firmware/fx3/b200/b200_main.h @@ -128,6 +128,10 @@ extern const uint8_t b200_usb_ss_config_desc[];  extern const uint8_t b200_string_lang_id_desc[];  extern const uint8_t b200_usb_manufacture_desc[];  extern const uint8_t b200_usb_product_desc[]; +extern const uint8_t niusrp_usb_manufacture_desc[]; +extern const uint8_t niusrp_2900_usb_product_desc[]; +extern const uint8_t niusrp_2901_usb_product_desc[]; +extern const uint8_t unknown_desc[];  extern uint8_t dev_serial[]; diff --git a/firmware/fx3/b200/b200_usb_descriptors.c b/firmware/fx3/b200/b200_usb_descriptors.c index e8a765b24..03dbce74a 100644 --- a/firmware/fx3/b200/b200_usb_descriptors.c +++ b/firmware/fx3/b200/b200_usb_descriptors.c @@ -458,6 +458,39 @@ const uint8_t b200_usb_manufacture_desc[] __attribute__ ((aligned (32))) =          'C',0x00      }; +/* NI Manufacturer String Descriptor */ +const uint8_t niusrp_usb_manufacture_desc[] __attribute__ ((aligned (32))) = +    { +        0x36,                           /* Descriptor Size */ +        CY_U3P_USB_STRING_DESCR,        /* Device Descriptor Type */ +        'N',0x00, +        'a',0x00, +        't',0x00, +        'i',0x00, +        'o',0x00, +        'n',0x00, +        'a',0x00, +        'l',0x00, +        ' ',0x00, +        'I',0x00, +        'n',0x00, +        's',0x00, +        't',0x00, +        'r',0x00, +        'u',0x00, +        'm',0x00, +        'e',0x00, +        'n',0x00, +        't',0x00, +        's',0x00, +        ' ',0x00, +        'C',0x00, +        'o',0x00, +        'r',0x00, +        'p',0x00, +        '.',0x00 +    }; +  /* Standard Product String Descriptor */  const uint8_t b200_usb_product_desc[] __attribute__ ((aligned (32))) = @@ -475,6 +508,57 @@ const uint8_t b200_usb_product_desc[] __attribute__ ((aligned (32))) =          '0',0x00      }; +/* NI-USRP 2900 Product String Descriptor */ +const uint8_t niusrp_2900_usb_product_desc[] __attribute__ ((aligned (32))) = +    { +        0x1A,                           /* Descriptor Size */ +        CY_U3P_USB_STRING_DESCR,        /* Device Descriptor Type */ +        'N',0x00, +        'I',0x00, +        ' ',0x00, +        'U',0x00, +        'S',0x00, +        'R',0x00, +        'P',0x00, +        '-',0x00, +        '2',0x00, +        '9',0x00, +        '0',0x00, +        '0',0x00 +    }; + +/* NI-USRP 2901 Product String Descriptor */ +const uint8_t niusrp_2901_usb_product_desc[] __attribute__ ((aligned (32))) = +    { +        0x1A,                           /* Descriptor Size */ +        CY_U3P_USB_STRING_DESCR,        /* Device Descriptor Type */ +        'N',0x00, +        'I',0x00, +        ' ',0x00, +        'U',0x00, +        'S',0x00, +        'R',0x00, +        'P',0x00, +        '-',0x00, +        '2',0x00, +        '9',0x00, +        '0',0x00, +        '1',0x00 +    }; + +const uint8_t unknown_desc[] __attribute__ ((aligned (32))) = +    { +        0x10,                           /* Descriptor Size */ +        CY_U3P_USB_STRING_DESCR,        /* Device Descriptor Type */ +        'U',0x00, +        'n',0x00, +        'k',0x00, +        'n',0x00, +        'o',0x00, +        'w',0x00, +        'n',0x00 +    }; +  /* Microsoft OS Descriptor. */  const uint8_t CyFxUsbOSDscr[] __attribute__ ((aligned (32))) =  { diff --git a/fpga-src b/fpga-src -Subproject 8aca31329f2fd1612df32383bb8bea80d5b7e47 +Subproject 9b69de6dc468ae6663c10e41a6322131bca0eb9 diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 8dddb6552..75635e415 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -24,7 +24,7 @@  # Project setup  ########################################################################  CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(UHD CXX) +PROJECT(UHD CXX C)  ENABLE_TESTING()  #make sure our local CMake Modules path comes first @@ -284,8 +284,8 @@ UHD_INSTALL(FILES  #{{{IMG_SECTION  # This section is written automatically by /images/create_imgs_package.py  # Any manual changes in here will be overwritten. -SET(UHD_IMAGES_MD5SUM "37d4899e320809951149c3670fb054ee") -SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.009.git-139-g3e3e236a.zip") +SET(UHD_IMAGES_MD5SUM "4b30c563530a3339a1a1510762afe555") +SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.009.git-166-ged632e6a.zip")  #}}}  ######################################################################## @@ -297,6 +297,19 @@ LIBUHD_REGISTER_COMPONENT("Utils" ENABLE_UTILS ON "ENABLE_LIBUHD" OFF)  LIBUHD_REGISTER_COMPONENT("Tests" ENABLE_TESTS ON "ENABLE_LIBUHD" OFF)  ######################################################################## +# Check for fpga-src submodule +######################################################################## +SET(HAS_FPGA_SUBMODULE FALSE) +EXECUTE_PROCESS( +    COMMAND ${PYTHON_EXECUTABLE} -c "import os; print os.path.abspath(os.path.join('${CMAKE_SOURCE_DIR}', '..', 'fpga-src'))" +    OUTPUT_VARIABLE FPGA_SUBMODULE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE +) +message(STATUS ${FPGA_SUBMODULE_DIR}) +IF(EXISTS "${FPGA_SUBMODULE_DIR}/docs/fpga.md") +    SET(HAS_FPGA_SUBMODULE TRUE) +ENDIF(EXISTS "${FPGA_SUBMODULE_DIR}/docs/fpga.md") + +########################################################################  # Add the subdirectories  ########################################################################  ADD_SUBDIRECTORY(docs) diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index 84ed88281..eb4b67c29 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -31,12 +31,34 @@ SET(ENABLE_MANUAL_OR_DOXYGEN false)  MESSAGE(STATUS "")  LIBUHD_REGISTER_COMPONENT("Manual" ENABLE_MANUAL ON "DOXYGEN_FOUND" OFF) +# Check if fpga submodule is there. If yes: +# - Add fpga-src/docs and fpga-src/README.md to inputs +# - Add fpga-src docs dirs to strip? +# If no: +# - Make FPGA Manual reference link to our website +  IF(ENABLE_MANUAL)      SET(ENABLE_MANUAL_OR_DOXYGEN true) +    # First: Set up UHD manual only      FILE(GLOB manual_sources "*.dox")      SET(DOXYGEN_DEPENDENCIES ${manual_sources}) -    SET(DOXYGEN_INPUT_DIRS ${CMAKE_SOURCE_DIR}/docs) +    SET(DOXYGEN_INPUT_DIRS "${CMAKE_SOURCE_DIR}/docs")      SET(DOXYGEN_DEP_COMPONENT "manual") +    SET(DOXYGEN_FPGA_MANUAL_REFERENCE "<a href=\"http://files.ettus.com/manual/page_fpga.html\">Part III: FPGA Manual</a>") +    SET(DOXYGEN_STRIP_EXTRA "") +    # Now, check if we have the FPGA sources as well. +    # If so, pull them in: +    IF(HAS_FPGA_SUBMODULE) +        FILE(GLOB_RECURSE fpga_manual_sources "${FPGA_SUBMODULE_DIR}/docs/*.md") +        LIST(APPEND manual_sources ${fpga_manual_sources}) +        SET(DOXYGEN_INPUT_DIRS "${DOXYGEN_INPUT_DIRS} ${FPGA_SUBMODULE_DIR}/docs") +        SET(DOXYGEN_FPGA_MANUAL_REFERENCE "\\subpage md_fpga \"Part III: FPGA Manual\"") +	SET(DOXYGEN_STRIP_EXTRA "${FPGA_SUBMODULE_DIR}/docs") +    ENDIF(HAS_FPGA_SUBMODULE) +    CONFIGURE_FILE( +        ${CMAKE_CURRENT_SOURCE_DIR}/mainpage.dox.in +        ${CMAKE_CURRENT_BINARY_DIR}/mainpage.dox +    @ONLY)  ENDIF(ENABLE_MANUAL)  ######################################################################## diff --git a/host/docs/Doxyfile.in b/host/docs/Doxyfile.in index b0490c5c0..0f0a5cc27 100644 --- a/host/docs/Doxyfile.in +++ b/host/docs/Doxyfile.in @@ -132,7 +132,7 @@ FULL_PATH_NAMES        = YES  # relative paths, which will be relative from the directory where doxygen is  # started. -STRIP_FROM_PATH        = @CMAKE_SOURCE_DIR@ +STRIP_FROM_PATH        = @CMAKE_SOURCE_DIR@ @DOXYGEN_STRIP_EXTRA@  # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of  # the path mentioned in the documentation of a class, which tells @@ -654,7 +654,7 @@ WARN_LOGFILE           =  # directories like "/usr/src/myproject". Separate the files or directories  # with spaces. -INPUT                  = @DOXYGEN_INPUT_DIRS@ +INPUT                  = @CMAKE_CURRENT_BINARY_DIR@/mainpage.dox @DOXYGEN_INPUT_DIRS@  # This tag can be used to specify the character encoding of the source files  # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -672,7 +672,7 @@ INPUT_ENCODING         = UTF-8  # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py  # *.f90 *.f *.for *.vhd *.vhdl -FILE_PATTERNS          = *.hpp *.dox *.h *.ipp +FILE_PATTERNS          = *.hpp *.dox *.h *.ipp *.md  # The RECURSIVE tag can be used to turn specify whether or not subdirectories  # should be searched for input files as well. Possible values are YES and NO. diff --git a/host/docs/mainpage.dox b/host/docs/mainpage.dox.in index a12e62c9c..428650633 100644 --- a/host/docs/mainpage.dox +++ b/host/docs/mainpage.dox.in @@ -12,6 +12,7 @@ Follow these links to get to the section of the manual you wish to consult, or u  \li \subpage page_devices "Part I: Devices & Usage Manual"  \li \subpage page_uhd "Part II: UHD Development Manual" +\li @DOXYGEN_FPGA_MANUAL_REFERENCE@  ### Further Information diff --git a/host/include/uhd/utils/paths.hpp b/host/include/uhd/utils/paths.hpp index 8edb87546..aa31fd5a2 100644 --- a/host/include/uhd/utils/paths.hpp +++ b/host/include/uhd/utils/paths.hpp @@ -87,7 +87,7 @@ namespace uhd {       * The error string will include the full path to the utility to run.       * \return the message suggesting the use of the named utility.       */ -    UHD_API std::string print_utility_error(std::string name); +    UHD_API std::string print_utility_error(const std::string &name, const std::string &args="");  } //namespace uhd  #endif /* INCLUDED_UHD_UTILS_PATHS_HPP */ diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index b1045ffa5..0baf8dc76 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -327,6 +327,7 @@ public:      bool firmware_loaded() {          return (get_manufacturer() == "Ettus Research LLC") or +               (get_manufacturer() == "National Instruments Corp.") or                 (get_manufacturer() == "Free Software Folks");      } diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 1821865d3..1d123439a 100644 --- a/host/lib/usrp/b200/b200_iface.hpp +++ b/host/lib/usrp/b200/b200_iface.hpp @@ -1,5 +1,5 @@  // -// Copyright 2012-2013 Ettus Research LLC +// Copyright 2012-2013,2015 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 @@ -21,22 +21,48 @@  #include <stdint.h>  #include <uhd/transport/usb_control.hpp>  #include <uhd/types/serial.hpp> //i2c iface +#include <uhd/types/dict.hpp> +#include <boost/assign/list_of.hpp>  #include <boost/shared_ptr.hpp>  #include <boost/utility.hpp>  #include "ad9361_ctrl.hpp" -const static boost::uint16_t B200_VENDOR_ID  = 0x2500; -const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; -const static boost::uint16_t B200_PRODUCT_ID = 0x0020; +enum b200_type_t { +    B200, +    B210 +}; + +const static boost::uint16_t B200_VENDOR_ID     = 0x2500; +const static boost::uint16_t B200_VENDOR_NI_ID  = 0x3923; +const static boost::uint16_t B200_PRODUCT_ID    = 0x0020;  const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813;  const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; -const static boost::uint16_t FX3_VID = 0x04b4; -const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; -const static boost::uint16_t FX3_REENUM_PID = 0x00f0; +const static boost::uint16_t FX3_VID            = 0x04b4; +const static boost::uint16_t FX3_DEFAULT_PID    = 0x00f3; +const static boost::uint16_t FX3_REENUM_PID     = 0x00f0;  static const std::string     B200_FW_FILE_NAME = "usrp_b200_fw.hex"; -static const std::string     B200_FPGA_FILE_NAME = "usrp_b200_fpga.bin"; -static const std::string     B210_FPGA_FILE_NAME = "usrp_b210_fpga.bin"; + +//! Map the product ID (in the EEPROM) to a device type +static const uhd::dict<boost::uint16_t, b200_type_t> B2X0_PRODUCT_ID = boost::assign::map_list_of +        (0x0001,             B200) +        (0x7737,             B200) +        (B200_PRODUCT_NI_ID, B200) +        (0x0002,             B210) +        (0x7738,             B210) +        (B210_PRODUCT_NI_ID, B210) +; + +static const uhd::dict<b200_type_t, std::string> B2X0_STR_NAMES = boost::assign::map_list_of +        (B200, "B200") +        (B210, "B210") +; + +static const uhd::dict<b200_type_t, std::string> B2X0_FPGA_FILE_NAME = boost::assign::map_list_of +        (B200, "usrp_b200_fpga.bin") +        (B210, "usrp_b210_fpga.bin") +; +  class UHD_API b200_iface: boost::noncopyable, public virtual uhd::i2c_iface {  public: diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index afc21d031..2b423afa5 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -43,10 +43,6 @@ using namespace uhd::transport;  static const boost::posix_time::milliseconds REENUMERATION_TIMEOUT_MS(3000); -//! mapping of frontend to radio perif index -static const size_t FE1 = 1; -static const size_t FE2 = 0; -  class b200_ad9361_client_t : public ad9361_params {  public:      ~b200_ad9361_client_t() {} @@ -77,6 +73,24 @@ public:  /***********************************************************************   * Discovery   **********************************************************************/ +//! Look up the type of B-Series device we're currently running. +//  If the product ID stored in mb_eeprom is invalid, throws a +//  uhd::runtime_error. +static b200_type_t get_b200_type(const mboard_eeprom_t &mb_eeprom) +{ +    if (mb_eeprom["product"].empty()) { +        throw uhd::runtime_error("B200: Missing product ID on EEPROM."); +    } +    boost::uint16_t product_id = boost::lexical_cast<boost::uint16_t>(mb_eeprom["product"]); +    if (not B2X0_PRODUCT_ID.has_key(product_id)) { +        throw uhd::runtime_error(str( +            boost::format("B200 unknown product code: 0x%04x") +            % product_id +        )); +    } +    return B2X0_PRODUCT_ID[product_id]; +} +  static device_addrs_t b200_find(const device_addr_t &hint)  {      device_addrs_t b200_addrs; @@ -155,24 +169,14 @@ static device_addrs_t b200_find(const device_addr_t &hint)              new_addr["type"] = "b200";              new_addr["name"] = mb_eeprom["name"];              new_addr["serial"] = handle->get_serial(); -            if (not mb_eeprom["product"].empty()) -            { -                switch (boost::lexical_cast<boost::uint16_t>(mb_eeprom["product"])) -                { -                //0x0001 and 0x7737 are Ettus B200 product Ids. -                case 0x0001: -                case 0x7737: -                case B200_PRODUCT_NI_ID: -                    new_addr["product"] = "B200"; -                    break; -                //0x0002 and 0x7738 are Ettus B210 product Ids. -                case 0x0002: -                case 0x7738: -                case B210_PRODUCT_NI_ID: -                    new_addr["product"] = "B210"; -                    break; -                default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; -                } +            try { +                // Turn the 16-Bit product ID into a string representation +                new_addr["product"] = B2X0_STR_NAMES[get_b200_type(mb_eeprom)]; +            } catch (const uhd::runtime_error &e) { +                // No problem if this fails -- this is just device discovery, after all. +                UHD_MSG(error) << e.what() << std::endl; +                // Skip this loop. +                continue;              }              //this is a found b200 when the hint serial and name match or blank              if ( @@ -204,6 +208,7 @@ UHD_STATIC_BLOCK(register_b200_device)   * Structors   **********************************************************************/  b200_impl::b200_impl(const device_addr_t &device_addr) : +    _revision(0),      _tick_rate(0.0) // Forces a clock initialization at startup  {      _tree = property_tree::make(); @@ -282,36 +287,55 @@ b200_impl::b200_impl(const device_addr_t &device_addr) :          .subscribe(boost::bind(&b200_impl::set_mb_eeprom, this, _1));      //////////////////////////////////////////////////////////////////// -    // Load the FPGA image, then reset GPIF +    // Identify the device type      ////////////////////////////////////////////////////////////////////      std::string default_file_name; -    std::string product_name = "B200?"; -    if (not mb_eeprom["product"].empty()) -    { -        switch (boost::lexical_cast<boost::uint16_t>(mb_eeprom["product"])) -        { -        //0x0001 and 0x7737 are Ettus B200 product Ids. -        case 0x0001: -        case 0x7737: -        case B200_PRODUCT_NI_ID: -            product_name = "B200"; -            default_file_name = B200_FPGA_FILE_NAME; -            break; -        //0x0002 and 0x7738 are Ettus B210 product Ids. -        case 0x0002: -        case 0x7738: -        case B210_PRODUCT_NI_ID: -            product_name = "B210"; -            default_file_name = B210_FPGA_FILE_NAME; -            break; -        default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; +    std::string product_name; +    try { +        // This will throw if the product ID is invalid: +        _b200_type = get_b200_type(mb_eeprom); +        default_file_name = B2X0_FPGA_FILE_NAME.get(_b200_type); +        product_name      = B2X0_STR_NAMES.get(_b200_type); +    } catch (const uhd::runtime_error &e) { +        // The only reason we may let this pass is if the user specified +        // the FPGA file name: +        if (not device_addr.has_key("fpga")) { +            throw e;          } +        // In this case, we must provide a default product name: +        product_name = "B200?"; +        _b200_type = B200;      } -    if (default_file_name.empty()) -    { -        UHD_ASSERT_THROW(device_addr.has_key("fpga")); +    if (not mb_eeprom["revision"].empty()) { +        _revision = boost::lexical_cast<size_t>(mb_eeprom["revision"]); +    } + +    //////////////////////////////////////////////////////////////////// +    // Set up frontend mapping +    //////////////////////////////////////////////////////////////////// +    // Explanation: The AD9361 has 2 frontends, FE1 and FE2. +    // On the B210 FE1 maps to the B-side (or radio 1), and FE2 maps +    // to the A-side (or radio 0). So, logically, the radios are swapped +    // between the host side and the AD9361-side. +    // B200 is more complicated: On Revs <= 4, the A-side is connected, +    // which means FE2 is used (like B210). On Revs >= 5, the left side +    // ("B-side") is connected, because these revs use an AD9364, which +    // does not have an FE2, so we don't swap FEs. + +    // Swapped setup: +    _fe1 = 1; +    _fe2 = 0; +    _gpio_state.swap_atr = 1; +    // Unswapped setup: +    if (_b200_type == B200 and _revision >= 5) { +        _fe1 = 0;                   //map radio0 to FE1 +        _fe2 = 1;                   //map radio1 to FE2 +        _gpio_state.swap_atr = 0; // ATRs for radio0 are mapped to FE1      } +    //////////////////////////////////////////////////////////////////// +    // Load the FPGA image, then reset GPIF +    ////////////////////////////////////////////////////////////////////      //extract the FPGA path for the B200      std::string b200_fpga_image = find_image_path(          device_addr.has_key("fpga")? device_addr["fpga"] : default_file_name @@ -364,7 +388,6 @@ b200_impl::b200_impl(const device_addr_t &device_addr) :      /* Initialize the GPIOs, set the default bandsels to the lower range. Note       * that calling update_bandsel calls update_gpio_state(). */ -    _gpio_state = gpio_state();      update_bandsel("RX", 800e6);      update_bandsel("TX", 850e6); @@ -481,9 +504,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) :      _tree->create<std::vector<size_t> >(mb_path / "rx_chan_dsp_mapping").set(default_map);      _tree->create<std::vector<size_t> >(mb_path / "tx_chan_dsp_mapping").set(default_map);      _tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec") +        .coerce(boost::bind(&b200_impl::coerce_subdev_spec, this, _1))          .set(subdev_spec_t())          .subscribe(boost::bind(&b200_impl::update_subdev_spec, this, "rx", _1));      _tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec") +        .coerce(boost::bind(&b200_impl::coerce_subdev_spec, this, _1))          .set(subdev_spec_t())          .subscribe(boost::bind(&b200_impl::update_subdev_spec, this, "tx", _1)); @@ -695,7 +720,7 @@ void b200_impl::setup_radio(const size_t dspno)      for(size_t direction = 0; direction < 2; direction++)      {          const std::string x = direction? "rx" : "tx"; -        const std::string key = std::string((direction? "RX" : "TX")) + std::string(((dspno == FE1)? "1" : "2")); +        const std::string key = std::string((direction? "RX" : "TX")) + std::string(((dspno == _fe1)? "1" : "2"));          const fs_path rf_fe_path = mb_path / "dboards" / "A" / (x+"_frontends") / (dspno? "B" : "A");          _tree->create<std::string>(rf_fe_path / "name").set("FE-"+key); @@ -1024,6 +1049,7 @@ void b200_impl::update_bandsel(const std::string& which, double freq)  void b200_impl::update_gpio_state(void)  {      const boost::uint32_t misc_word = 0 +        | (_gpio_state.swap_atr << 8)          | (_gpio_state.tx_bandsel_a << 7)          | (_gpio_state.tx_bandsel_b << 6)          | (_gpio_state.rx_bandsel_a << 5) @@ -1048,9 +1074,9 @@ void b200_impl::reset_codec_dcm(void)  void b200_impl::update_atrs(void)  { -    if (_radio_perifs.size() > FE1 and _radio_perifs[FE1].atr) +    if (_radio_perifs.size() > _fe1 and _radio_perifs[_fe1].atr)      { -        radio_perifs_t &perif = _radio_perifs[FE1]; +        radio_perifs_t &perif = _radio_perifs[_fe1];          const bool enb_rx = bool(perif.rx_streamer.lock());          const bool enb_tx = bool(perif.tx_streamer.lock());          const bool is_rx2 = perif.ant_rx2; @@ -1066,9 +1092,9 @@ void b200_impl::update_atrs(void)          atr->set_atr_reg(dboard_iface::ATR_REG_TX_ONLY, txonly);          atr->set_atr_reg(dboard_iface::ATR_REG_FULL_DUPLEX, fd);      } -    if (_radio_perifs.size() > FE2 and _radio_perifs[FE2].atr) +    if (_radio_perifs.size() > _fe2 and _radio_perifs[_fe2].atr)      { -        radio_perifs_t &perif = _radio_perifs[FE2]; +        radio_perifs_t &perif = _radio_perifs[_fe2];          const bool enb_rx = bool(perif.rx_streamer.lock());          const bool enb_tx = bool(perif.tx_streamer.lock());          const bool is_rx2 = perif.ant_rx2; @@ -1096,10 +1122,10 @@ void b200_impl::update_antenna_sel(const size_t which, const std::string &ant)  void b200_impl::update_enables(void)  {      //extract settings from state variables -    const bool enb_tx1 = (_radio_perifs.size() > FE1) and bool(_radio_perifs[FE1].tx_streamer.lock()); -    const bool enb_rx1 = (_radio_perifs.size() > FE1) and bool(_radio_perifs[FE1].rx_streamer.lock()); -    const bool enb_tx2 = (_radio_perifs.size() > FE2) and bool(_radio_perifs[FE2].tx_streamer.lock()); -    const bool enb_rx2 = (_radio_perifs.size() > FE2) and bool(_radio_perifs[FE2].rx_streamer.lock()); +    const bool enb_tx1 = (_radio_perifs.size() > _fe1) and bool(_radio_perifs[_fe1].tx_streamer.lock()); +    const bool enb_rx1 = (_radio_perifs.size() > _fe1) and bool(_radio_perifs[_fe1].rx_streamer.lock()); +    const bool enb_tx2 = (_radio_perifs.size() > _fe2) and bool(_radio_perifs[_fe2].tx_streamer.lock()); +    const bool enb_rx2 = (_radio_perifs.size() > _fe2) and bool(_radio_perifs[_fe2].rx_streamer.lock());      const size_t num_rx = (enb_rx1?1:0) + (enb_rx2?1:0);      const size_t num_tx = (enb_tx1?1:0) + (enb_tx2?1:0);      const bool mimo = num_rx == 2 or num_tx == 2; diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index b68293109..f5a7b62e9 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -47,7 +47,7 @@  #include "recv_packet_demuxer_3000.hpp"  static const boost::uint8_t  B200_FW_COMPAT_NUM_MAJOR = 7;  static const boost::uint8_t  B200_FW_COMPAT_NUM_MINOR = 0; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 5; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 7;  static const double          B200_BUS_CLOCK_RATE = 100e6;  static const double          B200_DEFAULT_TICK_RATE = 32e6;  static const double          B200_DEFAULT_FREQ = 100e6; // Hz @@ -107,6 +107,9 @@ public:      void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = "");  private: +    b200_type_t _b200_type; +    size_t      _revision; +      //controllers      b200_iface::sptr _iface;      radio_ctrl_core_3000::sptr _local_ctrl; @@ -143,6 +146,7 @@ private:      void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &);      void check_fw_compat(void);      void check_fpga_compat(void); +    uhd::usrp::subdev_spec_t coerce_subdev_spec(const uhd::usrp::subdev_spec_t &);      void update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &);      void update_time_source(const std::string &);      void update_clock_source(const std::string &); @@ -168,6 +172,13 @@ private:      };      std::vector<radio_perifs_t> _radio_perifs; +    //mapping of AD936x frontends (FE1 and FE2) to radio perif index (0 and 1) +    //FE1 corresponds to the ports labeled "RF B" on the B200/B210 +    //FE2 corresponds to the ports labeled "RF A" on the B200/B210 +    //the mapping is product and revision specific +    size_t _fe1; +    size_t _fe2; +      /*! \brief Setup the DSP chain for one radio front-end.       *       */ @@ -175,7 +186,7 @@ private:      void handle_overflow(const size_t radio_index);      struct gpio_state { -        boost::uint32_t  tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel; +        boost::uint32_t  tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel, swap_atr;          gpio_state() {              tx_bandsel_a = 0; @@ -186,6 +197,7 @@ private:              codec_arst = 0;              mimo = 0;              ref_sel = 0; +            swap_atr = 0;          }      } _gpio_state; diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index d6df726af..61bcc5f64 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -81,6 +81,7 @@ void b200_impl::set_auto_tick_rate(      if (num_chans == 0) { // Divine them          num_chans = std::max(size_t(1), max_chan_count());      } +    const double max_tick_rate = ad9361_device_t::AD9361_MAX_CLOCK_RATE/num_chans;      // See also the doxygen documentation for these steps in b200_impl.hpp      // Step 1: Obtain LCM and max rate from all relevant dsps @@ -94,6 +95,13 @@ void b200_impl::set_auto_tick_rate(                  continue;              }              double this_dsp_rate = _tree->access<double>(dsp_path / "rate/value").get(); +            // Check if the user selected something completely unreasonable: +            if (this_dsp_rate > max_tick_rate) { +                throw uhd::value_error(str( +                        boost::format("Requested sampling rate (%.2f Msps) exceeds maximum tick rate of %.2f MHz.") +                        % (this_dsp_rate / 1e6) % (max_tick_rate / 1e6) +                )); +            }              // If this_dsp_rate == B200_DEFAULT_RATE, we assume the user did not actually set              // the sampling rate. If the user *did* set the rate to              // B200_DEFAULT_RATE on all DSPs, then this will still work (see below). @@ -118,7 +126,6 @@ void b200_impl::set_auto_tick_rate(      // Step 2: Determine whether if we can use lcm_rate (preferred),      // or have to give up because too large: -    const double max_tick_rate = ad9361_device_t::AD9361_MAX_CLOCK_RATE/num_chans;      double base_rate = static_cast<double>(lcm_rate);      if (base_rate > max_tick_rate) {          UHD_MSG(warning) @@ -175,10 +182,19 @@ void b200_impl::update_tick_rate(const double new_tick_rate)      }  } +#define CHECK_RATE_AND_THROW(rate)  \ +        if (rate >ad9361_device_t::AD9361_MAX_CLOCK_RATE ) { \ +            throw uhd::value_error(str( \ +                    boost::format("Requested sampling rate (%.2f Msps) exceeds maximum tick rate.") \ +                    % (rate / 1e6) \ +            )); \ +        } +  double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate)  {      // Have to set tick rate first, or the ddc will change the requested rate based on default tick rate      if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { +        CHECK_RATE_AND_THROW(rx_rate);          const std::string dsp_path = (boost::format("/mboards/0/rx_dsps/%s") % dspno).str();          set_auto_tick_rate(rx_rate, dsp_path);      } @@ -208,6 +224,7 @@ double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno,  {      // Have to set tick rate first, or the duc will change the requested rate based on default tick rate      if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { +        CHECK_RATE_AND_THROW(tx_rate);          const std::string dsp_path = (boost::format("/mboards/0/tx_dsps/%s") % dspno).str();          set_auto_tick_rate(tx_rate, dsp_path);      } @@ -228,29 +245,31 @@ void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate)  /***********************************************************************   * frontend selection   **********************************************************************/ +uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec(const uhd::usrp::subdev_spec_t &spec_) +{ +    uhd::usrp::subdev_spec_t spec = spec_; +    // Because of the confusing nature of the subdevs on B200 +    // with different revs, we provide a convenience override, +    // where both A:A and A:B are mapped to A:A. +    // +    // Any other spec is probably illegal and will be caught by +    // validate_subdev_spec(). +    if (spec.size() and _b200_type == B200 and spec[0].sd_name == "B") { +        spec[0].sd_name = "A"; +    } +    return spec; +} +  void b200_impl::update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &spec)  {      //sanity checking -    if (spec.size()) validate_subdev_spec(_tree, spec, tx_rx); -    UHD_ASSERT_THROW(spec.size() <= _radio_perifs.size()); - -    if (spec.size() >= 1) -    { -        UHD_ASSERT_THROW(spec[0].db_name == "A"); -        UHD_ASSERT_THROW(spec[0].sd_name == "A" or spec[0].sd_name == "B"); -    } -    if (spec.size() == 2) -    { -        UHD_ASSERT_THROW(spec[1].db_name == "A"); -        UHD_ASSERT_THROW( -            (spec[0].sd_name == "A" and spec[1].sd_name == "B") or -            (spec[0].sd_name == "B" and spec[1].sd_name == "A") -        ); +    if (spec.size()) { +        validate_subdev_spec(_tree, spec, tx_rx);      }      std::vector<size_t> chan_to_dsp_map(spec.size(), 0);      for (size_t i = 0; i < spec.size(); i++) { -	chan_to_dsp_map[i] = (spec[i].sd_name == "A") ? 0 : 1; +        chan_to_dsp_map[i] = (spec[i].sd_name == "A") ? 0 : 1;      }      _tree->access<std::vector<size_t> >("/mboards/0" / (tx_rx + "_chan_dsp_mapping")).set(chan_to_dsp_map); @@ -300,7 +319,7 @@ boost::optional<uhd::msg_task::msg_type_t> b200_impl::handle_async_task(  {      managed_recv_buffer::sptr buff = xport->get_recv_buff();      if (not buff or buff->size() < 8) -        return NULL; +        return uhd::msg_task::msg_type_t(0, uhd::msg_task::msg_payload_t());      const boost::uint32_t sid = uhd::wtohx(buff->cast<const boost::uint32_t *>()[1]);      switch (sid) { @@ -364,7 +383,7 @@ boost::optional<uhd::msg_task::msg_type_t> b200_impl::handle_async_task(      default:          UHD_MSG(error) << "Got a ctrl packet with unknown SID " << sid << std::endl;      } -    return NULL; +    return uhd::msg_task::msg_type_t(0, uhd::msg_task::msg_payload_t());  }  /*********************************************************************** diff --git a/host/lib/usrp/dboard/db_ubx.cpp b/host/lib/usrp/dboard/db_ubx.cpp index 1e79c14b0..7cb4b2d6b 100644 --- a/host/lib/usrp/dboard/db_ubx.cpp +++ b/host/lib/usrp/dboard/db_ubx.cpp @@ -266,6 +266,8 @@ public:          }          // Enable the reference clocks that we need +        _rx_target_pfd_freq = pfd_freq_max; +        _tx_target_pfd_freq = pfd_freq_max;          if (_rev >= 1)          {              // set dboard clock rates to as close to the max PFD freq as possible diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index cfaee0ddc..81dd3523e 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -30,7 +30,8 @@ extern "C" {  #endif  //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 11 +#define USRP2_FPGA_COMPAT_NUM 10 +#define N200_FPGA_COMPAT_NUM 11  #define USRP2_FW_COMPAT_NUM 12  #define USRP2_FW_VER_MINOR 4 diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 50b8431a1..1acc1dad3 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -395,14 +395,35 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) :              fpga_major = fpga_minor;              fpga_minor = 0;          } -        if (fpga_major != USRP2_FPGA_COMPAT_NUM){ +        int expected_fpga_compat_num = std::min(USRP2_FPGA_COMPAT_NUM, N200_FPGA_COMPAT_NUM); +        switch (_mbc[mb].iface->get_rev()) +        { +        case usrp2_iface::USRP2_REV3: +        case usrp2_iface::USRP2_REV4: +            expected_fpga_compat_num = USRP2_FPGA_COMPAT_NUM; +            break; +        case usrp2_iface::USRP_N200: +        case usrp2_iface::USRP_N200_R4: +        case usrp2_iface::USRP_N210: +        case usrp2_iface::USRP_N210_R4: +            expected_fpga_compat_num = N200_FPGA_COMPAT_NUM; +            break; +        default: +            // handle case where the MB EEPROM is not programmed +            if (fpga_major == USRP2_FPGA_COMPAT_NUM or fpga_major == N200_FPGA_COMPAT_NUM) +            { +                UHD_MSG(warning)  << "Unable to identify device - assuming USRP2/N-Series device" << std::endl; +                expected_fpga_compat_num = fpga_major; +            } +        } +        if (fpga_major != expected_fpga_compat_num){              throw uhd::runtime_error(str(boost::format(                  "\nPlease update the firmware and FPGA images for your device.\n"                  "See the application notes for USRP2/N-Series for instructions.\n"                  "Expected FPGA compatibility number %d, but got %d:\n"                  "The FPGA build is not compatible with the host code build.\n"                  "%s\n" -            ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_major % _mbc[mb].iface->images_warn_help_message())); +            ) % expected_fpga_compat_num % fpga_major % _mbc[mb].iface->images_warn_help_message()));          }          _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index f29318ddd..a9c9965c8 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -367,10 +367,10 @@ std::string uhd::find_utility(std::string name) {          .string();  } -std::string uhd::print_utility_error(std::string name){ +std::string uhd::print_utility_error(const std::string &name, const std::string &args){      #ifdef UHD_PLATFORM_WIN32 -    return "As an Administrator, please run:\n\n\"" + find_utility(name) + "\""; +    return "As an Administrator, please run:\n\n\"" + find_utility(name) + args +  "\"";      #else -    return "Please run:\n\n \"" + find_utility(name) + "\""; +    return "Please run:\n\n \"" + find_utility(name) + (args.empty() ? "" : (" " + args)) + "\"";      #endif  } diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index ed8640187..e24b417c1 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -15,8 +15,6 @@  # along with this program.  If not, see <http://www.gnu.org/licenses/>.  # -SET(CMAKE_C_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT}) -  ########################################################################  # Utilities that get installed into the runtime path  ######################################################################## diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp index a03646cc0..f8a8b5665 100644 --- a/host/utils/uhd_usrp_probe.cpp +++ b/host/utils/uhd_usrp_probe.cpp @@ -192,7 +192,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("version", "print the version string and exit")          ("args", po::value<std::string>()->default_value(""), "device address args")          ("tree", "specify to print a complete property tree") -        ("string", po::value<std::string>(), "query a string value from the properties tree") +        ("string", po::value<std::string>(), "query a string value from the property tree") +        ("double", po::value<std::string>(), "query a double precision floating point value from the property tree") +        ("int", po::value<std::string>(), "query a integer value from the property tree") +        ("range", po::value<std::string>(), "query a range (gain, bandwidth, frequency, ...)  from the property tree")          ("init-only", "skip all queries, only initialize device")      ; @@ -219,6 +222,22 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          return EXIT_SUCCESS;      } +    if (vm.count("double")){ +        std::cout << tree->access<double>(vm["double"].as<std::string>()).get() << std::endl; +        return EXIT_SUCCESS; +    } + +    if (vm.count("int")){ +        std::cout << tree->access<int>(vm["int"].as<std::string>()).get() << std::endl; +        return EXIT_SUCCESS; +    } + +    if (vm.count("range")){ +        meta_range_t range = tree->access<meta_range_t>(vm["range"].as<std::string>()).get(); +        std::cout << boost::format("%.1f:%.1f:%.1f") % range.start() % range.step() % range.stop() << std::endl; +        return EXIT_SUCCESS; +    } +      if (vm.count("tree") != 0) print_tree("/", tree);      else if (not vm.count("init-only")) std::cout << make_border(get_device_pp_string(tree)) << std::endl; diff --git a/host/utils/usrp_x3xx_fpga_burner.cpp b/host/utils/usrp_x3xx_fpga_burner.cpp index e32e4d636..3c6225531 100644 --- a/host/utils/usrp_x3xx_fpga_burner.cpp +++ b/host/utils/usrp_x3xx_fpga_burner.cpp @@ -49,13 +49,9 @@  #include <uhd/utils/safe_main.hpp>  #include <uhd/utils/safe_call.hpp> -#ifdef _MSC_VER  extern "C" { -#endif  #include "cdecode.h" -#ifdef _MSC_VER  } -#endif  #define X300_FPGA_BIN_SIZE_BYTES 15877916  #define X300_FPGA_BIT_MAX_SIZE_BYTES 15878022  | 
