diff options
Diffstat (limited to 'host/lib/usrp/dboard')
-rw-r--r-- | host/lib/usrp/dboard/CMakeLists.txt | 5 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_wbx_common.cpp (renamed from host/lib/usrp/dboard/db_wbx.cpp) | 266 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_wbx_common.hpp | 72 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_wbx_simple.cpp | 251 |
4 files changed, 398 insertions, 196 deletions
diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 7bd201294..1687713a9 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,7 +23,8 @@ 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_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_wbx.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp index 2e9a1edc8..3ad2dac6a 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) + * WBX Common Implementation **********************************************************************/ -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_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 @@ -464,10 +350,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 +385,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 +405,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 +429,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 +457,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 +485,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 +505,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 +529,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); + } +} |