diff options
Diffstat (limited to 'host/lib/usrp')
| -rw-r--r-- | host/lib/usrp/CMakeLists.txt | 11 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_image_loader.cpp | 33 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 39 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_impl.hpp | 12 | ||||
| -rw-r--r-- | host/lib/usrp/common/ad936x_manager.cpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/dboard_eeprom_c.cpp | 109 | ||||
| -rw-r--r-- | host/lib/usrp/e300/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | host/lib/usrp/e300/e300_common.cpp | 16 | ||||
| -rw-r--r-- | host/lib/usrp/e300/e300_impl.cpp | 39 | ||||
| -rw-r--r-- | host/lib/usrp/e300/e300_regs.hpp | 62 | ||||
| -rw-r--r-- | host/lib/usrp/e300/e300_remote_codec_ctrl.cpp | 4 | ||||
| -rw-r--r-- | host/lib/usrp/mboard_eeprom_c.cpp | 72 | ||||
| -rw-r--r-- | host/lib/usrp/subdev_spec_c.cpp | 149 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/n200_image_loader.cpp | 80 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_c.cpp | 1523 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_adc_dac_utils.cpp | 6 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_image_loader.cpp | 32 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 33 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_regs.hpp | 67 | 
19 files changed, 2142 insertions, 151 deletions
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index ce913aaf6..e01e5e09d 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -1,5 +1,5 @@  # -# Copyright 2010-2013 Ettus Research LLC +# Copyright 2010-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 @@ -34,6 +34,15 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/subdev_spec.cpp  ) +IF(ENABLE_C_API) +    LIBUHD_APPEND_SOURCES( +        ${CMAKE_CURRENT_SOURCE_DIR}/dboard_eeprom_c.cpp +        ${CMAKE_CURRENT_SOURCE_DIR}/mboard_eeprom_c.cpp +        ${CMAKE_CURRENT_SOURCE_DIR}/subdev_spec_c.cpp +        ${CMAKE_CURRENT_SOURCE_DIR}/usrp_c.cpp +    ) +ENDIF(ENABLE_C_API) +  LIBUHD_REGISTER_COMPONENT("GPSD" ENABLE_GPSD OFF "ENABLE_LIBUHD;ENABLE_GPSD;LIBGPS_FOUND" OFF)  IF(ENABLE_GPSD) diff --git a/host/lib/usrp/b200/b200_image_loader.cpp b/host/lib/usrp/b200/b200_image_loader.cpp index 87010244c..9eaeeff63 100644 --- a/host/lib/usrp/b200/b200_image_loader.cpp +++ b/host/lib/usrp/b200/b200_image_loader.cpp @@ -40,27 +40,50 @@ static b200_iface::sptr get_b200_iface(const image_loader::image_loader_args_t &                                         bool user_specified){      std::vector<usb_device_handle::sptr> dev_handles = get_b200_device_handles(image_loader_args.args); +    std::vector<usb_device_handle::sptr> applicable_dev_handles;      b200_iface::sptr iface; +    mboard_eeprom_t eeprom; // Internal use      if(dev_handles.size() > 0){          BOOST_FOREACH(usb_device_handle::sptr dev_handle, dev_handles){              if(dev_handle->firmware_loaded()){                  iface = b200_iface::make(usb_control::make(dev_handle,0)); -                mb_eeprom = mboard_eeprom_t(*iface, "B200"); +                eeprom = mboard_eeprom_t(*iface, "B200");                  if(user_specified){                      if(image_loader_args.args.has_key("serial") and -                       mb_eeprom.get("serial") != image_loader_args.args.get("serial")){ +                       eeprom.get("serial") != image_loader_args.args.get("serial")){                             continue;                      }                      if(image_loader_args.args.has_key("name") and -                       mb_eeprom.get("name") != image_loader_args.args.get("name")){ +                       eeprom.get("name") != image_loader_args.args.get("name")){                             continue;                      } -                    return iface; +                    applicable_dev_handles.push_back(dev_handle);                  } -                else return iface; // Just return first found +                else applicable_dev_handles.push_back(dev_handle);              }          } + +        // At this point, we should have a single B2XX +        if(applicable_dev_handles.size() == 1){ +            mb_eeprom = eeprom; +            return iface; +        } +        else if(applicable_dev_handles.size() > 1){ +            std::string err_msg = "Could not resolve given args to a single B2XX device.\n" +                                  "Applicable devices:\n"; + +            BOOST_FOREACH(usb_device_handle::sptr dev_handle, applicable_dev_handles){ +                eeprom = mboard_eeprom_t(*b200_iface::make(usb_control::make(dev_handle,0)), "B200"); +                err_msg += str(boost::format(" * %s (serial=%s)\n") +                               % B2X0_STR_NAMES.get(get_b200_type(mb_eeprom), "B2XX") +                               % mb_eeprom.get("serial")); +            } + +            err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + +            throw uhd::runtime_error(err_msg); +         }      }      // No applicable devices found, return empty sptr so we can exit diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index b45529c1a..f5129bc24 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -37,6 +37,8 @@  #include <ctime>  #include <cmath> +#include "../../transport/libusb1_base.hpp" +  using namespace uhd;  using namespace uhd::usrp;  using namespace uhd::transport; @@ -125,8 +127,7 @@ static device_addrs_t b200_find(const device_addr_t &hint)      // so that re-enumeration after fw load can occur successfully.      // This requirement is a courtesy of libusb1.0 on windows.      size_t found = 0; -    std::vector<usb_device_handle::sptr> b200_device_handles = get_b200_device_handles(hint); -    BOOST_FOREACH(usb_device_handle::sptr handle, b200_device_handles) { +    BOOST_FOREACH(usb_device_handle::sptr handle, get_b200_device_handles(hint)) {          //extract the firmware path for the b200          std::string b200_fw_image;          try{ @@ -157,7 +158,7 @@ static device_addrs_t b200_find(const device_addr_t &hint)      //search for the device until found or timeout      while (boost::get_system_time() < timeout_time and b200_addrs.empty() and found != 0)      { -        BOOST_FOREACH(usb_device_handle::sptr handle, b200_device_handles) +        BOOST_FOREACH(usb_device_handle::sptr handle, get_b200_device_handles(hint))          {              usb_control::sptr control;              try{control = usb_control::make(handle, 0);} @@ -195,7 +196,24 @@ static device_addrs_t b200_find(const device_addr_t &hint)   **********************************************************************/  static device::sptr b200_make(const device_addr_t &device_addr)  { -    return device::sptr(new b200_impl(device_addr)); +    uhd::transport::usb_device_handle::sptr handle; + +    // We try twice, because the first time, the link might be in a bad state +    // and we might need to reset the link, but if that didn't help, trying +    // a third time is pointless. +    try { +        return device::sptr(new b200_impl(device_addr, handle)); +    } +    catch (const uhd::usb_error &e) { +        libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( +            boost::static_pointer_cast<libusb::special_handle>(handle)->get_device() +        )); +        dev_handle->clear_endpoints(B200_USB_CTRL_RECV_ENDPOINT, B200_USB_CTRL_SEND_ENDPOINT); +        dev_handle->clear_endpoints(B200_USB_DATA_RECV_ENDPOINT, B200_USB_DATA_SEND_ENDPOINT); +        dev_handle->reset_device(); +    } + +    return device::sptr(new b200_impl(device_addr, handle));  }  UHD_STATIC_BLOCK(register_b200_device) @@ -206,7 +224,7 @@ UHD_STATIC_BLOCK(register_b200_device)  /***********************************************************************   * Structors   **********************************************************************/ -b200_impl::b200_impl(const device_addr_t &device_addr) : +b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::sptr &handle) :      _revision(0),      _tick_rate(0.0) // Forces a clock initialization at startup  { @@ -263,7 +281,6 @@ b200_impl::b200_impl(const device_addr_t &device_addr) :      std::vector<usb_device_handle::sptr> device_list = usb_device_handle::get_device_list(vid_pid_pair_list);      //locate the matching handle in the device list -    usb_device_handle::sptr handle;      BOOST_FOREACH(usb_device_handle::sptr dev_handle, device_list) {          if (dev_handle->get_serial() == device_addr["serial"]){              handle = dev_handle; @@ -361,10 +378,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) :      ctrl_xport_args["send_frame_size"] = min_frame_size;      ctrl_xport_args["num_send_frames"] = "16"; +    // This may throw a uhd::usb_error, which will be caught by b200_make().      _ctrl_transport = usb_zero_copy::make(          handle, -        4, 8, //interface, endpoint -        3, 4, //interface, endpoint +        B200_USB_CTRL_RECV_INTERFACE, B200_USB_CTRL_RECV_ENDPOINT, //interface, endpoint +        B200_USB_CTRL_SEND_INTERFACE, B200_USB_CTRL_SEND_ENDPOINT, //interface, endpoint          ctrl_xport_args      );      while (_ctrl_transport->get_recv_buff(0.0)){} //flush ctrl xport @@ -443,10 +461,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) :      data_xport_args["send_frame_size"] = device_addr.get("send_frame_size", "8192");      data_xport_args["num_send_frames"] = device_addr.get("num_send_frames", "16"); +    // This may throw a uhd::usb_error, which will be caught by b200_make().      _data_transport = usb_zero_copy::make(          handle,        // identifier -        2, 6,          // IN interface, endpoint -        1, 2,          // OUT interface, endpoint +        B200_USB_DATA_RECV_INTERFACE, B200_USB_DATA_RECV_ENDPOINT, //interface, endpoint +        B200_USB_DATA_SEND_INTERFACE, B200_USB_DATA_SEND_ENDPOINT, //interface, endpoint          data_xport_args    // param hints      );      while (_data_transport->get_recv_buff(0.0)){} //flush ctrl xport diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 52ecb98f2..cbd51426d 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -78,6 +78,16 @@ static const boost::uint32_t B200_RX_GPS_UART_SID = FLIP_SID(B200_TX_GPS_UART_SI  static const boost::uint32_t B200_LOCAL_CTRL_SID = 0x00000040;  static const boost::uint32_t B200_LOCAL_RESP_SID = FLIP_SID(B200_LOCAL_CTRL_SID); +static const unsigned char B200_USB_CTRL_RECV_INTERFACE = 4; +static const unsigned char B200_USB_CTRL_RECV_ENDPOINT  = 8; +static const unsigned char B200_USB_CTRL_SEND_INTERFACE = 3; +static const unsigned char B200_USB_CTRL_SEND_ENDPOINT  = 4; + +static const unsigned char B200_USB_DATA_RECV_INTERFACE = 2; +static const unsigned char B200_USB_DATA_RECV_ENDPOINT  = 6; +static const unsigned char B200_USB_DATA_SEND_INTERFACE = 1; +static const unsigned char B200_USB_DATA_SEND_ENDPOINT  = 2; +  /*   * VID/PID pairs for all B2xx products   */ @@ -96,7 +106,7 @@ class b200_impl : public uhd::device  {  public:      //structors -    b200_impl(const uhd::device_addr_t &); +    b200_impl(const uhd::device_addr_t &, uhd::transport::usb_device_handle::sptr &handle);      ~b200_impl(void);      //the io interface diff --git a/host/lib/usrp/common/ad936x_manager.cpp b/host/lib/usrp/common/ad936x_manager.cpp index b060880cd..8c8897803 100644 --- a/host/lib/usrp/common/ad936x_manager.cpp +++ b/host/lib/usrp/common/ad936x_manager.cpp @@ -34,7 +34,7 @@ const uint32_t ad936x_manager::DEFAULT_DECIM  = 128;  const uint32_t ad936x_manager::DEFAULT_INTERP = 128;  const bool     ad936x_manager::DEFAULT_AUTO_DC_OFFSET = true;  const bool     ad936x_manager::DEFAULT_AUTO_IQ_BALANCE = true; -const bool     ad936x_manager::DEFAULT_AGC_ENABLE = true; +const bool     ad936x_manager::DEFAULT_AGC_ENABLE = false;  class ad936x_manager_impl : public ad936x_manager  { diff --git a/host/lib/usrp/dboard_eeprom_c.cpp b/host/lib/usrp/dboard_eeprom_c.cpp new file mode 100644 index 000000000..e3ef4933f --- /dev/null +++ b/host/lib/usrp/dboard_eeprom_c.cpp @@ -0,0 +1,109 @@ +// +// Copyright 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 +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/dboard_eeprom.h> +#include <uhd/error.h> + +#include <boost/lexical_cast.hpp> + +#include <string.h> + +uhd_error uhd_dboard_eeprom_make( +    uhd_dboard_eeprom_handle* h +){ +    UHD_SAFE_C( +        *h = new uhd_dboard_eeprom_t; +    ) +} + +uhd_error uhd_dboard_eeprom_free( +    uhd_dboard_eeprom_handle* h +){ +    UHD_SAFE_C( +        delete *h; +        *h = NULL; +    ) +} + +uhd_error uhd_dboard_eeprom_get_id( +    uhd_dboard_eeprom_handle h, +    char* id_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string dboard_id_cpp = h->dboard_eeprom_cpp.id.to_string(); +        strncpy(id_out, dboard_id_cpp.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_dboard_eeprom_set_id( +    uhd_dboard_eeprom_handle h, +    const char* id +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        h->dboard_eeprom_cpp.id = uhd::usrp::dboard_id_t::from_string(id); +    ) +} + +uhd_error uhd_dboard_eeprom_get_serial( +    uhd_dboard_eeprom_handle h, +    char* id_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string dboard_serial_cpp = h->dboard_eeprom_cpp.serial; +        strncpy(id_out, dboard_serial_cpp.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_dboard_eeprom_set_serial( +    uhd_dboard_eeprom_handle h, +    const char* serial +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        h->dboard_eeprom_cpp.serial = serial; +    ) +} + +uhd_error uhd_dboard_eeprom_get_revision( +    uhd_dboard_eeprom_handle h, +    int* revision_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *revision_out = boost::lexical_cast<int>(h->dboard_eeprom_cpp.revision); +    ) +} + +uhd_error uhd_dboard_eeprom_set_revision( +    uhd_dboard_eeprom_handle h, +    int revision +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        h->dboard_eeprom_cpp.revision = boost::lexical_cast<std::string>(revision); +    ) +} + +uhd_error uhd_dboard_eeprom_last_error( +    uhd_dboard_eeprom_handle h, +    char* error_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C( +        memset(error_out, '\0', strbuffer_len); +        strncpy(error_out, h->last_error.c_str(), strbuffer_len); +    ) +} diff --git a/host/lib/usrp/e300/CMakeLists.txt b/host/lib/usrp/e300/CMakeLists.txt index 26e34294a..ae817c620 100644 --- a/host/lib/usrp/e300/CMakeLists.txt +++ b/host/lib/usrp/e300/CMakeLists.txt @@ -42,14 +42,14 @@ IF(ENABLE_E300)          ${CMAKE_CURRENT_SOURCE_DIR}/e300_remote_codec_ctrl.cpp      )      LIBUHD_APPEND_SOURCES(${E300_SOURCES}) -    IF(UDEV_FOUND) +    IF(UDEV_FOUND AND NOT E300_FORCE_NETWORK)          INCLUDE_DIRECTORIES(${UDEV_INCLUDE_DIR})          LIBUHD_APPEND_LIBS(${UDEV_LIBS})          SET_SOURCE_FILES_PROPERTIES(              ${E300_SOURCES}              PROPERTIES COMPILE_DEFINITIONS "E300_NATIVE=1"          ) -    ENDIF(UDEV_FOUND) +    ENDIF(UDEV_FOUND AND NOT E300_FORCE_NETWORK)      IF(ENABLE_GPSD)          SET_SOURCE_FILES_PROPERTIES( diff --git a/host/lib/usrp/e300/e300_common.cpp b/host/lib/usrp/e300/e300_common.cpp index 29117e21f..216713bc6 100644 --- a/host/lib/usrp/e300/e300_common.cpp +++ b/host/lib/usrp/e300/e300_common.cpp @@ -29,6 +29,7 @@  #include <fstream>  #include <string> +#ifdef E300_NATIVE  namespace uhd { namespace usrp { namespace e300 {  namespace common { @@ -90,3 +91,18 @@ UHD_STATIC_BLOCK(register_e300_image_loader) {  }  }}} + +#else +namespace uhd { namespace usrp { namespace e300 { + +namespace common { + +void load_fpga_image(const std::string&) +{ +    throw uhd::assertion_error("load_fpga_image() !E300_NATIVE"); +} + +} + +}}} +#endif diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index 6eb63c786..5bef783f6 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -505,14 +505,14 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)          this->_setup_radio(instance);      // Radio 0 loopback through AD9361 -    _codec_mgr->loopback_self_test(_radio_perifs[0].ctrl, TOREG(SR_CODEC_IDLE), RB64_CODEC_READBACK); +    _codec_mgr->loopback_self_test(_radio_perifs[0].ctrl, radio::sr_addr(radio::CODEC_IDLE), radio::RB64_CODEC_READBACK);      // Radio 1 loopback through AD9361 -    _codec_mgr->loopback_self_test(_radio_perifs[1].ctrl, TOREG(SR_CODEC_IDLE), RB64_CODEC_READBACK); +    _codec_mgr->loopback_self_test(_radio_perifs[1].ctrl, radio::sr_addr(radio::CODEC_IDLE), radio::RB64_CODEC_READBACK);      ////////////////////////////////////////////////////////////////////      // internal gpios      //////////////////////////////////////////////////////////////////// -    gpio_core_200::sptr fp_gpio = gpio_core_200::make(_radio_perifs[0].ctrl, TOREG(SR_FP_GPIO), RB32_FP_GPIO); +    gpio_core_200::sptr fp_gpio = gpio_core_200::make(_radio_perifs[0].ctrl, radio::sr_addr(radio::FP_GPIO), radio::RB32_FP_GPIO);      BOOST_FOREACH(const gpio_attr_map_t::value_type attr, gpio_attr_map)      {          _tree->create<boost::uint32_t>(mb_path / "gpio" / "INT0" / attr.second) @@ -749,8 +749,8 @@ void e300_impl::_register_loopback_self_test(wb_iface::sptr iface)      for (size_t i = 0; i < 100; i++)      {          boost::hash_combine(hash, i); -        iface->poke32(TOREG(SR_TEST), boost::uint32_t(hash)); -        test_fail = iface->peek32(RB32_TEST) != boost::uint32_t(hash); +        iface->poke32(radio::sr_addr(radio::TEST), boost::uint32_t(hash)); +        test_fail = iface->peek32(radio::RB32_TEST) != boost::uint32_t(hash);          if (test_fail) break; //exit loop on any failure      }      UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl; @@ -998,20 +998,20 @@ void e300_impl::_setup_radio(const size_t dspno)      ////////////////////////////////////////////////////////////////////      // Set up peripherals      //////////////////////////////////////////////////////////////////// -    perif.atr = gpio_core_200_32wo::make(perif.ctrl, TOREG(SR_GPIO)); -    perif.rx_fe = rx_frontend_core_200::make(perif.ctrl, TOREG(SR_RX_FRONT)); +    perif.atr = gpio_core_200_32wo::make(perif.ctrl, radio::sr_addr(radio::GPIO)); +    perif.rx_fe = rx_frontend_core_200::make(perif.ctrl, radio::sr_addr(radio::RX_FRONT));      perif.rx_fe->set_dc_offset(rx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE);      perif.rx_fe->set_dc_offset_auto(rx_frontend_core_200::DEFAULT_DC_OFFSET_ENABLE);      perif.rx_fe->set_iq_balance(rx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); -    perif.tx_fe = tx_frontend_core_200::make(perif.ctrl, TOREG(SR_TX_FRONT)); +    perif.tx_fe = tx_frontend_core_200::make(perif.ctrl, radio::sr_addr(radio::TX_FRONT));      perif.tx_fe->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE);      perif.tx_fe->set_iq_balance(tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); -    perif.framer = rx_vita_core_3000::make(perif.ctrl, TOREG(SR_RX_CTRL)); -    perif.ddc = rx_dsp_core_3000::make(perif.ctrl, TOREG(SR_RX_DSP)); +    perif.framer = rx_vita_core_3000::make(perif.ctrl, radio::sr_addr(radio::RX_CTRL)); +    perif.ddc = rx_dsp_core_3000::make(perif.ctrl, radio::sr_addr(radio::RX_DSP));      perif.ddc->set_link_rate(10e9/8); //whatever      perif.ddc->set_freq(e300::DEFAULT_DDC_FREQ); -    perif.deframer = tx_vita_core_3000::make(perif.ctrl, TOREG(SR_TX_CTRL)); -    perif.duc = tx_dsp_core_3000::make(perif.ctrl, TOREG(SR_TX_DSP)); +    perif.deframer = tx_vita_core_3000::make(perif.ctrl, radio::sr_addr(radio::TX_CTRL)); +    perif.duc = tx_dsp_core_3000::make(perif.ctrl, radio::sr_addr(radio::TX_DSP));      perif.duc->set_link_rate(10e9/8); //whatever      perif.duc->set_freq(e300::DEFAULT_DUC_FREQ); @@ -1019,9 +1019,9 @@ void e300_impl::_setup_radio(const size_t dspno)      // create time control objects      ////////////////////////////////////////////////////////////////////      time_core_3000::readback_bases_type time64_rb_bases; -    time64_rb_bases.rb_now = RB64_TIME_NOW; -    time64_rb_bases.rb_pps = RB64_TIME_PPS; -    perif.time64 = time_core_3000::make(perif.ctrl, TOREG(SR_TIME), time64_rb_bases); +    time64_rb_bases.rb_now = radio::RB64_TIME_NOW; +    time64_rb_bases.rb_pps = radio::RB64_TIME_PPS; +    perif.time64 = time_core_3000::make(perif.ctrl, radio::sr_addr(radio::TIME), time64_rb_bases);      ////////////////////////////////////////////////////////////////////      // front end corrections @@ -1074,12 +1074,9 @@ void e300_impl::_setup_radio(const size_t dspno)          _tree->create<sensor_value_t>(rf_fe_path / "sensors" / "lo_locked")              .publish(boost::bind(&e300_impl::_get_fe_pll_lock, this, dir == TX_DIRECTION))          ; - -        // Network mode currently doesn't support the filter API, so -        // prevent it from using it: -        if (_xport_path != AXI) { -            _tree->remove(rf_fe_path / "filters"); -        } +        _tree->access<double>(rf_fe_path / "freq" / "value") +            .subscribe(boost::bind(&e300_impl::_update_fe_lo_freq, this, key, _1)) +        ;          // Antenna Setup          if (dir == RX_DIRECTION) { diff --git a/host/lib/usrp/e300/e300_regs.hpp b/host/lib/usrp/e300/e300_regs.hpp index 5736ebfd4..846c759a4 100644 --- a/host/lib/usrp/e300/e300_regs.hpp +++ b/host/lib/usrp/e300/e300_regs.hpp @@ -18,36 +18,48 @@  #ifndef INCLUDED_E300_REGS_HPP  #define INCLUDED_E300_REGS_HPP -#include <boost/cstdint.hpp> +#include <stdint.h> +#include <uhd/config.hpp> -#define TOREG(x) ((x)*4) +namespace uhd { namespace usrp { namespace e300 { namespace radio { -#define localparam static const int +static UHD_INLINE uint32_t sr_addr(const uint32_t offset) +{ +    return offset * 4; +} + +static const uint32_t DACSYNC    = 5; +static const uint32_t LOOPBACK   = 6; +static const uint32_t TEST       = 7; +static const uint32_t SPI        = 8; +static const uint32_t GPIO       = 16; +static const uint32_t MISC_OUTS  = 24; +static const uint32_t READBACK   = 32; +static const uint32_t TX_CTRL    = 64; +static const uint32_t RX_CTRL    = 96; +static const uint32_t TIME       = 128; +static const uint32_t RX_DSP     = 144; +static const uint32_t TX_DSP     = 184; +static const uint32_t LEDS       = 195; +static const uint32_t FP_GPIO    = 200; +static const uint32_t RX_FRONT   = 208; +static const uint32_t TX_FRONT   = 216; +static const uint32_t CODEC_IDLE = 250; -localparam SR_TEST       = 7; -localparam SR_SPI        = 8; -localparam SR_GPIO       = 16; -localparam SR_MISC_OUTS  = 24; -localparam SR_READBACK   = 32; -localparam SR_TX_CTRL    = 64; -localparam SR_RX_CTRL    = 96; -localparam SR_TIME       = 128; -localparam SR_RX_DSP     = 144; -localparam SR_TX_DSP     = 184; -localparam SR_LEDS       = 195; -localparam SR_FP_GPIO    = 200; -localparam SR_RX_FRONT   = 208; -localparam SR_TX_FRONT   = 216; -localparam SR_CODEC_IDLE = 250; +static const uint32_t RB32_GPIO            = 0; +static const uint32_t RB32_SPI             = 4; +static const uint32_t RB64_TIME_NOW        = 8; +static const uint32_t RB64_TIME_PPS        = 16; +static const uint32_t RB32_TEST            = 24; +static const uint32_t RB32_RX              = 28; +static const uint32_t RB32_FP_GPIO         = 32; +static const uint32_t RB32_MISC_INS        = 36; +static const uint32_t RB64_CODEC_READBACK  = 40; +static const uint32_t RB32_RADIO_NUM       = 48; +}}}} // namespace -localparam RB32_SPI             = 4; -localparam RB64_TIME_NOW        = 8; -localparam RB64_TIME_PPS        = 16; -localparam RB32_TEST            = 24; -localparam RB32_FP_GPIO         = 32; -localparam RB64_CODEC_READBACK  = 40; -localparam RB32_RADIO_NUM       = 48; +#define localparam static const int  localparam ST_RX_ENABLE = 20;  localparam ST_TX_ENABLE = 19; diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp index 9708634dd..1e0895393 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp @@ -227,7 +227,7 @@ public:      //! List all available filters by name      std::vector<std::string> get_filter_names(const std::string &)      { -        UHD_THROW_INVALID_CODE_PATH(); +        return std::vector<std::string>();      }      //! Return a list of all filters @@ -239,7 +239,7 @@ public:      //! Write back a filter      void set_filter(const std::string &, const std::string &, const filter_info_base::sptr)      { -        UHD_THROW_INVALID_CODE_PATH(); +        UHD_MSG(warning) << "Attempting to set filter on E300 in network mode." << std::endl;      }  private: diff --git a/host/lib/usrp/mboard_eeprom_c.cpp b/host/lib/usrp/mboard_eeprom_c.cpp new file mode 100644 index 000000000..8d5c069b9 --- /dev/null +++ b/host/lib/usrp/mboard_eeprom_c.cpp @@ -0,0 +1,72 @@ +// +// Copyright 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 +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/mboard_eeprom.h> + +#include <uhd/exception.hpp> + +#include <string.h> + +uhd_error uhd_mboard_eeprom_make( +    uhd_mboard_eeprom_handle* h +){ +    UHD_SAFE_C( +        *h = new uhd_mboard_eeprom_t; +    ) +} + +uhd_error uhd_mboard_eeprom_free( +    uhd_mboard_eeprom_handle* h +){ +    UHD_SAFE_C( +        delete *h; +        *h = NULL; +    ) +} + +uhd_error uhd_mboard_eeprom_get_value( +    uhd_mboard_eeprom_handle h, +    const char* key, +    char* value_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string value_cpp = h->mboard_eeprom_cpp.get(key); +        strncpy(value_out, value_cpp.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_mboard_eeprom_set_value( +    uhd_mboard_eeprom_handle h, +    const char* key, +    const char* value +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        h->mboard_eeprom_cpp[key] = value; +    ) +} + +uhd_error uhd_mboard_eeprom_last_error( +    uhd_mboard_eeprom_handle h, +    char* error_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C( +        memset(error_out, '\0', strbuffer_len); +        strncpy(error_out, h->last_error.c_str(), strbuffer_len); +    ) +} diff --git a/host/lib/usrp/subdev_spec_c.cpp b/host/lib/usrp/subdev_spec_c.cpp new file mode 100644 index 000000000..2c9c20506 --- /dev/null +++ b/host/lib/usrp/subdev_spec_c.cpp @@ -0,0 +1,149 @@ +// +// Copyright 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 +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/subdev_spec.h> + +#include <string.h> + +uhd_error uhd_subdev_spec_pair_free( +    uhd_subdev_spec_pair_t *subdev_spec_pair +){ +    UHD_SAFE_C( +        if(subdev_spec_pair->db_name){ +            free(subdev_spec_pair->db_name); +            subdev_spec_pair->db_name = NULL; +        } +        if(subdev_spec_pair->sd_name){ +            free(subdev_spec_pair->sd_name); +            subdev_spec_pair->sd_name = NULL; +        } +    ) +} + +uhd_error uhd_subdev_spec_pairs_equal( +    const uhd_subdev_spec_pair_t* first, +    const uhd_subdev_spec_pair_t* second, +    bool *result_out +){ +    UHD_SAFE_C( +        *result_out = (uhd_subdev_spec_pair_c_to_cpp(first) == +                       uhd_subdev_spec_pair_c_to_cpp(second)); +    ) +} + +uhd_error uhd_subdev_spec_make( +    uhd_subdev_spec_handle* h, +    const char* markup +){ +    UHD_SAFE_C( +        (*h) = new uhd_subdev_spec_t; +        std::string markup_cpp(markup); +        if(!markup_cpp.empty()){ +            (*h)->subdev_spec_cpp = uhd::usrp::subdev_spec_t(markup_cpp); +        } +    ) +} + +uhd_error uhd_subdev_spec_free( +    uhd_subdev_spec_handle* h +){ +    UHD_SAFE_C( +        delete (*h); +        (*h) = NULL; +    ) +} + +uhd_error uhd_subdev_spec_size( +    uhd_subdev_spec_handle h, +    size_t *size_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *size_out = h->subdev_spec_cpp.size(); +    ) +} + +uhd_error uhd_subdev_spec_push_back( +    uhd_subdev_spec_handle h, +    const char* markup +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        h->subdev_spec_cpp.push_back(uhd::usrp::subdev_spec_pair_t(markup)); +    ) +} + +uhd_error uhd_subdev_spec_at( +    uhd_subdev_spec_handle h, +    size_t num, +    uhd_subdev_spec_pair_t *subdev_spec_pair_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd_subdev_spec_pair_cpp_to_c( +            h->subdev_spec_cpp.at(num), +            subdev_spec_pair_out +        ); +    ) +} + +uhd_error uhd_subdev_spec_to_pp_string( +    uhd_subdev_spec_handle h, +    char* pp_string_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string pp_string_cpp = h->subdev_spec_cpp.to_pp_string(); +        memset(pp_string_out, '\0', strbuffer_len); +        strncpy(pp_string_out, pp_string_cpp.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_subdev_spec_to_string( +    uhd_subdev_spec_handle h, +    char* string_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string string_cpp = h->subdev_spec_cpp.to_string(); +        memset(string_out, '\0', strbuffer_len); +        strncpy(string_out, string_cpp.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_subdev_spec_last_error( +    uhd_subdev_spec_handle h, +    char* error_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C( +        memset(error_out, '\0', strbuffer_len); +        strncpy(error_out, h->last_error.c_str(), strbuffer_len); +    ) +} + +uhd::usrp::subdev_spec_pair_t uhd_subdev_spec_pair_c_to_cpp( +    const uhd_subdev_spec_pair_t *subdev_spec_pair_c +){ +    return uhd::usrp::subdev_spec_pair_t(subdev_spec_pair_c->db_name, +                                         subdev_spec_pair_c->sd_name); +} + +void uhd_subdev_spec_pair_cpp_to_c( +    const uhd::usrp::subdev_spec_pair_t &subdev_spec_pair_cpp, +    uhd_subdev_spec_pair_t *subdev_spec_pair_c +){ +    subdev_spec_pair_c->db_name = strdup(subdev_spec_pair_cpp.db_name.c_str()); +    subdev_spec_pair_c->sd_name = strdup(subdev_spec_pair_cpp.sd_name.c_str()); +} diff --git a/host/lib/usrp/usrp2/n200_image_loader.cpp b/host/lib/usrp/usrp2/n200_image_loader.cpp index ce956c22c..29bec8b4a 100644 --- a/host/lib/usrp/usrp2/n200_image_loader.cpp +++ b/host/lib/usrp/usrp2/n200_image_loader.cpp @@ -210,36 +210,62 @@ static uhd::device_addr_t n200_find(const image_loader::image_loader_args_t &ima                            image_loader_args.args.has_key("name");      uhd::device_addrs_t found = usrp2_find(image_loader_args.args); -    if(found.size() > 0){ -        uhd::device_addr_t ret = found[0]; - -        /* -         * Make sure the device found is an N-Series and not a USRP2. A USRP2 -         * will not respond to this query. If the user supplied specific -         * arguments that led to a USRP2, throw an error. -         */ -        udp_simple::sptr rev_xport = udp_simple::make_connected( -                                         ret["addr"], -                                         BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT) -                                     ); +    if(found.size() > 0){ +        uhd::device_addrs_t n200_found; +        udp_simple::sptr rev_xport;          n200_fw_update_data_t pkt_out;          boost::uint8_t data_in[udp_simple::mtu];          const n200_fw_update_data_t *pkt_in = reinterpret_cast<const n200_fw_update_data_t*>(data_in); +        size_t len = 0; -        size_t len = n200_send_and_recv(rev_xport, GET_HW_REV_CMD, &pkt_out, data_in); -        if(n200_response_matches(pkt_in, GET_HW_REV_ACK, len)){ -            boost::uint32_t rev = ntohl(pkt_in->data.hw_rev); -            ret["hw_rev"] = n200_filename_map.get(rev, "n2xx"); -            return ret; +        /* +         * Filter out any USRP2 devices by sending a query over the +         * UDP update port. Only N-Series devices will respond to +         * this query. If the user supplied specific arguments that +         * led to a USRP2, throw an error. +         */ +        BOOST_FOREACH(const uhd::device_addr_t &dev, found){ +            rev_xport = udp_simple::make_connected( +                            dev.get("addr"), +                            BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT) +                        ); + +            len = n200_send_and_recv(rev_xport, GET_HW_REV_CMD, &pkt_out, data_in); +            if(n200_response_matches(pkt_in, GET_HW_REV_ACK, len)){ +                boost::uint32_t rev = ntohl(pkt_in->data.hw_rev); +                std::string hw_rev = n200_filename_map.get(rev, "n2xx"); + +                n200_found.push_back(dev); +                n200_found[n200_found.size()-1]["hw_rev"] = hw_rev; +            } +            else if(len > offsetof(n200_fw_update_data_t, data) and ntohl(pkt_in->id) != GET_HW_REV_ACK){ +                throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.") +                                             % ntohl(pkt_in->id))); +            } +            else if(user_specified){ +                // At this point, we haven't received any response, so assume it's a USRP2 +                print_usrp2_error(image_loader_args); +            }          } -        else if(len > offsetof(n200_fw_update_data_t, data) and ntohl(pkt_in->id) != GET_HW_REV_ACK){ -            throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.") -                                         % ntohl(pkt_in->id))); + +        // At this point, we should have a single N-Series device +        if(n200_found.size() == 1){ +            return n200_found[0];          } -        else if(user_specified){ -            // At this point, we haven't received any response, so assume it's a USRP2 -            print_usrp2_error(image_loader_args); +        else if(n200_found.size() > 1){ +            std::string err_msg = "Could not resolve given args to a single N-Series device.\n" +                                  "Applicable devices:\n"; + +            BOOST_FOREACH(const uhd::device_addr_t &dev, n200_found){ +                err_msg += str(boost::format("* %s (addr=%s)\n") +                               % dev.get("hw_rev") +                               % dev.get("addr")); +            } + +            err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + +            throw uhd::runtime_error(err_msg);          }      } @@ -259,7 +285,7 @@ static void n200_validate_firmware_image(n200_session_t &session){      session.max_size = N200_FW_MAX_SIZE_BYTES;      if(session.size > session.max_size){ -        throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d") +        throw uhd::runtime_error(str(boost::format("The specified firmware image is too large: %d vs. %d")                                       % session.size % session.max_size));      } @@ -559,11 +585,15 @@ static std::string nice_name(const std::string &fw_rev){  }  static bool n200_image_loader(const image_loader::image_loader_args_t &image_loader_args){ +    if(!image_loader_args.load_firmware and !image_loader_args.load_fpga){ +        return false; +    } +      // See if any N2x0 with the given args is found      // This will throw if specific args lead to a USRP2      n200_session_t session;      session.dev_addr = n200_find(image_loader_args); -    if(session.dev_addr.size() == 0 or (!image_loader_args.load_firmware and !image_loader_args.load_fpga)){ +    if(session.dev_addr.size() == 0){          return false;      } diff --git a/host/lib/usrp/usrp_c.cpp b/host/lib/usrp/usrp_c.cpp new file mode 100644 index 000000000..829014829 --- /dev/null +++ b/host/lib/usrp/usrp_c.cpp @@ -0,0 +1,1523 @@ +/* + * Copyright 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +/* C-Interface for multi_usrp */ + +#include <uhd/utils/static.hpp> +#include <uhd/usrp/multi_usrp.hpp> + +#include <uhd/error.h> +#include <uhd/usrp/usrp.h> + +#include <boost/foreach.hpp> +#include <boost/thread/mutex.hpp> + +#include <string.h> +#include <map> + +/**************************************************************************** + * Helpers + ***************************************************************************/ +uhd::stream_args_t stream_args_c_to_cpp(const uhd_stream_args_t *stream_args_c) +{ +    std::string otw_format(stream_args_c->otw_format); +    std::string cpu_format(stream_args_c->cpu_format); +    std::string args(stream_args_c->args); +    std::vector<size_t> channels(stream_args_c->channel_list, stream_args_c->channel_list + stream_args_c->n_channels); + +    uhd::stream_args_t stream_args_cpp(cpu_format, otw_format); +    stream_args_cpp.args = args; +    stream_args_cpp.channels = channels; + +    return stream_args_cpp; +} + +uhd::stream_cmd_t stream_cmd_c_to_cpp(const uhd_stream_cmd_t *stream_cmd_c) +{ +    uhd::stream_cmd_t stream_cmd_cpp(uhd::stream_cmd_t::stream_mode_t(stream_cmd_c->stream_mode)); +    stream_cmd_cpp.num_samps   = stream_cmd_c->num_samps; +    stream_cmd_cpp.stream_now  = stream_cmd_c->stream_now; +    stream_cmd_cpp.time_spec   = uhd::time_spec_t(stream_cmd_c->time_spec_full_secs, stream_cmd_c->time_spec_frac_secs); +    return stream_cmd_cpp; +} + +/**************************************************************************** + * Registry / Pointer Management + ***************************************************************************/ +/* Public structs */ +struct uhd_usrp { +    size_t usrp_index; +    std::string last_error; +}; + +struct uhd_tx_streamer { +    size_t usrp_index; +    size_t streamer_index; +    std::string last_error; +}; + +struct uhd_rx_streamer { +    size_t usrp_index; +    size_t streamer_index; +    std::string last_error; +}; + +/* Not public: We use this for our internal registry */ +struct usrp_ptr { +    uhd::usrp::multi_usrp::sptr ptr; +    std::vector< uhd::rx_streamer::sptr > rx_streamers; +    std::vector< uhd::tx_streamer::sptr > tx_streamers; +    static size_t usrp_counter; +}; +size_t usrp_ptr::usrp_counter = 0; +typedef struct usrp_ptr usrp_ptr; +/* Prefer map, because the list can be discontiguous */ +typedef std::map<size_t, usrp_ptr> usrp_ptrs; + +UHD_SINGLETON_FCN(usrp_ptrs, get_usrp_ptrs); +/* Shortcut for accessing the underlying USRP sptr from a uhd_usrp_handle* */ +#define USRP(h_ptr) (get_usrp_ptrs()[h_ptr->usrp_index].ptr) +#define RX_STREAMER(h_ptr) (get_usrp_ptrs()[h_ptr->usrp_index].rx_streamers[h_ptr->streamer_index]) +#define TX_STREAMER(h_ptr) (get_usrp_ptrs()[h_ptr->usrp_index].tx_streamers[h_ptr->streamer_index]) + +/**************************************************************************** + * RX Streamer + ***************************************************************************/ +static boost::mutex _rx_streamer_make_mutex; +uhd_error uhd_rx_streamer_make(uhd_rx_streamer_handle* h){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock(_rx_streamer_make_mutex); +        (*h) = new uhd_rx_streamer; +    ) +} + +static boost::mutex _rx_streamer_free_mutex; +uhd_error uhd_rx_streamer_free(uhd_rx_streamer_handle* h){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock lock(_rx_streamer_free_mutex); +        delete (*h); +        (*h) = NULL; +    ) +} + +uhd_error uhd_rx_streamer_num_channels(uhd_rx_streamer_handle h, +                                       size_t *num_channels_out){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *num_channels_out = RX_STREAMER(h)->get_num_channels(); +    ) +} + +uhd_error uhd_rx_streamer_max_num_samps(uhd_rx_streamer_handle h, +                                        size_t *max_num_samps_out){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *max_num_samps_out = RX_STREAMER(h)->get_max_num_samps(); +    ) +} + +uhd_error uhd_rx_streamer_recv( +    uhd_rx_streamer_handle h, +    void **buffs, +    size_t samps_per_buff, +    uhd_rx_metadata_handle md, +    double timeout, +    bool one_packet, +    size_t *items_recvd +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::rx_streamer::buffs_type buffs_cpp(buffs, RX_STREAMER(h)->get_num_channels()); +        *items_recvd = RX_STREAMER(h)->recv(buffs_cpp, samps_per_buff, md->rx_metadata_cpp, timeout, one_packet); +    ) +} + +uhd_error uhd_rx_streamer_issue_stream_cmd( +    uhd_rx_streamer_handle h, +    const uhd_stream_cmd_t *stream_cmd +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        RX_STREAMER(h)->issue_stream_cmd(stream_cmd_c_to_cpp(stream_cmd)); +    ) +} + +uhd_error uhd_rx_streamer_last_error( +    uhd_rx_streamer_handle h, +    char* error_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        memset(error_out, '\0', strbuffer_len); +        strncpy(error_out, h->last_error.c_str(), strbuffer_len); +    ) +} + +/**************************************************************************** + * TX Streamer + ***************************************************************************/ +static boost::mutex _tx_streamer_make_mutex; +uhd_error uhd_tx_streamer_make( +    uhd_tx_streamer_handle* h +){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock lock(_tx_streamer_make_mutex); +        (*h) = new uhd_tx_streamer; +    ) +} + +static boost::mutex _tx_streamer_free_mutex; +uhd_error uhd_tx_streamer_free( +    uhd_tx_streamer_handle* h +){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock lock(_tx_streamer_free_mutex); +        delete *h; +        *h = NULL; +    ) +} + +uhd_error uhd_tx_streamer_num_channels( +    uhd_tx_streamer_handle h, +    size_t *num_channels_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *num_channels_out = TX_STREAMER(h)->get_num_channels(); +    ) +} + +uhd_error uhd_tx_streamer_max_num_samps( +    uhd_tx_streamer_handle h, +    size_t *max_num_samps_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *max_num_samps_out = TX_STREAMER(h)->get_max_num_samps(); +    ) +} + +uhd_error uhd_tx_streamer_send( +    uhd_tx_streamer_handle h, +    const void **buffs, +    const size_t samps_per_buff, +    const uhd_tx_metadata_handle md, +    const double timeout, +    size_t *items_sent +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::tx_streamer::buffs_type buffs_cpp(buffs, TX_STREAMER(h)->get_num_channels()); +        *items_sent = TX_STREAMER(h)->send( +            buffs_cpp, +            samps_per_buff, +            md->tx_metadata_cpp, +            timeout +        ); +    ) +} + +uhd_error uhd_tx_streamer_recv_async_msg( +    uhd_tx_streamer_handle h, +    uhd_async_metadata_handle md, +    const double timeout, +    bool *valid +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *valid = TX_STREAMER(h)->recv_async_msg(md->async_metadata_cpp, timeout); +    ) +} + +uhd_error uhd_tx_streamer_last_error( +    uhd_tx_streamer_handle h, +    char* error_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C( +        memset(error_out, '\0', strbuffer_len); +        strncpy(error_out, h->last_error.c_str(), strbuffer_len); +    ) +} + +/**************************************************************************** + * Generate / Destroy API calls + ***************************************************************************/ +static boost::mutex _usrp_find_mutex; +uhd_error uhd_usrp_find( +    uhd_device_addrs_handle h, +    const char* args, +    size_t *num_found +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        boost::mutex::scoped_lock _lock(_usrp_find_mutex); + +        h->device_addrs_cpp = uhd::device::find(std::string(args), uhd::device::USRP); +        *num_found = h->device_addrs_cpp.size(); +    ) +} + +static boost::mutex _usrp_make_mutex; +uhd_error uhd_usrp_make( +    uhd_usrp_handle *h, +    const char *args +){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock lock(_usrp_make_mutex); + +        size_t usrp_count = usrp_ptr::usrp_counter; +        usrp_ptr::usrp_counter++; + +        // Initialize USRP +        uhd::device_addr_t device_addr(args); +        usrp_ptr P; +        P.ptr = uhd::usrp::multi_usrp::make(device_addr); + +        // Dump into registry +        get_usrp_ptrs()[usrp_count] = P; + +        // Update handle +        (*h) = new uhd_usrp; +        (*h)->usrp_index = usrp_count; +    ) +} + +static boost::mutex _usrp_free_mutex; +uhd_error uhd_usrp_free( +    uhd_usrp_handle *h +){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock lock(_usrp_free_mutex); + +        if(!get_usrp_ptrs().count((*h)->usrp_index)){ +            return UHD_ERROR_INVALID_DEVICE; +        } + +        get_usrp_ptrs().erase((*h)->usrp_index); +        delete *h; +        *h = NULL; +    ) +} + +uhd_error uhd_usrp_last_error( +    uhd_usrp_handle h, +    char* error_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C( +        memset(error_out, '\0', strbuffer_len); +        strncpy(error_out, h->last_error.c_str(), strbuffer_len); +    ) +} + +static boost::mutex _usrp_get_rx_stream_mutex; +uhd_error uhd_usrp_get_rx_stream( +    uhd_usrp_handle h_u, +    uhd_stream_args_t *stream_args, +    uhd_rx_streamer_handle h_s +){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock lock(_usrp_get_rx_stream_mutex); + +        if(!get_usrp_ptrs().count(h_u->usrp_index)){ +            return UHD_ERROR_INVALID_DEVICE; +        } + +        usrp_ptr &usrp = get_usrp_ptrs()[h_u->usrp_index]; +        usrp.rx_streamers.push_back( +            usrp.ptr->get_rx_stream(stream_args_c_to_cpp(stream_args)) +        ); +        h_s->usrp_index     = h_u->usrp_index; +        h_s->streamer_index = usrp.rx_streamers.size() - 1; +    ) +} + +static boost::mutex _usrp_get_tx_stream_mutex; +uhd_error uhd_usrp_get_tx_stream( +    uhd_usrp_handle h_u, +    uhd_stream_args_t *stream_args, +    uhd_tx_streamer_handle h_s +){ +    UHD_SAFE_C( +        boost::mutex::scoped_lock lock(_usrp_get_tx_stream_mutex); + +        if(!get_usrp_ptrs().count(h_u->usrp_index)){ +            return UHD_ERROR_INVALID_DEVICE; +        } + +        usrp_ptr &usrp = get_usrp_ptrs()[h_u->usrp_index]; +        usrp.tx_streamers.push_back( +            usrp.ptr->get_tx_stream(stream_args_c_to_cpp(stream_args)) +        ); +        h_s->usrp_index     = h_u->usrp_index; +        h_s->streamer_index = usrp.tx_streamers.size() - 1; +    ) +} + +/**************************************************************************** + * multi_usrp API calls + ***************************************************************************/ + +#define COPY_INFO_FIELD(out, dict, field) \ +    out->field = strdup(dict.get(BOOST_STRINGIZE(field)).c_str()) + +uhd_error uhd_usrp_get_rx_info( +    uhd_usrp_handle h, +    size_t chan, +    uhd_usrp_rx_info_t *info_out +) { +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::dict<std::string, std::string> rx_info = USRP(h)->get_usrp_rx_info(chan); + +        COPY_INFO_FIELD(info_out, rx_info, mboard_id); +        COPY_INFO_FIELD(info_out, rx_info, mboard_serial); +        COPY_INFO_FIELD(info_out, rx_info, rx_id); +        COPY_INFO_FIELD(info_out, rx_info, rx_subdev_name); +        COPY_INFO_FIELD(info_out, rx_info, rx_subdev_spec); +        COPY_INFO_FIELD(info_out, rx_info, rx_serial); +        COPY_INFO_FIELD(info_out, rx_info, rx_antenna); +    ) +} + +uhd_error uhd_usrp_get_tx_info( +    uhd_usrp_handle h, +    size_t chan, +    uhd_usrp_tx_info_t *info_out +) { +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::dict<std::string, std::string> tx_info = USRP(h)->get_usrp_tx_info(chan); + +        COPY_INFO_FIELD(info_out, tx_info, mboard_id); +        COPY_INFO_FIELD(info_out, tx_info, mboard_serial); +        COPY_INFO_FIELD(info_out, tx_info, tx_id); +        COPY_INFO_FIELD(info_out, tx_info, tx_subdev_name); +        COPY_INFO_FIELD(info_out, tx_info, tx_subdev_spec); +        COPY_INFO_FIELD(info_out, tx_info, tx_serial); +        COPY_INFO_FIELD(info_out, tx_info, tx_antenna); +    ) +} + +/**************************************************************************** + * Motherboard methods + ***************************************************************************/ +uhd_error uhd_usrp_set_master_clock_rate( +    uhd_usrp_handle h, +    double rate, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_master_clock_rate(rate, mboard); +    ) +} + +uhd_error uhd_usrp_get_master_clock_rate( +    uhd_usrp_handle h, +    size_t mboard, +    double *clock_rate_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *clock_rate_out = USRP(h)->get_master_clock_rate(mboard); +    ) +} + +uhd_error uhd_usrp_get_pp_string( +    uhd_usrp_handle h, +    char* pp_string_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        strncpy(pp_string_out, USRP(h)->get_pp_string().c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_get_mboard_name( +    uhd_usrp_handle h, +    size_t mboard, +    char* mboard_name_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        strncpy(mboard_name_out, USRP(h)->get_mboard_name(mboard).c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_get_time_now( +    uhd_usrp_handle h, +    size_t mboard, +    time_t *full_secs_out, +    double *frac_secs_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::time_spec_t time_spec_cpp = USRP(h)->get_time_now(mboard); +        *full_secs_out = time_spec_cpp.get_full_secs(); +        *frac_secs_out = time_spec_cpp.get_frac_secs(); +    ) +} + +uhd_error uhd_usrp_get_time_last_pps( +    uhd_usrp_handle h, +    size_t mboard, +    time_t *full_secs_out, +    double *frac_secs_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::time_spec_t time_spec_cpp = USRP(h)->get_time_last_pps(mboard); +        *full_secs_out = time_spec_cpp.get_full_secs(); +        *frac_secs_out = time_spec_cpp.get_frac_secs(); +    ) +} + +uhd_error uhd_usrp_set_time_now( +    uhd_usrp_handle h, +    time_t full_secs, +    double frac_secs, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::time_spec_t time_spec_cpp(full_secs, frac_secs); +        USRP(h)->set_time_now(time_spec_cpp, mboard); +    ) +} + +uhd_error uhd_usrp_set_time_next_pps( +    uhd_usrp_handle h, +    time_t full_secs, +    double frac_secs, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::time_spec_t time_spec_cpp(full_secs, frac_secs); +        USRP(h)->set_time_next_pps(time_spec_cpp, mboard); +    ) +} + +uhd_error uhd_usrp_set_time_unknown_pps( +    uhd_usrp_handle h, +    time_t full_secs, +    double frac_secs +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::time_spec_t time_spec_cpp(full_secs, frac_secs); +        USRP(h)->set_time_unknown_pps(time_spec_cpp); +    ) +} + +uhd_error uhd_usrp_get_time_synchronized( +    uhd_usrp_handle h, +    bool *result_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *result_out = USRP(h)->get_time_synchronized(); +        return UHD_ERROR_NONE; +    ) +} + +uhd_error uhd_usrp_set_command_time( +    uhd_usrp_handle h, +    time_t full_secs, +    double frac_secs, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::time_spec_t time_spec_cpp(full_secs, frac_secs); +        USRP(h)->set_command_time(time_spec_cpp, mboard); +    ) +} + +uhd_error uhd_usrp_clear_command_time( +    uhd_usrp_handle h, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->clear_command_time(mboard); +    ) +} + +uhd_error uhd_usrp_issue_stream_cmd( +    uhd_usrp_handle h, +    uhd_stream_cmd_t *stream_cmd, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->issue_stream_cmd(stream_cmd_c_to_cpp(stream_cmd), chan); +    ) +} + +uhd_error uhd_usrp_set_time_source( +    uhd_usrp_handle h, +    const char* time_source, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_time_source(std::string(time_source), mboard); +    ) +} + +uhd_error uhd_usrp_get_time_source( +    uhd_usrp_handle h, +    size_t mboard, +    char* time_source_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        strncpy(time_source_out, USRP(h)->get_time_source(mboard).c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_get_time_sources( +    uhd_usrp_handle h, +    size_t mboard, +    char* time_sources_out, +    size_t strbuffer_len, +    size_t *num_time_sources_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> time_sources = USRP(h)->get_time_sources(mboard); +        *num_time_sources_out = time_sources.size(); + +        std::string time_sources_str = ""; +        BOOST_FOREACH(const std::string &time_source, time_sources){ +            time_sources_str += time_source; +            time_sources_str += ','; +        } +        if(time_sources.size() > 0){ +            time_sources_str.resize(time_sources_str.size()-1); +        } + +        memset(time_sources_out, '\0', strbuffer_len); +        strncpy(time_sources_out, time_sources_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_clock_source( +    uhd_usrp_handle h, +    const char* clock_source, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_clock_source(std::string(clock_source), mboard); +    ) +} + +uhd_error uhd_usrp_get_clock_source( +    uhd_usrp_handle h, +    size_t mboard, +    char* clock_source_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        strncpy(clock_source_out, USRP(h)->get_clock_source(mboard).c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_get_clock_sources( +    uhd_usrp_handle h, +    size_t mboard, +    char* clock_sources_out, +    size_t strbuffer_len, +    size_t *num_clock_sources_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> clock_sources = USRP(h)->get_clock_sources(mboard); +        *num_clock_sources_out = clock_sources.size(); + +        std::string clock_sources_str = ""; +        BOOST_FOREACH(const std::string &clock_source, clock_sources){ +            clock_sources_str += clock_source; +            clock_sources_str += ','; +        } +        if(clock_sources.size() > 0){ +            clock_sources_str.resize(clock_sources_str.size()-1); +        } + +        memset(clock_sources_out, '\0', strbuffer_len); +        strncpy(clock_sources_out, clock_sources_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_clock_source_out( +    uhd_usrp_handle h, +    bool enb, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_clock_source_out(enb, mboard); +    ) +} + +uhd_error uhd_usrp_get_num_mboards( +    uhd_usrp_handle h, +    size_t *num_mboards_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *num_mboards_out = USRP(h)->get_num_mboards(); +    ) +} + +uhd_error uhd_usrp_get_mboard_sensor( +    uhd_usrp_handle h, +    const char* name, +    size_t mboard, +    uhd_sensor_value_handle sensor_value_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        delete sensor_value_out->sensor_value_cpp; +        sensor_value_out->sensor_value_cpp = new uhd::sensor_value_t(USRP(h)->get_mboard_sensor(name, mboard)); +    ) +} + +uhd_error uhd_usrp_get_mboard_sensor_names( +    uhd_usrp_handle h, +    size_t mboard, +    char* mboard_sensor_names_out, +    size_t strbuffer_len, +    size_t *num_mboard_sensors_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> mboard_sensor_names = USRP(h)->get_mboard_sensor_names(mboard); +        *num_mboard_sensors_out = mboard_sensor_names.size(); + +        std::string mboard_sensor_names_str = ""; +        BOOST_FOREACH(const std::string &mboard_sensor_name, mboard_sensor_names){ +            mboard_sensor_names_str += mboard_sensor_name; +            mboard_sensor_names_str += ','; +        } +        if(mboard_sensor_names.size() > 0){ +            mboard_sensor_names_str.resize(mboard_sensor_names_str.size()-1); +        } + +        memset(mboard_sensor_names_out, '\0', strbuffer_len); +        strncpy(mboard_sensor_names_out, mboard_sensor_names_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_user_register( +    uhd_usrp_handle h, +    uint8_t addr, +    uint32_t data, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_user_register(addr, data, mboard); +    ) +} + +/**************************************************************************** + * EEPROM access methods + ***************************************************************************/ + +uhd_error uhd_usrp_get_mboard_eeprom( +    uhd_usrp_handle h, +    uhd_mboard_eeprom_handle mb_eeprom, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/eeprom") +                                       % mboard); + +        uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree(); +        mb_eeprom->mboard_eeprom_cpp = ptree->access<uhd::usrp::mboard_eeprom_t>(eeprom_path).get(); +    ) +} + +uhd_error uhd_usrp_set_mboard_eeprom( +    uhd_usrp_handle h, +    uhd_mboard_eeprom_handle mb_eeprom, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/eeprom") +                                       % mboard); + +        uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree(); +        ptree->access<uhd::usrp::mboard_eeprom_t>(eeprom_path).set(mb_eeprom->mboard_eeprom_cpp); +    ) +} + +uhd_error uhd_usrp_get_dboard_eeprom( +    uhd_usrp_handle h, +    uhd_dboard_eeprom_handle db_eeprom, +    const char* unit, +    const char* slot, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/dboards/%s/%s_eeprom") +                                       % mboard % slot % unit); + +        uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree(); +        db_eeprom->dboard_eeprom_cpp = ptree->access<uhd::usrp::dboard_eeprom_t>(eeprom_path).get(); +    ) +} + +uhd_error uhd_usrp_set_dboard_eeprom( +    uhd_usrp_handle h, +    uhd_dboard_eeprom_handle db_eeprom, +    const char* unit, +    const char* slot, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/dboards/%s/%s_eeprom") +                                       % mboard % slot % unit); + +        uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree(); +        ptree->access<uhd::usrp::dboard_eeprom_t>(eeprom_path).set(db_eeprom->dboard_eeprom_cpp); +    ) +} + +/**************************************************************************** + * RX methods + ***************************************************************************/ + +uhd_error uhd_usrp_set_rx_subdev_spec( +    uhd_usrp_handle h, +    uhd_subdev_spec_handle subdev_spec, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_rx_subdev_spec(subdev_spec->subdev_spec_cpp, mboard); +    ) +} + +uhd_error uhd_usrp_get_rx_subdev_spec( +    uhd_usrp_handle h, +    size_t mboard, +    uhd_subdev_spec_handle subdev_spec_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        subdev_spec_out->subdev_spec_cpp = USRP(h)->get_rx_subdev_spec(mboard); +    ) +} + +uhd_error uhd_usrp_get_rx_num_channels( +    uhd_usrp_handle h, +    size_t *num_channels_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *num_channels_out = USRP(h)->get_rx_num_channels(); +    ) +} + +uhd_error uhd_usrp_get_rx_subdev_name( +    uhd_usrp_handle h, +    size_t chan, +    char* rx_subdev_name_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string rx_subdev_name = USRP(h)->get_rx_subdev_name(chan); +        strncpy(rx_subdev_name_out, rx_subdev_name.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_rx_rate( +    uhd_usrp_handle h, +    double rate, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_rx_rate(rate, chan); +    ) +} + +uhd_error uhd_usrp_get_rx_rate( +    uhd_usrp_handle h, +    size_t chan, +    double *rate_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *rate_out = USRP(h)->get_rx_rate(chan); +    ) +} + +uhd_error uhd_usrp_get_rx_rates( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle rates_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        rates_out->meta_range_cpp = USRP(h)->get_rx_rates(chan); +    ) +} + +uhd_error uhd_usrp_set_rx_freq( +    uhd_usrp_handle h, +    uhd_tune_request_t *tune_request, +    size_t chan, +    uhd_tune_result_t *tune_result +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::tune_request_t tune_request_cpp = uhd_tune_request_c_to_cpp(tune_request); +        uhd::tune_result_t tune_result_cpp = USRP(h)->set_rx_freq(tune_request_cpp, chan); +        uhd_tune_result_cpp_to_c(tune_result_cpp, tune_result); +    ) +} + +uhd_error uhd_usrp_get_rx_freq( +    uhd_usrp_handle h, +    size_t chan, +    double *freq_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *freq_out = USRP(h)->get_rx_freq(chan); +    ) +} + +uhd_error uhd_usrp_get_rx_freq_range( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle freq_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        freq_range_out->meta_range_cpp = USRP(h)->get_rx_freq_range(chan); +    ) +} + +uhd_error uhd_usrp_get_fe_rx_freq_range( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle freq_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        freq_range_out->meta_range_cpp = USRP(h)->get_fe_rx_freq_range(chan); +    ) +} + +uhd_error uhd_usrp_set_rx_gain( +    uhd_usrp_handle h, +    double gain, +    size_t chan, +    const char *gain_name +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string name(gain_name); +        if(name.empty()){ +            USRP(h)->set_rx_gain(gain, chan); +        } +        else{ +            USRP(h)->set_rx_gain(gain, name, chan); +        } +    ) +} + +uhd_error uhd_usrp_set_normalized_rx_gain( +    uhd_usrp_handle h, +    double gain, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_normalized_rx_gain(gain, chan); +    ) +} + +uhd_error uhd_usrp_set_rx_agc( +    uhd_usrp_handle h, +    bool enable, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_rx_agc(enable, chan); +    ) +} + +uhd_error uhd_usrp_get_rx_gain( +    uhd_usrp_handle h, +    size_t chan, +    const char *gain_name, +    double *gain_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string name(gain_name); +        if(name.empty()){ +            *gain_out = USRP(h)->get_rx_gain(chan); +        } +        else{ +            *gain_out = USRP(h)->get_rx_gain(name, chan); +        } +    ) +} + +uhd_error uhd_usrp_get_normalized_rx_gain( +    uhd_usrp_handle h, +    size_t chan, +    double *gain_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *gain_out = USRP(h)->get_normalized_rx_gain(chan); +    ) +} + +uhd_error uhd_usrp_get_rx_gain_range( +    uhd_usrp_handle h, +    const char* name, +    size_t chan, +    uhd_meta_range_handle gain_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        gain_range_out->meta_range_cpp = USRP(h)->get_rx_gain_range(name, chan); +    ) +} + +uhd_error uhd_usrp_get_rx_gain_names( +    uhd_usrp_handle h, +    size_t chan, +    char* gain_names_out, +    size_t strbuffer_len, +    size_t *num_rx_gain_names_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> rx_gain_names = USRP(h)->get_rx_gain_names(chan); +        *num_rx_gain_names_out = rx_gain_names.size(); + +        std::string rx_gain_names_str = ""; +        BOOST_FOREACH(const std::string &gain_name, rx_gain_names){ +            rx_gain_names_str += gain_name; +            rx_gain_names_str += ','; +        } +        if(rx_gain_names.size() > 0){ +            rx_gain_names_str.resize(rx_gain_names_str.size()-1); +        } + +        memset(gain_names_out, '\0', strbuffer_len); +        strncpy(gain_names_out, rx_gain_names_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_rx_antenna( +    uhd_usrp_handle h, +    const char* ant, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_rx_antenna(std::string(ant), chan); +    ) +} + +uhd_error uhd_usrp_get_rx_antenna( +    uhd_usrp_handle h, +    size_t chan, +    char* ant_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string rx_antenna = USRP(h)->get_rx_antenna(chan); +        strncpy(ant_out, rx_antenna.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_get_rx_antennas( +    uhd_usrp_handle h, +    size_t chan, +    char* antennas_out, +    size_t strbuffer_len, +    size_t *num_rx_antennas_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> rx_antennas = USRP(h)->get_rx_antennas(chan); +        *num_rx_antennas_out = rx_antennas.size(); + +        std::string rx_antennas_str = ""; +        BOOST_FOREACH(const std::string &rx_antenna, rx_antennas){ +            rx_antennas_str += rx_antenna; +            rx_antennas_str += ','; +        } +        if(rx_antennas.size() > 0){ +            rx_antennas_str.resize(rx_antennas_str.size()-1); +        } + +        memset(antennas_out, '\0', strbuffer_len); +        strncpy(antennas_out, rx_antennas_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_rx_bandwidth( +    uhd_usrp_handle h, +    double bandwidth, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_rx_bandwidth(bandwidth, chan); +    ) +} + +uhd_error uhd_usrp_get_rx_bandwidth( +    uhd_usrp_handle h, +    size_t chan, +    double *bandwidth_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *bandwidth_out = USRP(h)->get_rx_bandwidth(chan); +    ) +} + +uhd_error uhd_usrp_get_rx_bandwidth_range( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle bandwidth_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        bandwidth_range_out->meta_range_cpp = USRP(h)->get_rx_bandwidth_range(chan); +    ) +} + +uhd_error uhd_usrp_get_rx_sensor( +    uhd_usrp_handle h, +    const char* name, +    size_t chan, +    uhd_sensor_value_handle sensor_value_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        delete sensor_value_out->sensor_value_cpp; +        sensor_value_out->sensor_value_cpp = new uhd::sensor_value_t(USRP(h)->get_rx_sensor(name, chan)); +    ) +} + +uhd_error uhd_usrp_get_rx_sensor_names( +    uhd_usrp_handle h, +    size_t chan, +    char* sensor_names_out, +    size_t strbuffer_len, +    size_t *num_rx_sensors_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> rx_sensor_names = USRP(h)->get_rx_sensor_names(chan); +        *num_rx_sensors_out = rx_sensor_names.size(); + +        std::string rx_sensor_names_str = ""; +        BOOST_FOREACH(const std::string &rx_sensor_name, rx_sensor_names){ +            rx_sensor_names_str += rx_sensor_name; +            rx_sensor_names_str += ','; +        } +        if(rx_sensor_names.size() > 0){ +            rx_sensor_names_str.resize(rx_sensor_names_str.size()-1); +        } + +        memset(sensor_names_out, '\0', strbuffer_len); +        strncpy(sensor_names_out, rx_sensor_names_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_rx_dc_offset_enabled( +    uhd_usrp_handle h, +    bool enb, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_rx_dc_offset(enb, chan); +    ) +} + +uhd_error uhd_usrp_set_rx_iq_balance_enabled( +    uhd_usrp_handle h, +    bool enb, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_rx_iq_balance(enb, chan); +    ) +} + +/**************************************************************************** + * TX methods + ***************************************************************************/ + +uhd_error uhd_usrp_set_tx_subdev_spec( +    uhd_usrp_handle h, +    uhd_subdev_spec_handle subdev_spec, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_tx_subdev_spec(subdev_spec->subdev_spec_cpp, mboard); +    ) +} + +uhd_error uhd_usrp_get_tx_subdev_spec( +    uhd_usrp_handle h, +    size_t mboard, +    uhd_subdev_spec_handle subdev_spec_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        subdev_spec_out->subdev_spec_cpp = USRP(h)->get_tx_subdev_spec(mboard); +    ) +} + + +uhd_error uhd_usrp_get_tx_num_channels( +    uhd_usrp_handle h, +    size_t *num_channels_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *num_channels_out = USRP(h)->get_tx_num_channels(); +    ) +} + +uhd_error uhd_usrp_get_tx_subdev_name( +    uhd_usrp_handle h, +    size_t chan, +    char* tx_subdev_name_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string tx_subdev_name = USRP(h)->get_tx_subdev_name(chan); +        strncpy(tx_subdev_name_out, tx_subdev_name.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_tx_rate( +    uhd_usrp_handle h, +    double rate, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_tx_rate(rate, chan); +    ) +} + +uhd_error uhd_usrp_get_tx_rate( +    uhd_usrp_handle h, +    size_t chan, +    double *rate_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *rate_out = USRP(h)->get_tx_rate(chan); +    ) +} + +uhd_error uhd_usrp_get_tx_rates( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle rates_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        rates_out->meta_range_cpp = USRP(h)->get_tx_rates(chan); +    ) +} + +uhd_error uhd_usrp_set_tx_freq( +    uhd_usrp_handle h, +    uhd_tune_request_t *tune_request, +    size_t chan, +    uhd_tune_result_t *tune_result +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        uhd::tune_request_t tune_request_cpp = uhd_tune_request_c_to_cpp(tune_request); +        uhd::tune_result_t tune_result_cpp = USRP(h)->set_tx_freq(tune_request_cpp, chan); +        uhd_tune_result_cpp_to_c(tune_result_cpp, tune_result); +    ) +} + +uhd_error uhd_usrp_get_tx_freq( +    uhd_usrp_handle h, +    size_t chan, +    double *freq_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *freq_out = USRP(h)->get_tx_freq(chan); +    ) +} + +uhd_error uhd_usrp_get_tx_freq_range( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle freq_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        freq_range_out->meta_range_cpp = USRP(h)->get_tx_freq_range(chan); +    ) +} + +uhd_error uhd_usrp_get_fe_tx_freq_range( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle freq_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        freq_range_out->meta_range_cpp = USRP(h)->get_fe_tx_freq_range(chan); +    ) +} + +uhd_error uhd_usrp_set_tx_gain( +    uhd_usrp_handle h, +    double gain, +    size_t chan, +    const char *gain_name +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string name(gain_name); +        if(name.empty()){ +            USRP(h)->set_tx_gain(gain, chan); +        } +        else{ +            USRP(h)->set_tx_gain(gain, name, chan); +        } +    ) +} + +uhd_error uhd_usrp_set_normalized_tx_gain( +    uhd_usrp_handle h, +    double gain, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_normalized_tx_gain(gain, chan); +    ) +} + +uhd_error uhd_usrp_get_tx_gain( +    uhd_usrp_handle h, +    size_t chan, +    const char *gain_name, +    double *gain_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string name(gain_name); +        if(name.empty()){ +            *gain_out = USRP(h)->get_tx_gain(chan); +        } +        else{ +            *gain_out = USRP(h)->get_tx_gain(name, chan); +        } +    ) +} + +uhd_error uhd_usrp_get_normalized_tx_gain( +    uhd_usrp_handle h, +    size_t chan, +    double *gain_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *gain_out = USRP(h)->get_normalized_tx_gain(chan); +    ) +} + +uhd_error uhd_usrp_get_tx_gain_range( +    uhd_usrp_handle h, +    const char* name, +    size_t chan, +    uhd_meta_range_handle gain_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        gain_range_out->meta_range_cpp = USRP(h)->get_tx_gain_range(name, chan); +    ) +} + +uhd_error uhd_usrp_get_tx_gain_names( +    uhd_usrp_handle h, +    size_t chan, +    char* gain_names_out, +    size_t strbuffer_len, +    size_t *num_tx_gain_names_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> tx_gain_names = USRP(h)->get_tx_gain_names(chan); +        *num_tx_gain_names_out = tx_gain_names.size(); + +        std::string tx_gain_names_str = ""; +        BOOST_FOREACH(const std::string &tx_gain_name, tx_gain_names){ +            tx_gain_names_str += tx_gain_name; +            tx_gain_names_str += ','; +        } +        if(tx_gain_names.size() > 0){ +            tx_gain_names_str.resize(tx_gain_names_str.size()-1); +        } + +        memset(gain_names_out, '\0', strbuffer_len); +        strncpy(gain_names_out, tx_gain_names_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_tx_antenna( +    uhd_usrp_handle h, +    const char* ant, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_tx_antenna(std::string(ant), chan); +    ) +} + +uhd_error uhd_usrp_get_tx_antenna( +    uhd_usrp_handle h, +    size_t chan, +    char* ant_out, +    size_t strbuffer_len +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::string tx_antenna = USRP(h)->get_tx_antenna(chan); +        strncpy(ant_out, tx_antenna.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_get_tx_antennas( +    uhd_usrp_handle h, +    size_t chan, +    char* antennas_out, +    size_t strbuffer_len, +    size_t *num_tx_antennas_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> tx_antennas = USRP(h)->get_tx_antennas(chan); +        *num_tx_antennas_out = tx_antennas.size(); + +        std::string tx_antennas_str = ""; +        BOOST_FOREACH(const std::string &tx_antenna, tx_antennas){ +            tx_antennas_str += tx_antenna; +            tx_antennas_str += ','; +        } +        if(tx_antennas.size() > 0){ +            tx_antennas_str.resize(tx_antennas_str.size()-1); +        } + +        memset(antennas_out, '\0', strbuffer_len); +        strncpy(antennas_out, tx_antennas_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_tx_bandwidth( +    uhd_usrp_handle h, +    double bandwidth, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_tx_bandwidth(bandwidth, chan); +    ) +} + +uhd_error uhd_usrp_get_tx_bandwidth( +    uhd_usrp_handle h, +    size_t chan, +    double *bandwidth_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *bandwidth_out = USRP(h)->get_tx_bandwidth(chan); +    ) +} + +uhd_error uhd_usrp_get_tx_bandwidth_range( +    uhd_usrp_handle h, +    size_t chan, +    uhd_meta_range_handle bandwidth_range_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        bandwidth_range_out->meta_range_cpp = USRP(h)->get_tx_bandwidth_range(chan); +    ) +} + +uhd_error uhd_usrp_get_tx_sensor( +    uhd_usrp_handle h, +    const char* name, +    size_t chan, +    uhd_sensor_value_handle sensor_value_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        delete sensor_value_out->sensor_value_cpp; +        sensor_value_out->sensor_value_cpp = new uhd::sensor_value_t(USRP(h)->get_tx_sensor(name, chan)); +    ) +} + +uhd_error uhd_usrp_get_tx_sensor_names( +    uhd_usrp_handle h, +    size_t chan, +    char* sensor_names_out, +    size_t strbuffer_len, +    size_t *num_tx_sensors_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> tx_sensor_names = USRP(h)->get_tx_sensor_names(chan); +        *num_tx_sensors_out = tx_sensor_names.size(); + +        std::string tx_sensor_names_str = ""; +        BOOST_FOREACH(const std::string &tx_sensor_name, tx_sensor_names){ +            tx_sensor_names_str += tx_sensor_name; +            tx_sensor_names_str += ','; +        } +        if(tx_sensor_names.size() > 0){ +            tx_sensor_names_str.resize(tx_sensor_names_str.size()-1); +        } + +        memset(sensor_names_out, '\0', strbuffer_len); +        strncpy(sensor_names_out, tx_sensor_names_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_tx_dc_offset_enabled( +    uhd_usrp_handle h, +    bool enb, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_tx_dc_offset(enb, chan); +    ) +} + +uhd_error uhd_usrp_set_tx_iq_balance_enabled( +    uhd_usrp_handle h, +    bool enb, +    size_t chan +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_tx_iq_balance(enb, chan); +    ) +} + +/**************************************************************************** + * GPIO methods + ***************************************************************************/ + +uhd_error uhd_usrp_get_gpio_banks( +    uhd_usrp_handle h, +    size_t chan, +    char* gpio_banks_out, +    size_t strbuffer_len, +    size_t *num_gpio_banks_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        std::vector<std::string> gpio_banks = USRP(h)->get_gpio_banks(chan); +        *num_gpio_banks_out = gpio_banks.size(); + +        std::string gpio_banks_str = ""; +        BOOST_FOREACH(const std::string &gpio_bank, gpio_banks){ +            gpio_banks_str += gpio_bank; +            gpio_banks_str += ','; +        } +        if(gpio_banks.size() > 0){ +            gpio_banks_str.resize(gpio_banks_str.size()-1); +        } + +        memset(gpio_banks_out, '\0', strbuffer_len); +        strncpy(gpio_banks_out, gpio_banks_str.c_str(), strbuffer_len); +    ) +} + +uhd_error uhd_usrp_set_gpio_attr( +    uhd_usrp_handle h, +    const char* bank, +    const char* attr, +    uint32_t value, +    uint32_t mask, +    size_t mboard +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        USRP(h)->set_gpio_attr(std::string(bank), std::string(attr), +                               value, mask, mboard); +    ) +} + +uhd_error uhd_usrp_get_gpio_attr( +    uhd_usrp_handle h, +    const char* bank, +    const char* attr, +    size_t mboard, +    uint32_t *attr_out +){ +    UHD_SAFE_C_SAVE_ERROR(h, +        *attr_out = USRP(h)->get_gpio_attr(std::string(bank), std::string(attr), mboard); +    ) +} diff --git a/host/lib/usrp/x300/x300_adc_dac_utils.cpp b/host/lib/usrp/x300/x300_adc_dac_utils.cpp index b1483b3a5..e08825749 100644 --- a/host/lib/usrp/x300/x300_adc_dac_utils.cpp +++ b/host/lib/usrp/x300/x300_adc_dac_utils.cpp @@ -41,7 +41,7 @@ void x300_impl::synchronize_dacs(const std::vector<radio_perifs_t*>& radios)      //Get a rough estimate of the cumulative command latency      boost::posix_time::ptime t_start = boost::posix_time::microsec_clock::local_time();      for (size_t i = 0; i < radios.size(); i++) { -        radios[i]->ctrl->peek64(RB64_TIME_NOW); //Discard value. We are just timing the call +        radios[i]->ctrl->peek64(uhd::usrp::radio::RB64_TIME_NOW); //Discard value. We are just timing the call      }      boost::posix_time::time_duration t_elapsed =          boost::posix_time::microsec_clock::local_time() - t_start; @@ -56,7 +56,7 @@ void x300_impl::synchronize_dacs(const std::vector<radio_perifs_t*>& radios)      //Send the sync command      for (size_t i = 0; i < radios.size(); i++) {          radios[i]->ctrl->set_time(sync_time); -        radios[i]->ctrl->poke32(TOREG(SR_DACSYNC), 0x1);    //Arm FRAMEP/N sync pulse +        radios[i]->ctrl->poke32(uhd::usrp::radio::sr_addr(uhd::usrp::radio::DACSYNC), 0x1);    //Arm FRAMEP/N sync pulse          radios[i]->ctrl->set_time(uhd::time_spec_t(0.0));   //Clear command time      } @@ -73,7 +73,7 @@ void x300_impl::synchronize_dacs(const std::vector<radio_perifs_t*>& radios)  static void check_adc(uhd::wb_iface::sptr iface, const boost::uint32_t val, const boost::uint32_t i)  { -    boost::uint32_t adc_rb = iface->peek32(RB32_RX); +    boost::uint32_t adc_rb = iface->peek32(uhd::usrp::radio::RB32_RX);      adc_rb ^= 0xfffc0000; //adapt for I inversion in FPGA      if (val != adc_rb) {          throw uhd::runtime_error( diff --git a/host/lib/usrp/x300/x300_image_loader.cpp b/host/lib/usrp/x300/x300_image_loader.cpp index 321309868..9ec8a2e13 100644 --- a/host/lib/usrp/x300/x300_image_loader.cpp +++ b/host/lib/usrp/x300/x300_image_loader.cpp @@ -158,17 +158,31 @@ static void x300_validate_image(x300_session_t &session){  static void x300_setup_session(x300_session_t &session,                                 const device_addr_t &args,                                 const std::string &filepath){ -    device_addr_t find_args; -    find_args["type"] = "x300"; -    if(args.has_key("name")) find_args["name"] = args["name"]; -    if(args.has_key("serial")) find_args["serial"] = args["serial"]; -    if(args.has_key("ip-addr")) find_args["addr"] = args["ip-addr"]; -    else if(args.has_key("resource")) find_args["resource"] = args["resource"]; -      device_addrs_t devs = x300_find(args); -    session.found = (devs.size() > 0); -    if(!session.found) return; +    if(devs.size() == 0){ +        session.found = false; +        return; +    } +    else if(devs.size() > 1){ +        std::string err_msg = "Could not resolve given args to a single X-Series device.\n" +                              "Applicable devices:\n"; + +        BOOST_FOREACH(const uhd::device_addr_t &dev, devs){ +            std::string identifier = dev.has_key("addr") ? "addr" +                                                         : "resource"; + +            err_msg += str(boost::format(" * %s (%s=%s)\n") +                           % dev.get("product", "X3XX") +                           % identifier +                           % dev.get(identifier)); +        } + +        err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + +        throw uhd::runtime_error(err_msg); +    } +    session.found = true;      session.dev_addr = devs[0];      session.ethernet = session.dev_addr.has_key("addr");      if(session.ethernet){ diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 437fec82d..229bf7b23 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -29,6 +29,7 @@  #include <uhd/transport/if_addrs.hpp>  #include <boost/foreach.hpp>  #include <boost/bind.hpp> +#include <boost/make_shared.hpp>  #include <boost/functional/hash.hpp>  #include <boost/assign/list_of.hpp>  #include <fstream> @@ -410,7 +411,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)          //Tell the quirks object which FIFOs carry TX stream data          const boost::uint32_t tx_data_fifos[2] = {X300_RADIO_DEST_PREFIX_TX, X300_RADIO_DEST_PREFIX_TX + 3}; -        mb.rio_fpga_interface->get_kernel_proxy()->get_rio_quirks().register_tx_streams(tx_data_fifos); +        mb.rio_fpga_interface->get_kernel_proxy()->get_rio_quirks().register_tx_streams(tx_data_fifos, 2);          _tree->create<double>(mb_path / "link_max_rate").set(X300_MAX_RATE_PCIE);      } @@ -748,7 +749,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)      ////////////////////////////////////////////////////////////////////      // front panel gpio      //////////////////////////////////////////////////////////////////// -    mb.fp_gpio = gpio_core_200::make(mb.radio_perifs[0].ctrl, TOREG(SR_FP_GPIO), RB32_FP_GPIO); +    mb.fp_gpio = gpio_core_200::make(mb.radio_perifs[0].ctrl, radio::sr_addr(radio::GPIO), radio::RB32_FP_GPIO);      BOOST_FOREACH(const gpio_attr_map_t::value_type attr, gpio_attr_map)      {          _tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / attr.second) @@ -943,30 +944,30 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con      ////////////////////////////////////////////////////////////////      // Setup peripherals      //////////////////////////////////////////////////////////////// -    perif.spi = spi_core_3000::make(perif.ctrl, TOREG(SR_SPI), RB32_SPI); +    perif.spi = spi_core_3000::make(perif.ctrl, radio::sr_addr(radio::SPI), radio::RB32_SPI);      perif.adc = x300_adc_ctrl::make(perif.spi, DB_ADC_SEN);      perif.dac = x300_dac_ctrl::make(perif.spi, DB_DAC_SEN, mb.clock->get_master_clock_rate()); -    perif.leds = gpio_core_200_32wo::make(perif.ctrl, TOREG(SR_LEDS)); -    perif.rx_fe = rx_frontend_core_200::make(perif.ctrl, TOREG(SR_RX_FRONT)); +    perif.leds = gpio_core_200_32wo::make(perif.ctrl, radio::sr_addr(radio::LEDS)); +    perif.rx_fe = rx_frontend_core_200::make(perif.ctrl, radio::sr_addr(radio::RX_FRONT));      perif.rx_fe->set_dc_offset(rx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE);      perif.rx_fe->set_dc_offset_auto(rx_frontend_core_200::DEFAULT_DC_OFFSET_ENABLE); -    perif.tx_fe = tx_frontend_core_200::make(perif.ctrl, TOREG(SR_TX_FRONT)); +    perif.tx_fe = tx_frontend_core_200::make(perif.ctrl, radio::sr_addr(radio::TX_FRONT));      perif.tx_fe->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE);      perif.tx_fe->set_iq_balance(tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); -    perif.framer = rx_vita_core_3000::make(perif.ctrl, TOREG(SR_RX_CTRL)); -    perif.ddc = rx_dsp_core_3000::make(perif.ctrl, TOREG(SR_RX_DSP)); +    perif.framer = rx_vita_core_3000::make(perif.ctrl, radio::sr_addr(radio::RX_CTRL)); +    perif.ddc = rx_dsp_core_3000::make(perif.ctrl, radio::sr_addr(radio::RX_DSP));      perif.ddc->set_link_rate(10e9/8); //whatever -    perif.deframer = tx_vita_core_3000::make(perif.ctrl, TOREG(SR_TX_CTRL)); -    perif.duc = tx_dsp_core_3000::make(perif.ctrl, TOREG(SR_TX_DSP)); +    perif.deframer = tx_vita_core_3000::make(perif.ctrl, radio::sr_addr(radio::TX_CTRL)); +    perif.duc = tx_dsp_core_3000::make(perif.ctrl, radio::sr_addr(radio::TX_DSP));      perif.duc->set_link_rate(10e9/8); //whatever      ////////////////////////////////////////////////////////////////////      // create time control objects      ////////////////////////////////////////////////////////////////////      time_core_3000::readback_bases_type time64_rb_bases; -    time64_rb_bases.rb_now = RB64_TIME_NOW; -    time64_rb_bases.rb_pps = RB64_TIME_PPS; -    perif.time64 = time_core_3000::make(perif.ctrl, TOREG(SR_TIME), time64_rb_bases); +    time64_rb_bases.rb_now = radio::RB64_TIME_NOW; +    time64_rb_bases.rb_pps = radio::RB64_TIME_PPS; +    perif.time64 = time_core_3000::make(perif.ctrl, radio::sr_addr(radio::TIME), time64_rb_bases);      //Capture delays are calibrated every time. The status is only printed is the user      //asks to run the xfer self cal using "self_cal_adc_delay" @@ -1030,7 +1031,7 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con      //create a new dboard interface      x300_dboard_iface_config_t db_config; -    db_config.gpio = gpio_core_200::make(perif.ctrl, TOREG(SR_GPIO), RB32_GPIO); +    db_config.gpio = gpio_core_200::make(perif.ctrl, radio::sr_addr(radio::GPIO), radio::RB32_GPIO);      db_config.spi = perif.spi;      db_config.rx_spi_slaveno = DB_RX_SEN;      db_config.tx_spi_slaveno = DB_TX_SEN; @@ -1343,8 +1344,8 @@ void x300_impl::register_loopback_self_test(wb_iface::sptr iface)      for (size_t i = 0; i < 100; i++)      {          boost::hash_combine(hash, i); -        iface->poke32(TOREG(SR_TEST), boost::uint32_t(hash)); -        test_fail = iface->peek32(RB32_TEST) != boost::uint32_t(hash); +        iface->poke32(radio::sr_addr(radio::TEST), boost::uint32_t(hash)); +        test_fail = iface->peek32(radio::RB32_TEST) != boost::uint32_t(hash);          if (test_fail) break; //exit loop on any failure      }      UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl; diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index 350845f28..eba30abb5 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -18,40 +18,47 @@  #ifndef INCLUDED_X300_REGS_HPP  #define INCLUDED_X300_REGS_HPP +#include <uhd/config.hpp>  #include <stdint.h> -#include <boost/cstdint.hpp>  #include <uhd/utils/soft_register.hpp> -#define TOREG(x) ((x)*4) +namespace uhd { namespace usrp { namespace radio { + +static UHD_INLINE uint32_t sr_addr(const uint32_t offset) +{ +    return offset * 4; +} + +static const uint32_t DACSYNC    = 5; +static const uint32_t LOOPBACK   = 6; +static const uint32_t TEST       = 7; +static const uint32_t SPI        = 8; +static const uint32_t GPIO       = 16; +static const uint32_t MISC_OUTS  = 24; +static const uint32_t READBACK   = 32; +static const uint32_t TX_CTRL    = 64; +static const uint32_t RX_CTRL    = 96; +static const uint32_t TIME       = 128; +static const uint32_t RX_DSP     = 144; +static const uint32_t TX_DSP     = 184; +static const uint32_t LEDS       = 195; +static const uint32_t FP_GPIO    = 200; +static const uint32_t RX_FRONT   = 208; +static const uint32_t TX_FRONT   = 216; + +static const uint32_t RB32_GPIO            = 0; +static const uint32_t RB32_SPI             = 4; +static const uint32_t RB64_TIME_NOW        = 8; +static const uint32_t RB64_TIME_PPS        = 16; +static const uint32_t RB32_TEST            = 24; +static const uint32_t RB32_RX              = 28; +static const uint32_t RB32_FP_GPIO         = 32; +static const uint32_t RB32_MISC_INS        = 36; + +}}} // namespace  #define localparam static const int -localparam SR_DACSYNC    = 5; -localparam SR_LOOPBACK   = 6; -localparam SR_TEST       = 7; -localparam SR_SPI        = 8; -localparam SR_GPIO       = 16; -localparam SR_MISC_OUTS  = 24; -localparam SR_READBACK   = 32; -localparam SR_TX_CTRL    = 64; -localparam SR_RX_CTRL    = 96; -localparam SR_TIME       = 128; -localparam SR_RX_DSP     = 144; -localparam SR_TX_DSP     = 184; -localparam SR_LEDS       = 195; -localparam SR_FP_GPIO    = 200; -localparam SR_RX_FRONT   = 208; -localparam SR_TX_FRONT   = 216; - -localparam RB32_GPIO     = 0; -localparam RB32_SPI      = 4; -localparam RB64_TIME_NOW = 8; -localparam RB64_TIME_PPS = 16; -localparam RB32_TEST     = 24; -localparam RB32_RX       = 28; -localparam RB32_FP_GPIO  = 32; -localparam RB32_MISC_INS = 36; -  localparam BL_ADDRESS    = 0;  localparam BL_DATA       = 1; @@ -247,7 +254,7 @@ namespace uhd { namespace usrp { namespace x300 {              UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL,     /*width*/ 5, /*shift*/ 4);  //[8:4]              UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER_ENABLED,  /*width*/ 1, /*shift*/ 9);  //[9] -            misc_outs_reg_t(): uhd::soft_reg32_wo_t(TOREG(SR_MISC_OUTS)) { +            misc_outs_reg_t(): uhd::soft_reg32_wo_t(uhd::usrp::radio::sr_addr(uhd::usrp::radio::MISC_OUTS)) {                  //Initial values                  set(DAC_ENABLED, 0);                  set(DAC_RESET_N, 0); @@ -269,7 +276,7 @@ namespace uhd { namespace usrp { namespace x300 {              UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_ERROR,  /*width*/ 1, /*shift*/ 6);  //[6]              UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_ERROR,  /*width*/ 1, /*shift*/ 7);  //[7] -            misc_ins_reg_t(): uhd::soft_reg32_ro_t(RB32_MISC_INS) { } +            misc_ins_reg_t(): uhd::soft_reg32_ro_t(uhd::usrp::radio::RB32_MISC_INS) { }          } misc_ins_reg;          radio_regmap_t(int radio_num) : soft_regmap_t("radio" + boost::lexical_cast<std::string>(radio_num) + "_regmap") {  | 
