aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-04-26 17:54:41 -0700
committerJosh Blum <josh@joshknows.com>2011-04-26 17:54:41 -0700
commit3ff2780a82eed3bbca8f6a9f52f31746de42ea40 (patch)
treef11a4056ccdba38ea1cc342ee5e265307c50851b /host/lib/usrp
parent190d7cd9d5206113fad22111107034cb52c3c28b (diff)
parent1a81e2a35ff1d288e87eb1e65911c1a97588217c (diff)
downloaduhd-3ff2780a82eed3bbca8f6a9f52f31746de42ea40.tar.gz
uhd-3ff2780a82eed3bbca8f6a9f52f31746de42ea40.tar.bz2
uhd-3ff2780a82eed3bbca8f6a9f52f31746de42ea40.zip
Merge branch 'gdb_support'
Conflicts: host/lib/usrp/dboard/CMakeLists.txt
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/dboard/CMakeLists.txt5
-rw-r--r--host/lib/usrp/dboard/db_sbx.cpp2
-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.hpp72
-rw-r--r--host/lib/usrp/dboard/db_wbx_simple.cpp251
-rw-r--r--host/lib/usrp/dboard_manager.cpp198
-rw-r--r--host/lib/usrp/usrp1/dboard_impl.cpp12
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.hpp2
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp14
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp2
-rw-r--r--host/lib/usrp/usrp_e100/dboard_impl.cpp15
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.hpp2
12 files changed, 592 insertions, 278 deletions
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;