From 069cd969ef68d4580ac159eea2b544d4e6fc2980 Mon Sep 17 00:00:00 2001 From: Ben Hilburn Date: Wed, 1 Apr 2015 16:03:30 -0700 Subject: FX3: Updating FX3 FW build docs Conflicts: firmware/fx3/README.md --- firmware/fx3/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 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=/arm-2011.03 + $ export ARMGCC_INSTALL_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 ``` -- cgit v1.2.3 From 90cc498983facb13f958e30d5662c872f839b356 Mon Sep 17 00:00:00 2001 From: Ben Hilburn Date: Wed, 1 Apr 2015 16:03:42 -0700 Subject: FX3: Updating FW to support NI-USRP VID and PIDs Conflicts: firmware/fx3/b200/b200_usb_descriptors.c --- firmware/fx3/b200/b200_main.c | 35 +++++++++++-- firmware/fx3/b200/b200_main.h | 4 ++ firmware/fx3/b200/b200_usb_descriptors.c | 84 ++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 3 deletions(-) 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))) = { -- cgit v1.2.3 From 5e3bf468c3e379743ede3b10a70699976ea83b09 Mon Sep 17 00:00:00 2001 From: Ben Hilburn Date: Thu, 2 Apr 2015 12:42:45 -0700 Subject: B200: UHD now detects loaded FW on NI-USRP devices Conflicts: host/lib/transport/libusb1_base.cpp --- host/lib/transport/libusb1_base.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 375cfe92d..ae33cc036 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"); } -- cgit v1.2.3 From be54951d4c14b11e21518f2e7d87fd527102c948 Mon Sep 17 00:00:00 2001 From: michael-west Date: Wed, 15 Apr 2015 13:55:10 -0700 Subject: UHD host code changes for B200 rev 5 support. --- host/lib/usrp/b200/b200_impl.cpp | 35 ++++++++++++++++++++++------------- host/lib/usrp/b200/b200_impl.hpp | 4 ++++ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index e567ff434..cea7e5969 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() {} @@ -264,6 +260,19 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : UHD_ASSERT_THROW(device_addr.has_key("fpga")); } + //set up frontend mapping + _fe1 = 1; + _fe2 = 0; + if (not mb_eeprom["revision"].empty()) + { + size_t rev = boost::lexical_cast(mb_eeprom["revision"]); + if (rev == 5) + { + _fe1 = 0; + _fe2 = 1; + } + } + //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 @@ -628,7 +637,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(rf_fe_path / "name").set("FE-"+key); @@ -924,9 +933,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; @@ -942,9 +951,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; @@ -972,10 +981,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 396819f9a..e871e6b9a 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -119,6 +119,10 @@ private: boost::mutex _transport_setup_mutex; + // mapping of frontend to radio perif index + size_t _fe1; + size_t _fe2; + //async ctrl + msgs uhd::msg_task::sptr _async_task; typedef uhd::transport::bounded_buffer async_md_type; -- cgit v1.2.3 From df6bf0e77d42f2281fbe07296766924c3c066962 Mon Sep 17 00:00:00 2001 From: michael-west Date: Wed, 15 Apr 2015 17:38:44 -0700 Subject: B200: Stricter checking of product and revision for frontend mapping. --- host/lib/usrp/b200/b200_impl.cpp | 15 ++++++++------- host/lib/usrp/b200/b200_impl.hpp | 11 +++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index cea7e5969..f55ae2a71 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -238,6 +238,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : //////////////////////////////////////////////////////////////////// std::string default_file_name; std::string product_name = "B200?"; + enum {UNKNOWN,B200,B210} product = UNKNOWN; if (not mb_eeprom["product"].empty()) { switch (boost::lexical_cast(mb_eeprom["product"])) @@ -246,11 +247,13 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : case 0x7737: product_name = "B200"; default_file_name = B200_FPGA_FILE_NAME; + product = B200; break; case 0x7738: case 0x0002: product_name = "B210"; default_file_name = B210_FPGA_FILE_NAME; + product = B210; break; default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; } @@ -263,14 +266,12 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : //set up frontend mapping _fe1 = 1; _fe2 = 0; - if (not mb_eeprom["revision"].empty()) + if (product == B200 and + not mb_eeprom["revision"].empty() and + boost::lexical_cast(mb_eeprom["revision"]) >= 5) { - size_t rev = boost::lexical_cast(mb_eeprom["revision"]); - if (rev == 5) - { - _fe1 = 0; - _fe2 = 1; - } + _fe1 = 0; + _fe2 = 1; } //extract the FPGA path for the B200 diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index e871e6b9a..fd94d36ab 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -119,10 +119,6 @@ private: boost::mutex _transport_setup_mutex; - // mapping of frontend to radio perif index - size_t _fe1; - size_t _fe2; - //async ctrl + msgs uhd::msg_task::sptr _async_task; typedef uhd::transport::bounded_buffer async_md_type; @@ -165,6 +161,13 @@ private: }; std::vector _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. * */ -- cgit v1.2.3 From 24c370781e7ea2e627ce36d3b102a686eaedcf1b Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 13 Mar 2015 14:39:09 -0700 Subject: b2x0: Cleaned up device lookup (moved all constants to one place) Conflicts: host/lib/usrp/b200/b200_iface.hpp host/lib/usrp/b200/b200_impl.cpp --- host/lib/usrp/b200/b200_iface.hpp | 45 +++++++++++++++++---- host/lib/usrp/b200/b200_impl.cpp | 84 +++++++++++++++++++++------------------ host/lib/usrp/b200/b200_impl.hpp | 2 + 3 files changed, 84 insertions(+), 47 deletions(-) diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 83adfdd64..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,19 +21,48 @@ #include #include #include //i2c iface +#include +#include #include #include #include "ad9361_ctrl.hpp" -const static boost::uint16_t B200_VENDOR_ID = 0x2500; -const static boost::uint16_t B200_PRODUCT_ID = 0x0020; -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; +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; 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 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 B2X0_STR_NAMES = boost::assign::map_list_of + (B200, "B200") + (B210, "B210") +; + +static const uhd::dict 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 f55ae2a71..f4a124a32 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -73,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(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; @@ -148,20 +166,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(mb_eeprom["product"])) - { - case 0x0001: - case 0x7737: - new_addr["product"] = "B200"; - break; - case 0x7738: - case 0x0002: - 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 ( @@ -234,39 +246,30 @@ 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?"; - enum {UNKNOWN,B200,B210} product = UNKNOWN; - if (not mb_eeprom["product"].empty()) - { - switch (boost::lexical_cast(mb_eeprom["product"])) - { - case 0x0001: - case 0x7737: - product_name = "B200"; - default_file_name = B200_FPGA_FILE_NAME; - product = B200; - break; - case 0x7738: - case 0x0002: - product_name = "B210"; - default_file_name = B210_FPGA_FILE_NAME; - product = B210; - 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; } - } - if (default_file_name.empty()) - { - UHD_ASSERT_THROW(device_addr.has_key("fpga")); + // In this case, we must provide a default product name: + product_name = "B200?"; + _b200_type = B200; } //set up frontend mapping _fe1 = 1; _fe2 = 0; - if (product == B200 and + if (_b200_type == B200 and not mb_eeprom["revision"].empty() and boost::lexical_cast(mb_eeprom["revision"]) >= 5) { @@ -274,6 +277,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _fe2 = 1; } + //////////////////////////////////////////////////////////////////// + // 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 diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index fd94d36ab..b580ff260 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -101,6 +101,8 @@ public: void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction = NULL); private: + b200_type_t _b200_type; + //controllers b200_iface::sptr _iface; radio_ctrl_core_3000::sptr _local_ctrl; -- cgit v1.2.3 From 0a103ba2bad243652e8c57732190a18a2ee31d38 Mon Sep 17 00:00:00 2001 From: michael-west Date: Fri, 17 Apr 2015 17:43:07 -0700 Subject: B200: Bumped FPGA compat number to 5 B200: Added bit to SR_MISC_OUT register to control ATR mapping from radio to frontend --- host/lib/usrp/b200/b200_impl.cpp | 7 ++++--- host/lib/usrp/b200/b200_impl.hpp | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index f4a124a32..273153c16 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -273,8 +273,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : not mb_eeprom["revision"].empty() and boost::lexical_cast(mb_eeprom["revision"]) >= 5) { - _fe1 = 0; - _fe2 = 1; + _fe1 = 0; //map radio0 to FE1 + _fe2 = 1; //map radio1 to FE2 + _gpio_state.atr_sel = 1; //map radio0 ATR pins to FE2 } //////////////////////////////////////////////////////////////////// @@ -332,7 +333,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); @@ -916,6 +916,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.atr_sel << 8) | (_gpio_state.tx_bandsel_a << 7) | (_gpio_state.tx_bandsel_b << 6) | (_gpio_state.rx_bandsel_a << 5) diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index b580ff260..8d0c637d7 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 = 4; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 5; static const double B200_BUS_CLOCK_RATE = 100e6; static const double B200_DEFAULT_TICK_RATE = 32e6; static const double B200_DEFAULT_FREQ = 100e6; // Hz @@ -177,7 +177,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, atr_sel; gpio_state() { tx_bandsel_a = 0; @@ -188,6 +188,7 @@ private: codec_arst = 0; mimo = 0; ref_sel = 0; + atr_sel = 0; } } _gpio_state; -- cgit v1.2.3 From 14d2555d832f68243d5c810ba76f8f0823a3198c Mon Sep 17 00:00:00 2001 From: Marcus Müller Date: Thu, 16 Apr 2015 21:37:49 +0200 Subject: utils: added integer, range and double property tree accessors This amends uhd_usrp_probe's ability to query the property tree. --- host/utils/uhd_usrp_probe.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) 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()->default_value(""), "device address args") ("tree", "specify to print a complete property tree") - ("string", po::value(), "query a string value from the properties tree") + ("string", po::value(), "query a string value from the property tree") + ("double", po::value(), "query a double precision floating point value from the property tree") + ("int", po::value(), "query a integer value from the property tree") + ("range", po::value(), "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(vm["double"].as()).get() << std::endl; + return EXIT_SUCCESS; + } + + if (vm.count("int")){ + std::cout << tree->access(vm["int"].as()).get() << std::endl; + return EXIT_SUCCESS; + } + + if (vm.count("range")){ + meta_range_t range = tree->access(vm["range"].as()).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; -- cgit v1.2.3 From eacd36d94d8d9432c09a8ab79884845efeb5fd4b Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Mon, 20 Apr 2015 14:32:28 -0400 Subject: b200: Boost 1.58-related fixes in B200 IO code. When returning an invalid payload in handle_async_task, Boost 1.58 does not allow NULL to be returned; instead, to be more compatible, use the correct type initialized to (0, []). --- host/lib/usrp/b200/b200_io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index cf5ba7a11..3e156f9bb 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -194,7 +194,7 @@ boost::optional 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()[1]); switch (sid) { @@ -258,7 +258,7 @@ boost::optional 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()); } /*********************************************************************** -- cgit v1.2.3 From 63ba4f76a76d9b04d8642abc71f002cb23a8759d Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 20 Apr 2015 15:50:48 -0700 Subject: cmake: Improve usage of C modules --- host/CMakeLists.txt | 2 +- host/utils/CMakeLists.txt | 2 -- host/utils/usrp_x3xx_fpga_burner.cpp | 4 ---- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index e2f318056..beb4d396f 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 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 . # -SET(CMAKE_C_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT}) - ######################################################################## # Utilities that get installed into the runtime path ######################################################################## 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 #include -#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 -- cgit v1.2.3 From 73d42182be1b84943dfa0569d3cb2d0a5b21e2ff Mon Sep 17 00:00:00 2001 From: Marcus Müller Date: Thu, 16 Apr 2015 21:37:49 +0200 Subject: utils: added integer, range and double property tree accessors This amends uhd_usrp_probe's ability to query the property tree. --- host/utils/uhd_usrp_probe.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) 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()->default_value(""), "device address args") ("tree", "specify to print a complete property tree") - ("string", po::value(), "query a string value from the properties tree") + ("string", po::value(), "query a string value from the property tree") + ("double", po::value(), "query a double precision floating point value from the property tree") + ("int", po::value(), "query a integer value from the property tree") + ("range", po::value(), "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(vm["double"].as()).get() << std::endl; + return EXIT_SUCCESS; + } + + if (vm.count("int")){ + std::cout << tree->access(vm["int"].as()).get() << std::endl; + return EXIT_SUCCESS; + } + + if (vm.count("range")){ + meta_range_t range = tree->access(vm["range"].as()).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; -- cgit v1.2.3 From a9b6141d7c5f46fd85a629c568ff0e8ebd46ec24 Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Mon, 20 Apr 2015 14:32:28 -0400 Subject: b200: Boost 1.58-related fixes in B200 IO code. When returning an invalid payload in handle_async_task, Boost 1.58 does not allow NULL to be returned; instead, to be more compatible, use the correct type initialized to (0, []). --- host/lib/usrp/b200/b200_io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index d6df726af..eb7bbe048 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -300,7 +300,7 @@ boost::optional 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()[1]); switch (sid) { @@ -364,7 +364,7 @@ boost::optional 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()); } /*********************************************************************** -- cgit v1.2.3 From 396549ac210df6cebc662213d812a8ce4353f467 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 20 Apr 2015 15:50:48 -0700 Subject: cmake: Improve usage of C modules --- host/CMakeLists.txt | 2 +- host/utils/CMakeLists.txt | 2 -- host/utils/usrp_x3xx_fpga_burner.cpp | 4 ---- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 8dddb6552..1fa8b2cdb 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 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 . # -SET(CMAKE_C_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT}) - ######################################################################## # Utilities that get installed into the runtime path ######################################################################## 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 #include -#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 -- cgit v1.2.3 From da800edf099db2adcb6b2fd4038cc6d15cdaf57f Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 13 Mar 2015 14:39:09 -0700 Subject: b2x0: Cleaned up device lookup (moved all constants to one place) --- host/lib/usrp/b200/b200_iface.hpp | 44 ++++++++++++++++---- host/lib/usrp/b200/b200_impl.cpp | 87 ++++++++++++++++++++------------------- host/lib/usrp/b200/b200_impl.hpp | 2 + 3 files changed, 81 insertions(+), 52 deletions(-) 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 #include #include //i2c iface +#include +#include #include #include #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 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 B2X0_STR_NAMES = boost::assign::map_list_of + (B200, "B200") + (B210, "B210") +; + +static const uhd::dict 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..14c2c31aa 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -77,6 +77,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(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 +173,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(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 ( @@ -282,36 +290,29 @@ 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(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; } - } - if (default_file_name.empty()) - { - UHD_ASSERT_THROW(device_addr.has_key("fpga")); + // In this case, we must provide a default product name: + product_name = "B200?"; + _b200_type = B200; } + //////////////////////////////////////////////////////////////////// + // 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 diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index b68293109..0e5e09d4b 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -107,6 +107,8 @@ public: void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = ""); private: + b200_type_t _b200_type; + //controllers b200_iface::sptr _iface; radio_ctrl_core_3000::sptr _local_ctrl; -- cgit v1.2.3 From 4e8f0817001d14a9eb2b85f042f185b0c802b6ed Mon Sep 17 00:00:00 2001 From: michael-west Date: Wed, 22 Apr 2015 17:55:43 -0700 Subject: USRP2: Separate FPGA compat numbers for USRP2 and N200. --- host/lib/usrp/usrp2/fw_common.h | 3 ++- host/lib/usrp/usrp2/usrp2_impl.cpp | 25 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) 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(mb_path / "fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); -- cgit v1.2.3 From 0eac5ac12dd92c90921633f89e2228972f74aade Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 23 Apr 2015 12:23:54 -0700 Subject: b200: Bumped FPGA compat number to 6 --- host/lib/usrp/b200/b200_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 8d0c637d7..318b35947 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 = 6; static const double B200_BUS_CLOCK_RATE = 100e6; static const double B200_DEFAULT_TICK_RATE = 32e6; static const double B200_DEFAULT_FREQ = 100e6; // Hz -- cgit v1.2.3 From 908b5429917ef8f3f5363f5ffc4710e0258914e6 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 23 Apr 2015 15:48:36 -0700 Subject: b200: Bumped FPGA compat number to 7. --- host/lib/usrp/b200/b200_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 97dc21fc5..3628745a1 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 = 6; +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 -- cgit v1.2.3 From 9ca0473ac09a2f251382b270059278730135b606 Mon Sep 17 00:00:00 2001 From: Michael West Date: Thu, 23 Apr 2015 16:18:45 -0700 Subject: ubx: pfd frequency fix (relevant for X300 operation) --- host/lib/usrp/dboard/db_ubx.cpp | 2 ++ 1 file changed, 2 insertions(+) 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 -- cgit v1.2.3 From d74af0b4d17d66f9bb94638a06a25195f6dc885a Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 24 Apr 2015 15:15:40 -0700 Subject: b200: Fixed FE swapping register --- host/lib/usrp/b200/b200_impl.cpp | 20 +++++++++++++++++--- host/lib/usrp/b200/b200_impl.hpp | 4 ++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 273153c16..84153309e 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -266,16 +266,30 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _b200_type = B200; } - //set up frontend mapping + //////////////////////////////////////////////////////////////////// + // 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 not mb_eeprom["revision"].empty() and boost::lexical_cast(mb_eeprom["revision"]) >= 5) { _fe1 = 0; //map radio0 to FE1 _fe2 = 1; //map radio1 to FE2 - _gpio_state.atr_sel = 1; //map radio0 ATR pins to FE2 + _gpio_state.swap_atr = 0; //map radio0 ATR pins to FE2 } //////////////////////////////////////////////////////////////////// @@ -916,7 +930,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.atr_sel << 8) + | (_gpio_state.swap_atr << 8) | (_gpio_state.tx_bandsel_a << 7) | (_gpio_state.tx_bandsel_b << 6) | (_gpio_state.rx_bandsel_a << 5) diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 318b35947..f3d3d0e98 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -177,7 +177,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, atr_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; @@ -188,7 +188,7 @@ private: codec_arst = 0; mimo = 0; ref_sel = 0; - atr_sel = 0; + swap_atr = 0; } } _gpio_state; -- cgit v1.2.3 From 47ddba6fcc0c14ddac961dfe73ce5c3aa15dbba4 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 14 Apr 2015 15:04:30 -0500 Subject: b200: Throw error for unreachable sampling rates When auto tick rate is used, and the sampling rate exceeds the limits, throw an error instead of coercing to the default rate. --- host/lib/usrp/b200/b200_io_impl.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index eb7bbe048..52a90a623 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(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(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("/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("/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); } -- cgit v1.2.3 From 925bd26d3a66de434f32ac69599564dc2f5bc69d Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 24 Apr 2015 18:13:58 -0700 Subject: docs: Added FPGA manual The actual FPGA manual pages are in the FPGA repository. Only if the submodule is checked out will it build the manual pages. If the submodule is not checked out, it will create a link to the FPGA manual hosted online. --- host/CMakeLists.txt | 13 +++++++++++++ host/docs/CMakeLists.txt | 23 ++++++++++++++++++++++- host/docs/Doxyfile.in | 6 +++--- host/docs/mainpage.dox | 28 ---------------------------- host/docs/mainpage.dox.in | 29 +++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 32 deletions(-) delete mode 100644 host/docs/mainpage.dox create mode 100644 host/docs/mainpage.dox.in diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index beb4d396f..c235ffe82 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -280,6 +280,19 @@ LIBUHD_REGISTER_COMPONENT("Examples" ENABLE_EXAMPLES ON "ENABLE_LIBUHD" OFF) 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 ######################################################################## diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index 84ed88281..9540ef28e 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -31,12 +31,33 @@ 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 "Part III: FPGA Manual") + # 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 page_fpga \"Part III: FPGA Manual\"") + ENDIF(HAS_FPGA_SUBMODULE) + message(STATUS ${manual_sources}) + 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..bca3b71d1 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@ @FPGA_SUBMODULE_DIR@ # 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 deleted file mode 100644 index a12e62c9c..000000000 --- a/host/docs/mainpage.dox +++ /dev/null @@ -1,28 +0,0 @@ -/*! \mainpage Table Of Contents - -Welcome to the USRP Hardware Driver (UHD) manual. Here, you will find information on how to use the devices and how to use the API to connect to them through your own software. - -This manual is split into two parts: The device manual, and the UHD/API manual. The first part describes details of our devices, mainboards and daughterboards, as well as aspects of _using_ UHD. - -The second is meant for developers writing UHD-based applications, and includes descriptions of the API, sorted by namespaces, classes and files. - -Follow these links to get to the section of the manual you wish to consult, or use the browser in the left sidebar. A search bar is also available at the top right, but note that this only works on API components. For information on how to build and install UHD, go to the UHD web site (see below). - -## Manual Parts - -\li \subpage page_devices "Part I: Devices & Usage Manual" -\li \subpage page_uhd "Part II: UHD Development Manual" - -### Further Information - -\li Ettus Research LLC Website -\li UHD Wiki Page - -### Building and Installing UHD - -\li \subpage page_build_guide -\li Installation Guide (Linux) -\li Installation Guide (Windows) - -*/ -// vim:ft=doxygen: diff --git a/host/docs/mainpage.dox.in b/host/docs/mainpage.dox.in new file mode 100644 index 000000000..428650633 --- /dev/null +++ b/host/docs/mainpage.dox.in @@ -0,0 +1,29 @@ +/*! \mainpage Table Of Contents + +Welcome to the USRP Hardware Driver (UHD) manual. Here, you will find information on how to use the devices and how to use the API to connect to them through your own software. + +This manual is split into two parts: The device manual, and the UHD/API manual. The first part describes details of our devices, mainboards and daughterboards, as well as aspects of _using_ UHD. + +The second is meant for developers writing UHD-based applications, and includes descriptions of the API, sorted by namespaces, classes and files. + +Follow these links to get to the section of the manual you wish to consult, or use the browser in the left sidebar. A search bar is also available at the top right, but note that this only works on API components. For information on how to build and install UHD, go to the UHD web site (see below). + +## Manual Parts + +\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 + +\li Ettus Research LLC Website +\li UHD Wiki Page + +### Building and Installing UHD + +\li \subpage page_build_guide +\li Installation Guide (Linux) +\li Installation Guide (Windows) + +*/ +// vim:ft=doxygen: -- cgit v1.2.3 From 0e1bba1ae05aa3edff65eddfc174d98d64fa1f42 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 27 Apr 2015 10:09:04 -0700 Subject: b200: Added convenience subdev override for consistent subdev experience --- host/lib/usrp/b200/b200_impl.cpp | 15 +++++++++------ host/lib/usrp/b200/b200_impl.hpp | 2 ++ host/lib/usrp/b200/b200_io_impl.cpp | 34 ++++++++++++++++++---------------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 84153309e..d66920bd9 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -205,7 +205,8 @@ UHD_STATIC_BLOCK(register_b200_device) * Structors **********************************************************************/ b200_impl::b200_impl(const device_addr_t &device_addr) : - _tick_rate(0.0) // Forces a clock initialization at startup + _tick_rate(0.0), // Forces a clock initialization at startup + _revision(0) { _tree = property_tree::make(); _type = device::USRP; @@ -265,6 +266,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : product_name = "B200?"; _b200_type = B200; } + if (not mb_eeprom["revision"].empty()) { + _revision = boost::lexical_cast(mb_eeprom["revision"]); + } //////////////////////////////////////////////////////////////////// // Set up frontend mapping @@ -283,13 +287,10 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _fe2 = 0; _gpio_state.swap_atr = 1; // Unswapped setup: - if (_b200_type == B200 and - not mb_eeprom["revision"].empty() and - boost::lexical_cast(mb_eeprom["revision"]) >= 5) - { + if (_b200_type == B200 and _revision >= 5) { _fe1 = 0; //map radio0 to FE1 _fe2 = 1; //map radio1 to FE2 - _gpio_state.swap_atr = 0; //map radio0 ATR pins to FE2 + _gpio_state.swap_atr = 0; // ATRs for radio0 are mapped to FE1 } //////////////////////////////////////////////////////////////////// @@ -462,9 +463,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _tree->create >(mb_path / "rx_chan_dsp_mapping").set(default_map); _tree->create >(mb_path / "tx_chan_dsp_mapping").set(default_map); _tree->create(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(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)); diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index f3d3d0e98..bc49595b9 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -102,6 +102,7 @@ public: private: b200_type_t _b200_type; + size_t _revision; //controllers b200_iface::sptr _iface; @@ -139,6 +140,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 &); diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index 3e156f9bb..1e11e7ff6 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -122,29 +122,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 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 >("/mboards/0" / (tx_rx + "_chan_dsp_mapping")).set(chan_to_dsp_map); -- cgit v1.2.3 From b3bfba0f3e4afedd98e330e542975db796d298b1 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 10:41:44 -0700 Subject: uhd: Added args arg to print_utility_warning --- host/include/uhd/utils/paths.hpp | 2 +- host/lib/utils/paths.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) 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/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 } -- cgit v1.2.3 From 4efa67ffcdedd68f77d8df439d433597a5744059 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 11:27:39 -0700 Subject: docs: Track doc updates on fpga-src --- host/docs/CMakeLists.txt | 4 +++- host/docs/Doxyfile.in | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index 9540ef28e..a73d39356 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -45,13 +45,15 @@ IF(ENABLE_MANUAL) SET(DOXYGEN_INPUT_DIRS "${CMAKE_SOURCE_DIR}/docs") SET(DOXYGEN_DEP_COMPONENT "manual") SET(DOXYGEN_FPGA_MANUAL_REFERENCE "Part III: FPGA Manual") + 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 page_fpga \"Part III: FPGA Manual\"") + SET(DOXYGEN_FPGA_MANUAL_REFERENCE "\\subpage md_fpga \"Part III: FPGA Manual\"") + SET(DOXYGEN_STRIP_EXTRA "${FPGA_SUBMODULE_DIR}/docs") ENDIF(HAS_FPGA_SUBMODULE) message(STATUS ${manual_sources}) CONFIGURE_FILE( diff --git a/host/docs/Doxyfile.in b/host/docs/Doxyfile.in index bca3b71d1..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@ @FPGA_SUBMODULE_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 -- cgit v1.2.3 From 121fbf3795332fb86ac24a4174e707a26265e982 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 12:24:17 -0700 Subject: Updated Images Package for B200 --- host/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 5ae2a3273..75635e415 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -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") #}}} ######################################################################## -- cgit v1.2.3 From b108a919b286431d5d44f343bc9f2fac4bdb58d7 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 12:36:19 -0700 Subject: Updated Images Package for B200 --- host/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index c235ffe82..d41da8d0e 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -268,8 +268,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 "57c06338de0504f296a2431762725683") -SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.008.003-release.zip") +SET(UHD_IMAGES_MD5SUM "3cffe150413380ef74f23137f0157ba6") +SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.008.003-18-g4efa67ff.zip") #}}} ######################################################################## -- cgit v1.2.3 From 15a61a77f499363d64d92e5bb79b0867f66a8f1f Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 12:36:58 -0700 Subject: b200: Fixed compiler warning --- host/lib/usrp/b200/b200_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index d66920bd9..724f5f8b9 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -205,8 +205,8 @@ UHD_STATIC_BLOCK(register_b200_device) * Structors **********************************************************************/ b200_impl::b200_impl(const device_addr_t &device_addr) : - _tick_rate(0.0), // Forces a clock initialization at startup - _revision(0) + _revision(0), + _tick_rate(0.0) // Forces a clock initialization at startup { _tree = property_tree::make(); _type = device::USRP; -- cgit v1.2.3 From dd3e56965ed9f60aee1cb1cc88593fb41bf2bc02 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 12:38:42 -0700 Subject: docs: Removed stray CMake message --- host/docs/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index a73d39356..eb4b67c29 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -55,7 +55,6 @@ IF(ENABLE_MANUAL) SET(DOXYGEN_FPGA_MANUAL_REFERENCE "\\subpage md_fpga \"Part III: FPGA Manual\"") SET(DOXYGEN_STRIP_EXTRA "${FPGA_SUBMODULE_DIR}/docs") ENDIF(HAS_FPGA_SUBMODULE) - message(STATUS ${manual_sources}) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/mainpage.dox.in ${CMAKE_CURRENT_BINARY_DIR}/mainpage.dox -- cgit v1.2.3 From 7af2e970379fb8f58c8afbc99b1498e42698c0a5 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 12:39:42 -0700 Subject: Updated FPGA submodule --- fpga-src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga-src b/fpga-src index 78eab419f..b3e1e8511 160000 --- a/fpga-src +++ b/fpga-src @@ -1 +1 @@ -Subproject commit 78eab419fdcdc18f4da8fd33f267af6c4d0494f6 +Subproject commit b3e1e851146bcf5c7d445b44d26f53c85422c398 -- cgit v1.2.3