diff options
| -rw-r--r-- | firmware/microblaze/usrp2/Makefile.am | 3 | ||||
| -rw-r--r-- | firmware/microblaze/usrp2p/Makefile.am | 3 | ||||
| -rw-r--r-- | host/include/uhd/usrp/mboard_rev.hpp | 90 | ||||
| -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 | 
13 files changed, 219 insertions, 46 deletions
diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am index 17f7a4744..e3f57728a 100644 --- a/firmware/microblaze/usrp2/Makefile.am +++ b/firmware/microblaze/usrp2/Makefile.am @@ -22,9 +22,10 @@ AM_CFLAGS = \  AM_LDFLAGS = \  	$(COMMON_LFLAGS) \ -	libusrp2.a \  	-Wl,-defsym -Wl,_TEXT_START_ADDR=0x0050 \  	-Wl,-defsym -Wl,_STACK_SIZE=3072 +	 +LDADD = libusrp2.a  ########################################################################  # USRP2 specific library and programs diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am index 0d0b60437..a5df3ff08 100644 --- a/firmware/microblaze/usrp2p/Makefile.am +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -22,10 +22,11 @@ AM_CFLAGS = \  AM_LDFLAGS = \  	$(COMMON_LFLAGS) \ -	libusrp2p.a \  	-Wl,-defsym -Wl,_TEXT_START_ADDR=0x8050 \  	-Wl,-defsym -Wl,_STACK_SIZE=3072 +LDADD = libusrp2p.a +  #all of this here is to relocate the hardware vectors to somewhere normal.  RELOCATE_ARGS = \  	--change-section-address .vectors.sw_exception+0x8000 \ diff --git a/host/include/uhd/usrp/mboard_rev.hpp b/host/include/uhd/usrp/mboard_rev.hpp new file mode 100644 index 000000000..5307d80c1 --- /dev/null +++ b/host/include/uhd/usrp/mboard_rev.hpp @@ -0,0 +1,90 @@ +// +// 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/>. +// + +#ifndef INCLUDED_UHD_USRP_MBOARD_REV_HPP +#define INCLUDED_UHD_USRP_MBOARD_REV_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <boost/operators.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + +    class UHD_API mboard_rev_t : boost::equality_comparable<mboard_rev_t>{ +    public: +        /*! +         * Create a mboard rev from an integer. +         * \param rev the integer representation +         */ +        mboard_rev_t(boost::uint16_t rev = 0xffff); + +        /*! +         * Obtain a mboard rev that represents an invalid/uninit mboard ID +         * \return the mboard rev with the 0xffff rev. +         */ +        static mboard_rev_t none(void); + +        /*! +         * Create a new mboard rev from an integer representation. +         * \param uint16 an unsigned 16 bit integer +         * \return a new mboard rev containing the integer +         */ +        static mboard_rev_t from_uint16(boost::uint16_t uint16); + +        /*! +         * Get the mboard rev represented as an integer. +         * \return an unsigned 16 bit integer representation +         */ +        boost::uint16_t to_uint16(void) const; + +        /*! +         * Create a new mboard rev from a string representation. +         * If the string has a 0x prefix, it will be parsed as hex. +         * \param string a numeric string, possibly hex +         * \return a new dboard id containing the integer +         */ +        static mboard_rev_t from_string(const std::string &string); + +        /*! +         * Get the mboard rev represented as an integer. +         * \return a hex string representation with 0x prefix +         */ +        std::string to_string(void) const; + +        /*! +         * Get the pretty print representation of this mboard rev. +         * \return a string with the mboard name and rev number +         */ +        std::string to_pp_string(void) const; + +    private: +        boost::uint16_t _rev; //internal representation +    }; + +    /*! +     * Comparator operator overloaded for mboard rev. +     * The boost::equality_comparable provides the !=. +     * \param lhs the dboard id to the left of the operator +     * \param rhs the dboard id to the right of the operator +     * \return true when the mboard revs are equal +     */ +    UHD_API bool operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MBOARD_REV_HPP */ 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  | 
