diff options
| -rw-r--r-- | host/Modules/UHDVersion.cmake | 4 | ||||
| -rw-r--r-- | host/include/uhd/usrp/dboard_props.hpp | 1 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_sbx.cpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_wbx_common.cpp (renamed from host/lib/usrp/dboard/db_wbx.cpp) | 295 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_wbx_common.hpp | 72 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_wbx_simple.cpp | 251 | ||||
| -rw-r--r-- | host/lib/usrp/dboard_manager.cpp | 198 | ||||
| -rw-r--r-- | host/lib/usrp/usrp1/dboard_impl.cpp | 12 | ||||
| -rw-r--r-- | host/lib/usrp/usrp1/usrp1_impl.hpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/dboard_impl.cpp | 14 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/dboard_impl.cpp | 15 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.hpp | 2 | ||||
| -rw-r--r-- | host/utils/uhd_usrp_probe.cpp | 23 | ||||
| -rw-r--r-- | host/utils/usrp_burn_db_eeprom.cpp | 15 | 
16 files changed, 620 insertions, 293 deletions
| diff --git a/host/Modules/UHDVersion.cmake b/host/Modules/UHDVersion.cmake index 86d3133a8..abee8f509 100644 --- a/host/Modules/UHDVersion.cmake +++ b/host/Modules/UHDVersion.cmake @@ -26,8 +26,8 @@ FIND_PACKAGE(Git QUIET)  #  - increment patch on for bug fixes and docs  ########################################################################  SET(UHD_VERSION_MAJOR 003) -SET(UHD_VERSION_MINOR 000) -SET(UHD_VERSION_PATCH 001) +SET(UHD_VERSION_MINOR 001) +SET(UHD_VERSION_PATCH 000)  ########################################################################  # Version information discovery through git log diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp index 35721ab47..29211ec8c 100644 --- a/host/include/uhd/usrp/dboard_props.hpp +++ b/host/include/uhd/usrp/dboard_props.hpp @@ -32,6 +32,7 @@ namespace uhd{ namespace usrp{          DBOARD_PROP_SUBDEV,         //ro, wax::obj          DBOARD_PROP_SUBDEV_NAMES,   //ro, prop_names_t          DBOARD_PROP_DBOARD_EEPROM,  //rw, dboard_eeprom_t +        DBOARD_PROP_GBOARD_EEPROM,  //rw, dboard_eeprom_t          DBOARD_PROP_DBOARD_IFACE,   //ro, dboard_iface::sptr          DBOARD_PROP_CODEC,          //ro, wax::obj          DBOARD_PROP_GAIN_GROUP      //ro, gain_group diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 36e988f30..0eff5c4bd 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -1,5 +1,5 @@  # -# Copyright 2010 Ettus Research LLC +# Copyright 2010-2011 Ettus Research LLC  #  # This program is free software: you can redistribute it and/or modify  # it under the terms of the GNU General Public License as published by @@ -23,8 +23,9 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp +    ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp +    ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp diff --git a/host/lib/usrp/dboard/db_sbx.cpp b/host/lib/usrp/dboard/db_sbx.cpp index 1fa169304..d0c3c63ac 100644 --- a/host/lib/usrp/dboard/db_sbx.cpp +++ b/host/lib/usrp/dboard/db_sbx.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2011 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp index 2e9a1edc8..eb239c305 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx_common.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2011 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -16,7 +16,6 @@  //  // Common IO Pins -#define ANTSW_IO        ((1 << 5)|(1 << 15))    // on UNIT_TX, 0 = TX, 1 = RX, on UNIT_RX 0 = main ant, 1 = RX2  #define ADF4350_CE      (1 << 3)  #define ADF4350_PDBRF   (1 << 2)  #define ADF4350_MUXOUT  (1 << 1)                // INPUT!!! @@ -43,38 +42,23 @@  #define RX_MIXER_ENB    (RXBB_PDB|ADF4350_PDBRF)  #define RX_MIXER_DIS    0 -// Pin functions -#define TX_POWER_IO     (TX_PUP_5V|TX_PUP_3V)   // high enables power supply -#define TXIO_MASK       (TX_POWER_IO|ANTSW_IO|ADF4350_CE|ADF4350_PDBRF|TXMOD_EN) - -#define RX_POWER_IO     (RX_PUP_5V|RX_PUP_3V)   // high enables power supply -#define RXIO_MASK       (RX_POWER_IO|ANTSW_IO|ADF4350_CE|ADF4350_PDBRF|RXBB_PDB|RX_ATTN_MASK) -  // Power functions -#define TX_POWER_UP     (TX_POWER_IO|ADF4350_CE) +#define TX_POWER_UP     (TX_PUP_5V|TX_PUP_3V|ADF4350_CE) // high enables power supply  #define TX_POWER_DOWN   0 -#define RX_POWER_UP     (RX_POWER_IO|ADF4350_CE) +#define RX_POWER_UP     (RX_PUP_5V|RX_PUP_3V|ADF4350_CE) // high enables power supply  #define RX_POWER_DOWN   0 -// Antenna constants -#define ANT_TX          0                       //the tx line is transmitting -#define ANT_RX          ANTSW_IO                //the tx line is receiving -#define ANT_TXRX        0                       //the rx line is on txrx -#define ANT_RX2         ANTSW_IO                //the rx line in on rx2 -#define ANT_XX          0                       //dont care how the antenna is set - +#include "db_wbx_common.hpp"  #include "adf4350_regs.hpp"  #include <uhd/types/dict.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/types/ranges.hpp>  #include <uhd/types/sensors.hpp>  #include <uhd/utils/assert_has.hpp> -#include <uhd/utils/static.hpp>  #include <uhd/utils/algorithm.hpp>  #include <uhd/utils/warning.hpp>  #include <uhd/usrp/dboard_base.hpp> -#include <uhd/usrp/dboard_manager.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/format.hpp>  #include <boost/math/special_functions/round.hpp> @@ -84,16 +68,10 @@ using namespace uhd::usrp;  using namespace boost::assign;  /*********************************************************************** - * The WBX dboard constants + * The WBX Common dboard constants   **********************************************************************/  static const bool wbx_debug = false; -static const freq_range_t wbx_freq_range(68.75e6, 2.2e9); - -static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); - -static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); -  static const uhd::dict<std::string, gain_range_t> wbx_tx_gain_ranges = map_list_of      ("PGA0", gain_range_t(0, 25, 0.05))  ; @@ -103,105 +81,69 @@ static const uhd::dict<std::string, gain_range_t> wbx_rx_gain_ranges = map_list_  ;  /*********************************************************************** - * The WBX dboard - **********************************************************************/ -class wbx_xcvr : public xcvr_dboard_base{ -public: -    wbx_xcvr(ctor_args_t args); -    ~wbx_xcvr(void); - -    void rx_get(const wax::obj &key, wax::obj &val); -    void rx_set(const wax::obj &key, const wax::obj &val); - -    void tx_get(const wax::obj &key, wax::obj &val); -    void tx_set(const wax::obj &key, const wax::obj &val); - -private: -    uhd::dict<std::string, double> _tx_gains, _rx_gains; -    double       _rx_lo_freq, _tx_lo_freq; -    std::string  _tx_ant, _rx_ant; - -    void set_rx_lo_freq(double freq); -    void set_tx_lo_freq(double freq); -    void set_rx_ant(const std::string &ant); -    void set_tx_ant(const std::string &ant); -    void set_rx_gain(double gain, const std::string &name); -    void set_tx_gain(double gain, const std::string &name); - -    void update_atr(void); - -    /*! -     * Set the LO frequency for the particular dboard unit. -     * \param unit which unit rx or tx -     * \param target_freq the desired frequency in Hz -     * \return the actual frequency in Hz -     */ -    double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - -    /*! -     * Get the lock detect status of the LO. -     * \param unit which unit rx or tx -     * \return true for locked -     */ -    bool get_locked(dboard_iface::unit_t unit){ -        return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; -    } -}; - -/*********************************************************************** - * Register the WBX dboard (min freq, max freq, rx div2, tx div2) - **********************************************************************/ -static dboard_base::sptr make_wbx(dboard_base::ctor_args_t args){ -    return dboard_base::sptr(new wbx_xcvr(args)); -} - -UHD_STATIC_BLOCK(reg_wbx_dboards){ -    dboard_manager::register_dboard(0x0053, 0x0052, &make_wbx, "WBX"); -} - -/*********************************************************************** - * Structors + * WBX Common Implementation   **********************************************************************/ -wbx_xcvr::wbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ +wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){      //enable the clocks that we need      this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);      this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); -    //set the gpio directions and atr controls (identically) -    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); -    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); -    this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK); -    this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); -    if (wbx_debug) std::cerr << boost::format( -        "WBX GPIO Direction: RX: 0x%08x, TX: 0x%08x" -    ) % RXIO_MASK % TXIO_MASK << std::endl; +    //set the gpio directions and atr controls +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXMOD_EN|ADF4350_PDBRF); +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4350_PDBRF); +    this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|ADF4350_CE|TXMOD_EN|ADF4350_PDBRF); +    this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); -    //set some default values -    set_rx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); -    set_tx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); -    set_rx_ant("RX2"); +    //setup ATR for the mixer enables +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE,        TX_MIXER_DIS, TX_MIXER_DIS | TX_MIXER_ENB); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY,     TX_MIXER_DIS, TX_MIXER_DIS | TX_MIXER_ENB); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY,     TX_MIXER_ENB, TX_MIXER_DIS | TX_MIXER_ENB); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, TX_MIXER_ENB, TX_MIXER_DIS | TX_MIXER_ENB); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE,        RX_MIXER_DIS, RX_MIXER_DIS | RX_MIXER_ENB); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY,     RX_MIXER_DIS, RX_MIXER_DIS | RX_MIXER_ENB); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY,     RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + +    //set some default values      BOOST_FOREACH(const std::string &name, wbx_tx_gain_ranges.keys()){          set_tx_gain(wbx_tx_gain_ranges[name].start(), name);      }      BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){          set_rx_gain(wbx_rx_gain_ranges[name].start(), name);      } +    set_rx_enabled(false); +    set_tx_enabled(false);  } -wbx_xcvr::~wbx_xcvr(void){ +wbx_base::~wbx_base(void){      /* NOP */  }  /*********************************************************************** + * Enables + **********************************************************************/ +void wbx_base::set_rx_enabled(bool enb){ +    this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, +        (enb)? RX_POWER_UP : RX_POWER_DOWN, RX_POWER_UP | RX_POWER_DOWN +    ); +} + +void wbx_base::set_tx_enabled(bool enb){ +    this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, +        (enb)? TX_POWER_UP : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN +    ); +} + +/***********************************************************************   * Gain Handling   **********************************************************************/  static int rx_pga0_gain_to_iobits(double &gain){      //clip the input      gain = wbx_rx_gain_ranges["PGA0"].clip(gain); -    //convert to attenuation and update iobits for atr +    //convert to attenuation      double attn = wbx_rx_gain_ranges["PGA0"].stop() - gain;      //calculate the attenuation @@ -239,7 +181,7 @@ static double tx_pga0_gain_to_dac_volts(double &gain){      return dac_volts;  } -void wbx_xcvr::set_tx_gain(double gain, const std::string &name){ +void wbx_base::set_tx_gain(double gain, const std::string &name){      assert_has(wbx_tx_gain_ranges.keys(), name, "wbx tx gain name");      if(name == "PGA0"){          double dac_volts = tx_pga0_gain_to_dac_volts(gain); @@ -251,75 +193,22 @@ void wbx_xcvr::set_tx_gain(double gain, const std::string &name){      else UHD_THROW_INVALID_CODE_PATH();  } -void wbx_xcvr::set_rx_gain(double gain, const std::string &name){ +void wbx_base::set_rx_gain(double gain, const std::string &name){      assert_has(wbx_rx_gain_ranges.keys(), name, "wbx rx gain name");      if(name == "PGA0"){ -        rx_pga0_gain_to_iobits(gain); +        boost::uint16_t io_bits = rx_pga0_gain_to_iobits(gain);          _rx_gains[name] = gain; -        //write the new gain to atr regs -        update_atr(); +        //write the new gain to rx gpio outputs +        this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, io_bits, RX_ATTN_MASK);      }      else UHD_THROW_INVALID_CODE_PATH();  }  /*********************************************************************** - * Antenna Handling - **********************************************************************/ -void wbx_xcvr::update_atr(void){ -    //calculate atr pins -    int pga0_iobits = rx_pga0_gain_to_iobits(_rx_gains["PGA0"]); - -    //setup the tx atr (this does not change with antenna) -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE,        TX_POWER_UP | ANT_XX | TX_MIXER_DIS); -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY,     TX_POWER_UP | ANT_RX | TX_MIXER_DIS); -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY,     TX_POWER_UP | ANT_TX | TX_MIXER_ENB); -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, TX_POWER_UP | ANT_TX | TX_MIXER_ENB); - -    //setup the rx atr (this does not change with antenna) -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, -        pga0_iobits | RX_POWER_UP | ANT_XX | RX_MIXER_DIS); -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, -        pga0_iobits | RX_POWER_UP | ANT_XX | RX_MIXER_DIS); -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, -        pga0_iobits | RX_POWER_UP | ANT_RX2| RX_MIXER_ENB); - -    //set the rx atr regs that change with antenna setting -    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, -        pga0_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)); -    if (wbx_debug) std::cerr << boost::format( -        "WBX RXONLY ATR REG: 0x%08x" -    ) % (pga0_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)) << std::endl; -} - -void wbx_xcvr::set_rx_ant(const std::string &ant){ -    //validate input -    assert_has(wbx_rx_antennas, ant, "wbx rx antenna name"); - -    //shadow the setting -    _rx_ant = ant; - -    //write the new antenna setting to atr regs -    update_atr(); -} - -void wbx_xcvr::set_tx_ant(const std::string &ant){ -    assert_has(wbx_tx_antennas, ant, "wbx tx antenna name"); -    //only one antenna option, do nothing -} - -/***********************************************************************   * Tuning   **********************************************************************/ -void wbx_xcvr::set_rx_lo_freq(double freq){ -    _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); -} - -void wbx_xcvr::set_tx_lo_freq(double freq){ -    _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq); -} - -double wbx_xcvr::set_lo_freq( +double wbx_base::set_lo_freq(      dboard_iface::unit_t unit,      double target_freq  ){ @@ -327,9 +216,6 @@ double wbx_xcvr::set_lo_freq(          "WBX tune: target frequency %f Mhz"      ) % (target_freq/1e6) << std::endl; -    //clip the input -    target_freq = wbx_freq_range.clip(target_freq); -      //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler)      static const uhd::dict<int, int> prescaler_to_min_int_div = map_list_of          (0,23) //adf4350_regs_t::PRESCALER_4_5 @@ -443,6 +329,35 @@ double wbx_xcvr::set_lo_freq(      UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv));      regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; +    if (unit == dboard_iface::UNIT_RX) { +        freq_range_t rx_lo_5dbm = list_of +            (range_t(0.05e9, 1.4e9)) +        ; + +        freq_range_t rx_lo_2dbm = list_of +            (range_t(1.4e9, 2.2e9)) +        ; + +        if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + +        if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; + +    } else if (unit == dboard_iface::UNIT_TX) { +        freq_range_t tx_lo_5dbm = list_of +            (range_t(0.05e9, 1.7e9)) +            (range_t(1.9e9, 2.2e9)) +        ; + +        freq_range_t tx_lo_m1dbm = list_of +            (range_t(1.7e9, 1.9e9)) +        ; + +        if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + +        if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_M1DBM; + +    } +      //write the registers      //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0)      int addr; @@ -464,10 +379,14 @@ double wbx_xcvr::set_lo_freq(      return actual_freq;  } +bool wbx_base::get_locked(dboard_iface::unit_t unit){ +    return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; +} +  /***********************************************************************   * RX Get and Set   **********************************************************************/ -void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ +void wbx_base::rx_get(const wax::obj &key_, wax::obj &val){      named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key @@ -495,19 +414,19 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_FREQ: -        val = _rx_lo_freq; +        val = 0.0;          return;      case SUBDEV_PROP_FREQ_RANGE: -        val = wbx_freq_range; +        val = freq_range_t(0.0, 0.0, 0.0);;          return;      case SUBDEV_PROP_ANTENNA: -        val = _rx_ant; +        val = std::string("");          return;      case SUBDEV_PROP_ANTENNA_NAMES: -        val = wbx_rx_antennas; +        val = prop_names_t(1, "");          return;      case SUBDEV_PROP_CONNECTION: @@ -515,7 +434,7 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_ENABLED: -        val = true; //always enabled +        val = _rx_enabled;          return;      case SUBDEV_PROP_USE_LO_OFFSET: @@ -539,26 +458,20 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){      }  } -void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ +void wbx_base::rx_set(const wax::obj &key_, const wax::obj &val){      named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ -    case SUBDEV_PROP_FREQ: -        this->set_rx_lo_freq(val.as<double>()); -        return; -      case SUBDEV_PROP_GAIN:          this->set_rx_gain(val.as<double>(), key.name);          return; -    case SUBDEV_PROP_ANTENNA: -        this->set_rx_ant(val.as<std::string>()); -        return; -      case SUBDEV_PROP_ENABLED: -        return; //always enabled +        _rx_enabled = val.as<bool>(); +        this->set_rx_enabled(_rx_enabled); +        return;      case SUBDEV_PROP_BANDWIDTH:          uhd::warning::post( @@ -573,7 +486,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){  /***********************************************************************   * TX Get and Set   **********************************************************************/ -void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ +void wbx_base::tx_get(const wax::obj &key_, wax::obj &val){      named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key @@ -601,19 +514,19 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_FREQ: -        val = _tx_lo_freq; +        val = 0.0;          return;      case SUBDEV_PROP_FREQ_RANGE: -        val = wbx_freq_range; +        val = freq_range_t(0.0, 0.0, 0.0);          return;      case SUBDEV_PROP_ANTENNA: -        val = std::string("TX/RX"); +        val = std::string("");          return;      case SUBDEV_PROP_ANTENNA_NAMES: -        val = wbx_tx_antennas; +        val = prop_names_t(1, "");          return;      case SUBDEV_PROP_CONNECTION: @@ -621,7 +534,7 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_ENABLED: -        val = true; //always enabled +        val = _tx_enabled;          return;      case SUBDEV_PROP_USE_LO_OFFSET: @@ -645,26 +558,20 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){      }  } -void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ +void wbx_base::tx_set(const wax::obj &key_, const wax::obj &val){      named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ -    case SUBDEV_PROP_FREQ: -        this->set_tx_lo_freq(val.as<double>()); -        return; -      case SUBDEV_PROP_GAIN:          this->set_tx_gain(val.as<double>(), key.name);          return; -    case SUBDEV_PROP_ANTENNA: -        this->set_tx_ant(val.as<std::string>()); -        return; -      case SUBDEV_PROP_ENABLED: -        return; //always enabled +        _tx_enabled = val.as<bool>(); +        this->set_tx_enabled(_tx_enabled); +        return;      case SUBDEV_PROP_BANDWIDTH:          uhd::warning::post( diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp new file mode 100644 index 000000000..07e84a565 --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_common.hpp @@ -0,0 +1,72 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP +#define INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP + +#include "adf4350_regs.hpp" +#include <uhd/types/dict.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/utils/props.hpp> +#include <uhd/usrp/dboard_base.hpp> + +namespace uhd{ namespace usrp{ + +/*********************************************************************** + * The WBX dboard base class + **********************************************************************/ +class wbx_base : public xcvr_dboard_base{ +public: +    wbx_base(ctor_args_t args); +    virtual ~wbx_base(void); + +protected: +    virtual void set_rx_gain(double gain, const std::string &name); +    virtual void set_tx_gain(double gain, const std::string &name); + +    virtual void set_rx_enabled(bool enb); +    virtual void set_tx_enabled(bool enb); + +    void rx_get(const wax::obj &key, wax::obj &val); +    void rx_set(const wax::obj &key, const wax::obj &val); + +    void tx_get(const wax::obj &key, wax::obj &val); +    void tx_set(const wax::obj &key, const wax::obj &val); + +    /*! +     * Set the LO frequency for the particular dboard unit. +     * \param unit which unit rx or tx +     * \param target_freq the desired frequency in Hz +     * \return the actual frequency in Hz +     */ +    virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + +    /*! +     * Get the lock detect status of the LO. +     * \param unit which unit rx or tx +     * \return true for locked +     */ +    virtual bool get_locked(dboard_iface::unit_t unit); + +private: +    uhd::dict<std::string, double> _tx_gains, _rx_gains; +    bool _rx_enabled, _tx_enabled; +}; + +}} //namespace uhd::usrp + +#endif /* INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP */ diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp new file mode 100644 index 000000000..390b4474b --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -0,0 +1,251 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +// Antenna constants +#define ANTSW_IO        ((1 << 5)|(1 << 15))    // on UNIT_TX, 0 = TX, 1 = RX, on UNIT_RX 0 = main ant, 1 = RX2 +#define ANT_TX          0                       //the tx line is transmitting +#define ANT_RX          ANTSW_IO                //the tx line is receiving +#define ANT_TXRX        0                       //the rx line is on txrx +#define ANT_RX2         ANTSW_IO                //the rx line in on rx2 +#define ANT_XX          0                       //dont care how the antenna is set + +#include "db_wbx_common.hpp" +#include <uhd/utils/static.hpp> +#include <uhd/utils/assert_has.hpp> +#include <uhd/usrp/dboard_manager.hpp> +#include <uhd/usrp/subdev_props.hpp> +#include <boost/assign/list_of.hpp> + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * The WBX Simple dboard constants + **********************************************************************/ +static const bool wbx_debug = false; + +static const freq_range_t wbx_freq_range(68.75e6, 2.2e9); + +static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); + +static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); + +/*********************************************************************** + * The WBX simple implementation + **********************************************************************/ +class wbx_simple : public wbx_base{ +public: +    wbx_simple(ctor_args_t args); +    ~wbx_simple(void); + +    void rx_get(const wax::obj &key, wax::obj &val); +    void rx_set(const wax::obj &key, const wax::obj &val); + +    void tx_get(const wax::obj &key, wax::obj &val); +    void tx_set(const wax::obj &key, const wax::obj &val); + +private: +    void set_rx_lo_freq(double freq); +    void set_tx_lo_freq(double freq); +    double _rx_lo_freq, _tx_lo_freq; + +    void set_rx_ant(const std::string &ant); +    void set_tx_ant(const std::string &ant); +    std::string _rx_ant; +}; + +/*********************************************************************** + * Register the WBX simple implementation + **********************************************************************/ +static dboard_base::sptr make_wbx_simple(dboard_base::ctor_args_t args){ +    return dboard_base::sptr(new wbx_simple(args)); +} + +UHD_STATIC_BLOCK(reg_wbx_simple_dboards){ +    dboard_manager::register_dboard(0x0053, 0x0052, &make_wbx_simple, "WBX"); +    dboard_manager::register_dboard(0x0053, 0x004f, &make_wbx_simple, "WBX + Simple GDB"); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ + +    //set the gpio directions and atr controls (antenna switches all under ATR) +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, ANTSW_IO, ANTSW_IO); +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, ANTSW_IO, ANTSW_IO); +    this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, ANTSW_IO, ANTSW_IO); +    this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, ANTSW_IO, ANTSW_IO); + +    //setup ATR for the antenna switches (constant) +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE,        ANT_XX, ANTSW_IO); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY,     ANT_RX, ANTSW_IO); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY,     ANT_TX, ANTSW_IO); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, ANT_TX, ANTSW_IO); + +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE,        ANT_XX, ANTSW_IO); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY,     ANT_XX, ANTSW_IO); +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, ANT_RX2, ANTSW_IO); + +    //set some default values +    set_rx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); +    set_tx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); +    set_rx_ant("RX2"); +} + +wbx_simple::~wbx_simple(void){ +    /* NOP */ +} + +/*********************************************************************** + * Antennas + **********************************************************************/ +void wbx_simple::set_rx_ant(const std::string &ant){ +    //validate input +    assert_has(wbx_rx_antennas, ant, "wbx rx antenna name"); + +    //shadow the setting +    _rx_ant = ant; + +    //write the new antenna setting to atr regs +    this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2), ANTSW_IO); +} + +void wbx_simple::set_tx_ant(const std::string &ant){ +    assert_has(wbx_tx_antennas, ant, "wbx tx antenna name"); +    //only one antenna option, do nothing +} + +/*********************************************************************** + * Tuning + **********************************************************************/ +void wbx_simple::set_rx_lo_freq(double freq){ +    _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, wbx_freq_range.clip(freq)); +} + +void wbx_simple::set_tx_lo_freq(double freq){ +    _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, wbx_freq_range.clip(freq)); +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void wbx_simple::rx_get(const wax::obj &key_, wax::obj &val){ +    named_prop_t key = named_prop_t::extract(key_); + +    //handle the get request conditioned on the key +    switch(key.as<subdev_prop_t>()){ +    case SUBDEV_PROP_NAME: +        val = std::string("WBX RX + Simple GDB"); +        return; + +    case SUBDEV_PROP_FREQ: +        val = _rx_lo_freq; +        return; + +    case SUBDEV_PROP_FREQ_RANGE: +        val = wbx_freq_range; +        return; + +    case SUBDEV_PROP_ANTENNA: +        val = _rx_ant; +        return; + +    case SUBDEV_PROP_ANTENNA_NAMES: +        val = wbx_rx_antennas; +        return; + +    default: +        //call into the base class for other properties +        wbx_base::rx_get(key_, val); +    } +} + +void wbx_simple::rx_set(const wax::obj &key_, const wax::obj &val){ +    named_prop_t key = named_prop_t::extract(key_); + +    //handle the get request conditioned on the key +    switch(key.as<subdev_prop_t>()){ + +    case SUBDEV_PROP_FREQ: +        this->set_rx_lo_freq(val.as<double>()); +        return; + +    case SUBDEV_PROP_ANTENNA: +        this->set_rx_ant(val.as<std::string>()); +        return; + +    default: +        //call into the base class for other properties +        wbx_base::rx_set(key_, val); +    } +} + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void wbx_simple::tx_get(const wax::obj &key_, wax::obj &val){ +    named_prop_t key = named_prop_t::extract(key_); + +    //handle the get request conditioned on the key +    switch(key.as<subdev_prop_t>()){ +    case SUBDEV_PROP_NAME: +        val = std::string("WBX TX + Simple GDB"); +        return; + +    case SUBDEV_PROP_FREQ: +        val = _tx_lo_freq; +        return; + +    case SUBDEV_PROP_FREQ_RANGE: +        val = wbx_freq_range; +        return; + +    case SUBDEV_PROP_ANTENNA: +        val = std::string("TX/RX"); +        return; + +    case SUBDEV_PROP_ANTENNA_NAMES: +        val = wbx_tx_antennas; +        return; + +    default: +        //call into the base class for other properties +        wbx_base::tx_get(key_, val); +    } +} + +void wbx_simple::tx_set(const wax::obj &key_, const wax::obj &val){ +    named_prop_t key = named_prop_t::extract(key_); + +    //handle the get request conditioned on the key +    switch(key.as<subdev_prop_t>()){ + +    case SUBDEV_PROP_FREQ: +        this->set_tx_lo_freq(val.as<double>()); +        return; + +    case SUBDEV_PROP_ANTENNA: +        this->set_tx_ant(val.as<std::string>()); +        return; + +    default: +        //call into the base class for other properties +        wbx_base::tx_set(key_, val); +    } +} diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 9055905b1..2e8b39311 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -33,33 +33,87 @@ using namespace uhd;  using namespace uhd::usrp;  /*********************************************************************** + * dboard key class to use for look-up + **********************************************************************/ +class dboard_key_t{ +public: +    dboard_key_t(const dboard_id_t &id = dboard_id_t::none()): +        _rx_id(id), _tx_id(id), _xcvr(false){} + +    dboard_key_t(const dboard_id_t &rx_id, const dboard_id_t &tx_id): +        _rx_id(rx_id), _tx_id(tx_id), _xcvr(true){} + +    dboard_id_t xx_id(void) const{ +        UHD_ASSERT_THROW(not this->is_xcvr()); +        return this->_rx_id; +    } + +    dboard_id_t rx_id(void) const{ +        UHD_ASSERT_THROW(this->is_xcvr()); +        return this->_rx_id; +    } + +    dboard_id_t tx_id(void) const{ +        UHD_ASSERT_THROW(this->is_xcvr()); +        return this->_tx_id; +    } + +    bool is_xcvr(void) const{ +        return this->_xcvr; +    } + +private: +    dboard_id_t _rx_id, _tx_id; +    bool _xcvr; +}; + +bool operator==(const dboard_key_t &lhs, const dboard_key_t &rhs){ +    if (lhs.is_xcvr() and rhs.is_xcvr()) +        return lhs.rx_id() == rhs.rx_id() and lhs.tx_id() == rhs.tx_id(); +    if (not lhs.is_xcvr() and not rhs.is_xcvr()) +        return lhs.xx_id() == rhs.xx_id(); +    return false; +} + +/***********************************************************************   * storage and registering for dboards   **********************************************************************/  //dboard registry tuple: dboard constructor, canonical name, subdev names  typedef boost::tuple<dboard_manager::dboard_ctor_t, std::string, prop_names_t> args_t;  //map a dboard id to a dboard constructor -typedef uhd::dict<dboard_id_t, args_t> id_to_args_map_t; +typedef uhd::dict<dboard_key_t, args_t> id_to_args_map_t;  UHD_SINGLETON_FCN(id_to_args_map_t, get_id_to_args_map) -void dboard_manager::register_dboard( -    const dboard_id_t &dboard_id, -    dboard_ctor_t dboard_ctor, +static void register_dboard_key( +    const dboard_key_t &dboard_key, +    dboard_manager::dboard_ctor_t dboard_ctor,      const std::string &name,      const prop_names_t &subdev_names  ){      //std::cout << "registering: " << name << std::endl; -    if (get_id_to_args_map().has_key(dboard_id)){ -        throw uhd::key_error(str(boost::format( +    if (get_id_to_args_map().has_key(dboard_key)){ + +        if (dboard_key.is_xcvr()) throw uhd::key_error(str(boost::format( +            "The dboard id pair [%s, %s] is already registered to %s." +        ) % dboard_key.rx_id().to_string() % dboard_key.tx_id().to_string() % get_id_to_args_map()[dboard_key].get<1>())); + +        else throw uhd::key_error(str(boost::format(              "The dboard id %s is already registered to %s." -        ) % dboard_id.to_string() % dboard_id.to_pp_string())); +        ) % dboard_key.xx_id().to_string() % get_id_to_args_map()[dboard_key].get<1>())); +      } -    get_id_to_args_map()[dboard_id] = args_t(dboard_ctor, name, subdev_names); +    get_id_to_args_map()[dboard_key] = args_t(dboard_ctor, name, subdev_names);  } -//map an xcvr dboard id to its partner dboard id -typedef uhd::dict<dboard_id_t, dboard_id_t> xcvr_id_to_id_map_t; -UHD_SINGLETON_FCN(xcvr_id_to_id_map_t, get_xcvr_id_to_id_map) +void dboard_manager::register_dboard( +    const dboard_id_t &dboard_id, +    dboard_ctor_t dboard_ctor, +    const std::string &name, +    const prop_names_t &subdev_names +){ +    register_dboard_key(dboard_key_t(dboard_id), dboard_ctor, name, subdev_names); +}  void dboard_manager::register_dboard(      const dboard_id_t &rx_dboard_id, @@ -68,18 +122,21 @@ void dboard_manager::register_dboard(      const std::string &name,      const prop_names_t &subdev_names  ){ -    //regular registration for ids -    register_dboard(rx_dboard_id, dboard_ctor, name, subdev_names); -    register_dboard(tx_dboard_id, dboard_ctor, name, subdev_names); - -    //register xcvr mapping for ids -    get_xcvr_id_to_id_map()[rx_dboard_id] = tx_dboard_id; -    get_xcvr_id_to_id_map()[tx_dboard_id] = rx_dboard_id; +    register_dboard_key(dboard_key_t(rx_dboard_id, tx_dboard_id), dboard_ctor, name, subdev_names);  }  std::string dboard_id_t::to_cname(void) const{ -    if (not get_id_to_args_map().has_key(*this)) return "Unknown"; -    return get_id_to_args_map()[*this].get<1>(); +    std::string cname; +    BOOST_FOREACH(const dboard_key_t &key, get_id_to_args_map().keys()){ +        if ( +            (not key.is_xcvr() and *this == key.xx_id()) or +            (key.is_xcvr() and (*this == key.rx_id() or *this == key.tx_id())) +        ){ +            if (not cname.empty()) cname += ", "; +            cname += get_id_to_args_map()[key].get<1>(); +        } +    } +    return (cname.empty())? "Unknown" : cname;  }  std::string dboard_id_t::to_pp_string(void) const{ @@ -172,34 +229,6 @@ dboard_manager::sptr dboard_manager::make(  /***********************************************************************   * implementation class methods   **********************************************************************/ -static args_t get_dboard_args( -    dboard_iface::unit_t unit, -    dboard_id_t dboard_id, -    bool force_to_unknown = false -){ -    //special case, the none id was provided, use the following ids -    if (dboard_id == dboard_id_t::none() or force_to_unknown){ -        UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff1)); -        UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff0)); -        switch(unit){ -        case dboard_iface::UNIT_RX: return get_dboard_args(unit, 0xfff1); -        case dboard_iface::UNIT_TX: return get_dboard_args(unit, 0xfff0); -        default: UHD_THROW_INVALID_CODE_PATH(); -        } -    } - -    //verify that there is a registered constructor for this id -    if (not get_id_to_args_map().has_key(dboard_id)){ -        uhd::warning::post(str(boost::format( -            "Unknown dboard ID: %s.\n" -        ) % dboard_id.to_pp_string())); -        return get_dboard_args(unit, dboard_id, true); -    } - -    //return the dboard args for this id -    return get_id_to_args_map()[dboard_id]; -} -  dboard_manager_impl::dboard_manager_impl(      dboard_id_t rx_dboard_id,      dboard_id_t tx_dboard_id, @@ -219,35 +248,30 @@ dboard_manager_impl::dboard_manager_impl(  void dboard_manager_impl::init(      dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id  ){ -    //determine xcvr status -    bool rx_dboard_is_xcvr = get_xcvr_id_to_id_map().has_key(rx_dboard_id); -    bool tx_dboard_is_xcvr = get_xcvr_id_to_id_map().has_key(tx_dboard_id); -    bool this_dboard_is_xcvr = ( -        rx_dboard_is_xcvr and tx_dboard_is_xcvr and -        (get_xcvr_id_to_id_map()[rx_dboard_id] == tx_dboard_id) and -        (get_xcvr_id_to_id_map()[tx_dboard_id] == rx_dboard_id) -    ); +    //find the dboard key matches for the dboard ids +    dboard_key_t rx_dboard_key, tx_dboard_key, xcvr_dboard_key; +    BOOST_FOREACH(const dboard_key_t &key, get_id_to_args_map().keys()){ +        if (key.is_xcvr()){ +            if (rx_dboard_id == key.rx_id() and tx_dboard_id == key.tx_id()) xcvr_dboard_key = key; +            if (rx_dboard_id == key.rx_id()) rx_dboard_key = key; //kept to handle warning +            if (tx_dboard_id == key.tx_id()) tx_dboard_key = key; //kept to handle warning +        } +        else{ +            if (rx_dboard_id == key.xx_id()) rx_dboard_key = key; +            if (tx_dboard_id == key.xx_id()) tx_dboard_key = key; +        } +    }      //warn for invalid dboard id xcvr combinations -    if (rx_dboard_is_xcvr != this_dboard_is_xcvr or tx_dboard_is_xcvr != this_dboard_is_xcvr){ +    if (not xcvr_dboard_key.is_xcvr() and (rx_dboard_key.is_xcvr() or tx_dboard_key.is_xcvr())){          uhd::warning::post(str(boost::format( -            "Unknown transceiver board ID combination...\n" +            "Unknown transceiver board ID combination.\n" +            "Is your daughter-board mounted properly?\n"              "RX dboard ID: %s\n"              "TX dboard ID: %s\n"          ) % rx_dboard_id.to_pp_string() % tx_dboard_id.to_pp_string()));      } -    //extract dboard constructor and settings (force to unknown for messed up xcvr status) -    dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; -    boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args( -        dboard_iface::UNIT_RX, rx_dboard_id, rx_dboard_is_xcvr != this_dboard_is_xcvr -    ); - -    dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; -    boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args( -        dboard_iface::UNIT_TX, tx_dboard_id, tx_dboard_is_xcvr != this_dboard_is_xcvr -    ); -      //initialize the gpio pins before creating subdevs      set_nice_dboard_if(); @@ -255,15 +279,19 @@ void dboard_manager_impl::init(      dboard_ctor_args_t db_ctor_args;      db_ctor_args.db_iface = _iface; -    //make xcvr subdevs (make one subdev for both rx and tx dboards) -    if (this_dboard_is_xcvr){ -        UHD_ASSERT_THROW(rx_dboard_ctor == tx_dboard_ctor); -        UHD_ASSERT_THROW(rx_subdevs == tx_subdevs); -        BOOST_FOREACH(const std::string &subdev, rx_subdevs){ +    //make xcvr subdevs +    if (xcvr_dboard_key.is_xcvr()){ + +        //extract data for the xcvr dboard key +        dboard_ctor_t dboard_ctor; std::string name; prop_names_t subdevs; +        boost::tie(dboard_ctor, name, subdevs) = get_id_to_args_map()[xcvr_dboard_key]; + +        //create the xcvr object for each subdevice +        BOOST_FOREACH(const std::string &subdev, subdevs){              db_ctor_args.sd_name = subdev;              db_ctor_args.rx_id = rx_dboard_id;              db_ctor_args.tx_id = tx_dboard_id; -            dboard_base::sptr xcvr_dboard = rx_dboard_ctor(&db_ctor_args); +            dboard_base::sptr xcvr_dboard = dboard_ctor(&db_ctor_args);              //create a rx proxy for this xcvr board              _rx_dboards[subdev] = subdev_proxy::sptr(                  new subdev_proxy(xcvr_dboard, subdev_proxy::RX_TYPE) @@ -277,6 +305,16 @@ void dboard_manager_impl::init(      //make tx and rx subdevs (separate subdevs for rx and tx dboards)      else{ + +        //force the rx key to the unknown board for bad combinations +        if (rx_dboard_key.is_xcvr() or rx_dboard_key.xx_id() == dboard_id_t::none()){ +            rx_dboard_key = dboard_key_t(0xfff1); +        } + +        //extract data for the rx dboard key +        dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; +        boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_id_to_args_map()[rx_dboard_key]; +          //make the rx subdevs          BOOST_FOREACH(const std::string &subdev, rx_subdevs){              db_ctor_args.sd_name = subdev; @@ -288,6 +326,16 @@ void dboard_manager_impl::init(                  new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE)              );          } + +        //force the tx key to the unknown board for bad combinations +        if (tx_dboard_key.is_xcvr() or tx_dboard_key.xx_id() == dboard_id_t::none()){ +            tx_dboard_key = dboard_key_t(0xfff0); +        } + +        //extract data for the tx dboard key +        dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; +        boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_id_to_args_map()[tx_dboard_key]; +          //make the tx subdevs          BOOST_FOREACH(const std::string &subdev, tx_subdevs){              db_ctor_args.sd_name = subdev; diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index 02906fc45..df0bb6261 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -59,6 +59,7 @@ void usrp1_impl::dboard_init(void)          //read the tx and rx dboard eeproms          _rx_db_eeproms[dboard_slot].load(*_iface, get_rx_ee_addr(dboard_slot));          _tx_db_eeproms[dboard_slot].load(*_iface, get_tx_ee_addr(dboard_slot)); +        _gdb_eeproms[dboard_slot].load(*_iface, get_tx_ee_addr(dboard_slot) ^ 5);          //create a new dboard interface and manager          _dboard_ifaces[dboard_slot] = make_dboard_iface( @@ -68,7 +69,7 @@ void usrp1_impl::dboard_init(void)          _dboard_managers[dboard_slot] = dboard_manager::make(              _rx_db_eeproms[dboard_slot].id, -            _tx_db_eeproms[dboard_slot].id, +            ((_gdb_eeproms[dboard_slot].id == dboard_id_t::none())? _tx_db_eeproms[dboard_slot] : _gdb_eeproms[dboard_slot]).id,              _dboard_ifaces[dboard_slot]          ); @@ -171,6 +172,10 @@ void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_          val = _tx_db_eeproms[dboard_slot];          return; +    case DBOARD_PROP_GBOARD_EEPROM: +        val = _gdb_eeproms[dboard_slot]; +        return; +      case DBOARD_PROP_DBOARD_IFACE:          val = _dboard_ifaces[dboard_slot];          return; @@ -203,6 +208,11 @@ void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val, dboard_          _tx_db_eeproms[dboard_slot].store(*_iface, get_tx_ee_addr(dboard_slot));          return; +    case DBOARD_PROP_GBOARD_EEPROM: +        _gdb_eeproms[dboard_slot] = val.as<dboard_eeprom_t>(); +        _gdb_eeproms[dboard_slot].store(*_iface, get_tx_ee_addr(dboard_slot) ^ 5); +        return; +      default: UHD_THROW_PROP_SET_ERROR();      }  } diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 9755c466d..f53894b29 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -175,7 +175,7 @@ private:      uhd::dict<dboard_slot_t, wax_obj_proxy::sptr> _rx_dboard_proxies;      //tx dboard functions and settings -    uhd::dict<dboard_slot_t, uhd::usrp::dboard_eeprom_t> _tx_db_eeproms; +    uhd::dict<dboard_slot_t, uhd::usrp::dboard_eeprom_t> _tx_db_eeproms, _gdb_eeproms;      void tx_dboard_get(const wax::obj &, wax::obj &, dboard_slot_t);      void tx_dboard_set(const wax::obj &, const wax::obj &, dboard_slot_t);      uhd::dict<dboard_slot_t, wax_obj_proxy::sptr> _tx_dboard_proxies; diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 3f41cddcf..8c6379d66 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -38,11 +38,14 @@ void usrp2_mboard_impl::dboard_init(void){      //read the dboard eeprom to extract the dboard ids      _rx_db_eeprom.load(*_iface, USRP2_I2C_ADDR_RX_DB);      _tx_db_eeprom.load(*_iface, USRP2_I2C_ADDR_TX_DB); +    _gdb_eeprom.load(*_iface, USRP2_I2C_ADDR_TX_DB ^ 5);      //create a new dboard interface and manager      _dboard_iface = make_usrp2_dboard_iface(_iface, _clock_ctrl);      _dboard_manager = dboard_manager::make( -        _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface +        _rx_db_eeprom.id, +        ((_gdb_eeprom.id == dboard_id_t::none())? _tx_db_eeprom : _gdb_eeprom).id, +        _dboard_iface      );      //load dboards @@ -137,6 +140,10 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){          val = _tx_db_eeprom;          return; +    case DBOARD_PROP_GBOARD_EEPROM: +        val = _gdb_eeprom; +        return; +      case DBOARD_PROP_DBOARD_IFACE:          val = _dboard_iface;          return; @@ -166,6 +173,11 @@ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){          _tx_db_eeprom.store(*_iface, USRP2_I2C_ADDR_TX_DB);          return; +    case DBOARD_PROP_GBOARD_EEPROM: +        _gdb_eeprom = val.as<dboard_eeprom_t>(); +        _gdb_eeprom.store(*_iface, USRP2_I2C_ADDR_TX_DB ^ 5); +        return; +      default: UHD_THROW_PROP_SET_ERROR();      }  } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 0676cecf2..e9ff22b13 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -147,7 +147,7 @@ private:      void tx_dboard_get(const wax::obj &, wax::obj &);      void tx_dboard_set(const wax::obj &, const wax::obj &);      wax_obj_proxy::sptr _tx_dboard_proxy; -    uhd::usrp::dboard_eeprom_t _tx_db_eeprom; +    uhd::usrp::dboard_eeprom_t _tx_db_eeprom, _gdb_eeprom;      //methods and shadows for the dsps      UHD_PIMPL_DECL(dsp_impl) _dsp_impl; diff --git a/host/lib/usrp/usrp_e100/dboard_impl.cpp b/host/lib/usrp/usrp_e100/dboard_impl.cpp index 0b89fed9f..f6bbbd5e8 100644 --- a/host/lib/usrp/usrp_e100/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/dboard_impl.cpp @@ -31,15 +31,19 @@ using namespace uhd::usrp;   * Dboard Initialization   **********************************************************************/  void usrp_e100_impl::dboard_init(void){ +    //read the dboard eeprom to extract the dboard ids      _rx_db_eeprom.load(*_iface, I2C_ADDR_RX_DB);      _tx_db_eeprom.load(*_iface, I2C_ADDR_TX_DB); +    _gdb_eeprom.load(*_iface, I2C_ADDR_TX_DB ^ 5);      //create a new dboard interface and manager      _dboard_iface = make_usrp_e100_dboard_iface(          _iface, _clock_ctrl, _codec_ctrl      );      _dboard_manager = dboard_manager::make( -        _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface +        _rx_db_eeprom.id, +        ((_gdb_eeprom.id == dboard_id_t::none())? _tx_db_eeprom : _gdb_eeprom).id, +        _dboard_iface      );      //setup the dboard proxies @@ -136,6 +140,10 @@ void usrp_e100_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){          val = _tx_db_eeprom;          return; +    case DBOARD_PROP_GBOARD_EEPROM: +        val = _gdb_eeprom; +        return; +      case DBOARD_PROP_DBOARD_IFACE:          val = _dboard_iface;          return; @@ -167,6 +175,11 @@ void usrp_e100_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){          _tx_db_eeprom.store(*_iface, I2C_ADDR_TX_DB);          return; +    case DBOARD_PROP_GBOARD_EEPROM: +        _gdb_eeprom = val.as<dboard_eeprom_t>(); +        _gdb_eeprom.store(*_iface, I2C_ADDR_TX_DB ^ 5); +        return; +      default: UHD_THROW_PROP_SET_ERROR();      }  } diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp index 98117cf26..737aa4e8f 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp @@ -132,7 +132,7 @@ private:      wax_obj_proxy::sptr _rx_dboard_proxy;      //tx dboard functions and settings -    uhd::usrp::dboard_eeprom_t _tx_db_eeprom; +    uhd::usrp::dboard_eeprom_t _tx_db_eeprom, _gdb_eeprom;      void tx_dboard_get(const wax::obj &, wax::obj &);      void tx_dboard_set(const wax::obj &, const wax::obj &);      wax_obj_proxy::sptr _tx_dboard_proxy; diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp index b32131b2a..3ea63c4bb 100644 --- a/host/utils/uhd_usrp_probe.cpp +++ b/host/utils/uhd_usrp_probe.cpp @@ -27,6 +27,7 @@  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dboard_id.hpp>  #include <uhd/usrp/mboard_eeprom.hpp> +#include <uhd/usrp/dboard_eeprom.hpp>  #include <boost/program_options.hpp>  #include <boost/format.hpp>  #include <boost/foreach.hpp> @@ -46,12 +47,12 @@ static std::string make_border(const std::string &text){      ss << boost::format("  _____________________________________________________") << std::endl;      ss << boost::format(" /") << std::endl;      std::vector<std::string> lines; boost::split(lines, text, boost::is_any_of("\n")); -    while (lines.back() == "") lines.pop_back(); //strip trailing newlines +    while (lines.back().empty()) lines.pop_back(); //strip trailing newlines      if (lines.size()) lines[0] = "    " + lines[0]; //indent the title line      BOOST_FOREACH(const std::string &line, lines){          ss << boost::format("|   %s") % line << std::endl;      } -    //ss << boost::format(" \\____________________________________________________") << std::endl; +    //ss << boost::format(" \\_____________________________________________________") << std::endl;      return ss.str();  } @@ -114,6 +115,14 @@ static std::string get_dboard_pp_string(const std::string &type, wax::obj dboard      std::stringstream ss;      ss << boost::format("%s Dboard: %s") % type % dboard[usrp::DBOARD_PROP_NAME].as<std::string>() << std::endl;      //ss << std::endl; +    usrp::dboard_eeprom_t db_eeprom = dboard[usrp::DBOARD_PROP_DBOARD_EEPROM].as<usrp::dboard_eeprom_t>(); +    if (db_eeprom.id != usrp::dboard_id_t::none()) ss << boost::format("ID: %s") % db_eeprom.id.to_pp_string() << std::endl; +    if (not db_eeprom.serial.empty()) ss << boost::format("Serial: %s") % db_eeprom.serial << std::endl; +    if (type == "TX"){ +        usrp::dboard_eeprom_t gdb_eeprom = dboard[usrp::DBOARD_PROP_GBOARD_EEPROM].as<usrp::dboard_eeprom_t>(); +        if (gdb_eeprom.id != usrp::dboard_id_t::none()) ss << boost::format("GDB ID: %s") % gdb_eeprom.id.to_pp_string() << std::endl; +        if (not gdb_eeprom.serial.empty()) ss << boost::format("GDB Serial: %s") % gdb_eeprom.serial << std::endl; +    }      BOOST_FOREACH(const std::string &subdev_name, dboard[usrp::DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>()){          ss << make_border(get_subdev_pp_string(type, dboard[named_prop_t(usrp::DBOARD_PROP_SUBDEV, subdev_name)]));      } @@ -132,14 +141,14 @@ static std::string get_mboard_pp_string(wax::obj mboard){      BOOST_FOREACH(const std::string &dsp_name, mboard[usrp::MBOARD_PROP_RX_DSP_NAMES].as<prop_names_t>()){          ss << make_border(get_dsp_pp_string("RX", mboard[named_prop_t(usrp::MBOARD_PROP_RX_DSP, dsp_name)]));      } +    BOOST_FOREACH(const std::string &db_name, mboard[usrp::MBOARD_PROP_RX_DBOARD_NAMES].as<prop_names_t>()){ +        ss << make_border(get_dboard_pp_string("RX", mboard[named_prop_t(usrp::MBOARD_PROP_RX_DBOARD, db_name)])); +    }      BOOST_FOREACH(const std::string &dsp_name, mboard[usrp::MBOARD_PROP_TX_DSP_NAMES].as<prop_names_t>()){          ss << make_border(get_dsp_pp_string("TX", mboard[named_prop_t(usrp::MBOARD_PROP_TX_DSP, dsp_name)]));      } -    BOOST_FOREACH(const std::string &dsp_name, mboard[usrp::MBOARD_PROP_RX_DBOARD_NAMES].as<prop_names_t>()){ -        ss << make_border(get_dboard_pp_string("RX", mboard[named_prop_t(usrp::MBOARD_PROP_RX_DBOARD, dsp_name)])); -    } -    BOOST_FOREACH(const std::string &dsp_name, mboard[usrp::MBOARD_PROP_TX_DBOARD_NAMES].as<prop_names_t>()){ -        ss << make_border(get_dboard_pp_string("TX", mboard[named_prop_t(usrp::MBOARD_PROP_TX_DBOARD, dsp_name)])); +    BOOST_FOREACH(const std::string &db_name, mboard[usrp::MBOARD_PROP_TX_DBOARD_NAMES].as<prop_names_t>()){ +        ss << make_border(get_dboard_pp_string("TX", mboard[named_prop_t(usrp::MBOARD_PROP_TX_DBOARD, db_name)]));      }      return ss.str();  } diff --git a/host/utils/usrp_burn_db_eeprom.cpp b/host/utils/usrp_burn_db_eeprom.cpp index 617417e09..58417bd68 100644 --- a/host/utils/usrp_burn_db_eeprom.cpp +++ b/host/utils/usrp_burn_db_eeprom.cpp @@ -37,10 +37,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      //command line variables      std::string args, slot, unit;      static const uhd::dict<std::string, mboard_prop_t> unit_to_db_prop = boost::assign::map_list_of -        ("RX", MBOARD_PROP_RX_DBOARD) ("TX", MBOARD_PROP_TX_DBOARD) +        ("RX", MBOARD_PROP_RX_DBOARD) ("TX", MBOARD_PROP_TX_DBOARD) ("GDB", MBOARD_PROP_TX_DBOARD)      ;      static const uhd::dict<std::string, mboard_prop_t> unit_to_db_names_prop = boost::assign::map_list_of -        ("RX", MBOARD_PROP_RX_DBOARD_NAMES) ("TX", MBOARD_PROP_TX_DBOARD_NAMES) +        ("RX", MBOARD_PROP_RX_DBOARD_NAMES) ("TX", MBOARD_PROP_TX_DBOARD_NAMES) ("GDB", MBOARD_PROP_TX_DBOARD_NAMES) +    ; +    static const uhd::dict<std::string, dboard_prop_t> unit_to_db_eeprom_prop = boost::assign::map_list_of +        ("RX", DBOARD_PROP_DBOARD_EEPROM) ("TX", DBOARD_PROP_DBOARD_EEPROM) ("GDB", DBOARD_PROP_GBOARD_EEPROM)      ;      po::options_description desc("Allowed options"); @@ -48,7 +51,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("help", "help message")          ("args", po::value<std::string>(&args)->default_value(""),    "device address args [default = \"\"]")          ("slot", po::value<std::string>(&slot)->default_value(""),    "dboard slot name [default is blank for automatic]") -        ("unit", po::value<std::string>(&unit)->default_value(""),    "which unit [RX or TX]") +        ("unit", po::value<std::string>(&unit)->default_value(""),    "which unit [RX, TX, or GDB]")          ("id",   po::value<std::string>(),                            "dboard id to burn, omit for readback")          ("ser",  po::value<std::string>(),                            "serial to burn, omit for readback")      ; @@ -82,19 +85,19 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      std::string prefix = unit + ":" + slot;      std::cout << boost::format("Reading EEPROM on %s dboard...") % prefix << std::endl; -    dboard_eeprom_t db_eeprom = dboard[DBOARD_PROP_DBOARD_EEPROM].as<dboard_eeprom_t>(); +    dboard_eeprom_t db_eeprom = dboard[unit_to_db_eeprom_prop[unit]].as<dboard_eeprom_t>();      //------------- handle the dboard ID -----------------------------//      if (vm.count("id")){          db_eeprom.id = dboard_id_t::from_string(vm["id"].as<std::string>()); -        dboard[DBOARD_PROP_DBOARD_EEPROM] = db_eeprom; +        dboard[unit_to_db_eeprom_prop[unit]] = db_eeprom;      }      std::cout << boost::format("  Current ID: %s") % db_eeprom.id.to_pp_string() << std::endl;      //------------- handle the dboard serial--------------------------//      if (vm.count("ser")){          db_eeprom.serial = vm["ser"].as<std::string>(); -        dboard[DBOARD_PROP_DBOARD_EEPROM] = db_eeprom; +        dboard[unit_to_db_eeprom_prop[unit]] = db_eeprom;      }      std::cout << boost::format("  Current serial: \"%s\"") % db_eeprom.serial << std::endl; | 
