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; |