diff options
author | Nick Foster <nick@nerdnetworks.org> | 2010-10-12 14:46:41 -0700 |
---|---|---|
committer | Nick Foster <nick@nerdnetworks.org> | 2010-10-12 14:46:41 -0700 |
commit | 5982ec4ee2c6f9efca1c5068e42dc38b822df7dc (patch) | |
tree | 6b15ce5f837ea57cc5c9fdf79e45fdbd2f44d9de /host/lib/usrp | |
parent | 3df994e1c784d7037e869610f1417fe64e0e89a8 (diff) | |
download | uhd-5982ec4ee2c6f9efca1c5068e42dc38b822df7dc.tar.gz uhd-5982ec4ee2c6f9efca1c5068e42dc38b822df7dc.tar.bz2 uhd-5982ec4ee2c6f9efca1c5068e42dc38b822df7dc.zip |
USRP2P: This is surprisingly involved. Adding a consistent interface to deal with hardware revisions.
Diffstat (limited to 'host/lib/usrp')
-rw-r--r-- | host/lib/usrp/mboard_rev.cpp | 68 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/clock_ctrl.cpp | 36 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/codec_impl.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 3 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 30 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_clk_regs.hpp | 15 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 1 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_regs.hpp | 2 |
10 files changed, 125 insertions, 44 deletions
diff --git a/host/lib/usrp/mboard_rev.cpp b/host/lib/usrp/mboard_rev.cpp new file mode 100644 index 000000000..8206d12af --- /dev/null +++ b/host/lib/usrp/mboard_rev.cpp @@ -0,0 +1,68 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/mboard_rev.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/format.hpp> +#include <sstream> +#include <iostream> + +using namespace uhd::usrp; + +mboard_rev_t::mboard_rev_t(boost::uint16_t id){ + _rev = rev; +} + +mboard_rev_t mboard_rev_t::none(void){ + return mboard_rev_t(); +} + +mboard_rev_t mboard_rev_t::from_uint16(boost::uint16_t uint16){ + return mboard_rev_t(uint16); +} + +boost::uint16_t mboard_rev_t::to_uint16(void) const{ + return _rev; +} + +//used with lexical cast to parse a hex string +template <class T> struct to_hex{ + T value; + operator T() const {return value;} + friend std::istream& operator>>(std::istream& in, to_hex& out){ + in >> std::hex >> out.value; + return in; + } +}; + +mboard_rev_t mboard_rev_t::from_string(const std::string &string){ + if (string.substr(0, 2) == "0x"){ + return mboard_rev_t::from_uint16(boost::lexical_cast<to_hex<boost::uint16_t> >(string)); + } + return mboard_rev_t::from_uint16(boost::lexical_cast<boost::uint16_t>(string)); +} + +std::string mboard_rev_t::to_string(void) const{ + return str(boost::format("0x%04x") % this->to_uint16()); +} + +//Note: to_pp_string is implemented in the dboard manager +//because it needs access to the dboard registration table + +bool uhd::usrp::operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs){ + return lhs.to_uint16() == rhs.to_uint16(); +} diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index c3dc4917e..8887faf12 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -17,6 +17,7 @@ #include "clock_ctrl.hpp" #include "ad9510_regs.hpp" +#include <uhd/usrp/mboard_rev.hpp> #include "usrp2_regs.hpp" //spi slave constants #include "usrp2_clk_regs.hpp" #include <uhd/utils/assert.hpp> @@ -31,9 +32,7 @@ using namespace uhd; class usrp2_clock_ctrl_impl : public usrp2_clock_ctrl{ public: usrp2_clock_ctrl_impl(usrp2_iface::sptr iface){ - _iface = iface; //_iface has get_hw_rev(), which lets us know if it's a USRP2+ (>=0x80) or USRP2 (<0x80). - - clk_regs = usrp2_clk_regs_t(_iface->get_hw_rev()); + clk_regs = usrp2_clk_regs_t(iface->get_hw_rev()); _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; this->write_reg(clk_regs.pll_3); @@ -86,16 +85,13 @@ public: } void enable_mimo_clock_out(bool enb){ - //FIXME TODO put this revision read in a common place - boost::uint8_t rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0); - //calculate the low and high dividers size_t divider = size_t(this->get_master_clock_rate()/10e6); size_t high = divider/2; size_t low = divider - high; - switch(rev_hi){ - case 3: //clock 2 + switch(clk_regs.exp){ + case 2: //U2 rev 3 _ad9510_regs.power_down_lvpecl_out2 = enb? ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL : ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; @@ -104,11 +100,9 @@ public: _ad9510_regs.divider_low_cycles_out2 = low - 1; _ad9510_regs.divider_high_cycles_out2 = high - 1; _ad9510_regs.bypass_divider_out2 = 0; - this->write_reg(0x3e); - this->write_reg(0x4c); break; - case 4: //clock 5 + case 5: //U2 rev 4 _ad9510_regs.power_down_lvds_cmos_out5 = enb? 0 : 1; _ad9510_regs.lvds_cmos_select_out5 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_LVDS; _ad9510_regs.output_level_lvds_out5 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; @@ -116,19 +110,26 @@ public: _ad9510_regs.divider_low_cycles_out5 = low - 1; _ad9510_regs.divider_high_cycles_out5 = high - 1; _ad9510_regs.bypass_divider_out5 = 0; - this->write_reg(0x41); - this->write_reg(0x52); + break; + + case 6: //U2+ + _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_LVDS; + _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; + //set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out6 = low - 1; + _ad9510_regs.divider_high_cycles_out6 = high - 1; + _ad9510_regs.bypass_divider_out5 = 0; break; - //TODO FIXME do i want to throw, what about uninitialized boards? - //default: throw std::runtime_error("unknown rev hi in mboard eeprom"); - default: std::cerr << "unknown rev hi: " << rev_hi << std::endl; + default: } + this->write_reg(clk_regs.output(clk_regs.exp)); + this->write_reg(clk_regs.div_lo(clk_regs.exp)); this->update_regs(); } //uses output clock 7 (cmos) - //this clock is the same between USRP2 and USRP2+ and so this fn does not get a switch statement void enable_rx_dboard_clock(bool enb){ _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; @@ -297,7 +298,6 @@ private: } usrp2_clk_regs_t clk_regs; - usrp2_iface::sptr _iface; ad9510_regs_t _ad9510_regs; }; diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index db98e50ab..04a11d922 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -67,7 +67,7 @@ void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_NAMES: - if(_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV) { + if(_iface->get_hw_rev().to_uint16() >= USRP2P_FIRST_HW_REV) { val = prop_names_t(codec_rx_gain_ranges.keys()); } else val = prop_names_t(); return; @@ -94,7 +94,7 @@ void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ switch(key.as<codec_prop_t>()) { case CODEC_PROP_GAIN_I: case CODEC_PROP_GAIN_Q: - if(_iface->get_hw_rev() < USRP2P_FIRST_HW_REV) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P + if(_iface->get_hw_rev().to_uint16() < USRP2P_FIRST_HW_REV) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P gain = val.as<float>(); this->rx_codec_set_gain(gain, key.name); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 67955c831..6c9596092 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -55,8 +55,7 @@ extern "C" { //////////////////////////////////////////////////////////////////////// // EEPROM Layout //////////////////////////////////////////////////////////////////////// -#define USRP2_EE_MBOARD_REV_LSB 0x00 //1 byte -#define USRP2_EE_MBOARD_REV_MSB 0x01 //1 byte +#define USRP2_EE_MBOARD_REV 0x00 //2 bytes, little-endian (historic, don't blame me) #define USRP2_EE_MBOARD_MAC_ADDR 0x02 //6 bytes #define USRP2_EE_MBOARD_IP_ADDR 0x0C //uint32, big-endian #define USRP2_EE_MBOARD_BOOTLOADER_FLAGS 0xF7 diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index e0e0d726e..6ee6d03a1 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -20,6 +20,7 @@ #include <uhd/usrp/misc_utils.hpp> #include <uhd/usrp/dsp_utils.hpp> #include <uhd/usrp/mboard_props.hpp> +#include <uhd/usrp/mboard_rev.hpp> #include <uhd/utils/assert.hpp> #include <uhd/utils/algorithm.hpp> #include <uhd/types/mac_addr.hpp> @@ -49,12 +50,9 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface = usrp2_iface::make(ctrl_transport); //extract the mboard rev numbers - _rev_lo = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, 1).at(0); - _rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0); - - //set the device revision (USRP2 or USRP2+) based on the above - _iface->set_hw_rev((_rev_hi << 8) | _rev_lo); - + byte_vector_t rev_bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, 2); + _iface->set_hw_rev(mboard_rev_t::from_uint16(rev_bytes.at(0) | (revbytes.at(1) << 8))); + //contruct the interfaces to mboard perifs _clock_ctrl = usrp2_clock_ctrl::make(_iface); _codec_ctrl = usrp2_codec_ctrl::make(_iface); @@ -224,12 +222,17 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){ val = boost::asio::ip::address_v4(bytes).to_string(); return; } - } + + if (key.as<std::string>() == "hw-rev"){ + //extract the mboard rev numbers + val = _iface->get_hw_rev().to_string(); + return; + } //handle the get request conditioned on the key switch(key.as<mboard_prop_t>()){ case MBOARD_PROP_NAME: - val = str(boost::format("usrp2 mboard%d - rev %d:%d") % _index % _rev_hi % _rev_lo); + val = str(boost::format("usrp2 mboard%d - rev %s") % _index % _iface->get_hw_rev().to_string()); return; case MBOARD_PROP_OTHERS:{ @@ -321,9 +324,18 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){ _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, bytes); return; } + + if (key.as<std::string>() == "hw-rev"){ + mboard_rev_t rev = mboard_rev_t::from_string(val.as<std::string>()); + byte_vector_t revbytes(2); + revbytes(1) = rev.to_uint16() >> 8; + revbytes(0) = rev.to_uint16() & 0xff; + _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, revbytes); + _iface->set_hw_rev(rev); //so the iface knows what rev it is + return; } - //handle the get request conditioned on the key + //handle the set request conditioned on the key switch(key.as<mboard_prop_t>()){ case MBOARD_PROP_CLOCK_CONFIG: diff --git a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp index d057fb342..edbdfa15d 100644 --- a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp @@ -18,19 +18,24 @@ #ifndef INCLUDED_USRP2_CLK_REGS_HPP #define INCLUDED_USRP2_CLK_REGS_HPP +#include <uhd/usrp/mboard_rev.hpp> #include "usrp2_regs.hpp" class usrp2_clk_regs_t { public: usrp2_clk_regs_t(void) { ; } - usrp2_clk_regs_t(int hw_rev) { + usrp2_clk_regs_t(uhd::usrp::mboard_rev_t hw_rev) { test = 0; fpga = 1; - adc = (hw_rev>=USRP2P_FIRST_HW_REV) ? 2 : 4; + adc = (hw_rev.is_usrp2p()) ? 2 : 4; dac = 3; - serdes = (hw_rev>=USRP2P_FIRST_HW_REV) ? 4 : 2; //only used by usrp2+ - tx_db = (hw_rev>=USRP2P_FIRST_HW_REV) ? 5 : 6; - exp = (hw_rev>=USRP2P_FIRST_HW_REV) ? 6 : 5; + serdes = (hw_rev.is_usrp2p()) ? 4 : 2; //only used by usrp2+ + tx_db = (hw_rev.is_usrp2p()) ? 5 : 6; + + if(hw_rev.major() == 3) exp = 2; + else if(hw_rev.major() >= 4) exp = 5; + else if(hw_rev.major() > 10) exp = 6; + rx_db = 7; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 0771c4945..7ce5cc936 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -260,12 +260,12 @@ public: /*********************************************************************** * Get/set hardware revision **********************************************************************/ - void set_hw_rev(int rev) { + void set_hw_rev(mboard_rev_t rev) { hw_rev = rev; regs = usrp2_get_regs(rev); //might be a better place to do this } - int get_hw_rev(void) { + mboard_rev_t get_hw_rev(void) { return hw_rev; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 55fbfa7e4..fe2687d02 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -112,12 +112,12 @@ public: * Set the hardware revision number. Also selects the proper register set for the device. * \param rev the 16-bit revision */ - virtual void set_hw_rev(int rev) = 0; + virtual void set_hw_rev(uhd::usrp::mboard_rev_t rev) = 0; /*! Return the hardware revision number * \return hardware revision */ - virtual int get_hw_rev(void) = 0; + virtual uhd::usrp::mboard_rev_t get_hw_rev(void) = 0; /*! * Register map selected from USRP2/USRP2+. @@ -126,7 +126,7 @@ public: /*! * Hardware revision as returned by the device. */ - int hw_rev; + uhd::usrp::mboard_rev_t hw_rev; }; #endif /* INCLUDED_USRP2_IFACE_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index b81711e2b..1ebd90ca4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -95,7 +95,6 @@ public: private: size_t _index; - int _rev_hi, _rev_lo; const size_t _recv_frame_size; //properties for this mboard diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index f74c78b7b..8dae843ab 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -18,8 +18,6 @@ #ifndef INCLUDED_USRP2_REGS_HPP #define INCLUDED_USRP2_REGS_HPP -//these are used to set the - #define USRP2_MISC_OUTPUT_BASE 0xD400 #define USRP2_GPIO_BASE 0xC800 #define USRP2_ATR_BASE 0xE400 |