aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
authorNick Foster <nick@nerdnetworks.org>2010-10-12 14:46:41 -0700
committerNick Foster <nick@nerdnetworks.org>2010-10-12 14:46:41 -0700
commit5982ec4ee2c6f9efca1c5068e42dc38b822df7dc (patch)
tree6b15ce5f837ea57cc5c9fdf79e45fdbd2f44d9de /host/lib/usrp
parent3df994e1c784d7037e869610f1417fe64e0e89a8 (diff)
downloaduhd-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.cpp68
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.cpp36
-rw-r--r--host/lib/usrp/usrp2/codec_impl.cpp4
-rw-r--r--host/lib/usrp/usrp2/fw_common.h3
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp30
-rw-r--r--host/lib/usrp/usrp2/usrp2_clk_regs.hpp15
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp4
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.hpp6
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp1
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.hpp2
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