diff options
| -rw-r--r-- | host/include/uhd/usrp/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/include/uhd/usrp/mboard_eeprom.hpp | 64 | ||||
| -rw-r--r-- | host/lib/types.cpp | 13 | ||||
| -rw-r--r-- | host/lib/usrp/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/lib/usrp/mboard_eeprom.cpp | 176 | 
5 files changed, 247 insertions, 8 deletions
| diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index abddf3951..cdf31df87 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -34,6 +34,7 @@ INSTALL(FILES      ### utilities ###      dsp_utils.hpp +    mboard_eeprom.hpp      misc_utils.hpp      subdev_spec.hpp      tune_helper.hpp diff --git a/host/include/uhd/usrp/mboard_eeprom.hpp b/host/include/uhd/usrp/mboard_eeprom.hpp new file mode 100644 index 000000000..0d57105b9 --- /dev/null +++ b/host/include/uhd/usrp/mboard_eeprom.hpp @@ -0,0 +1,64 @@ +// +// 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_EEPROM_HPP +#define INCLUDED_UHD_USRP_MBOARD_EEPROM_HPP + +#include <uhd/config.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/types/serial.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + +    /*! +     * The motherboard EEPROM class: +     * Knows how to read and write the EEPROM for various USRPs. +     * The class inherits from a string, string dictionary. +     * Use the dictionary interface to get and set values. +     * Commit to the EEPROM to save changed settings. +     */ +    class UHD_API mboard_eeprom_t: boost::noncopyable, +        public uhd::dict<std::string, std::string> +    { +    public: +        typedef boost::shared_ptr<mboard_eeprom_t> sptr; + +        //! Possible EEPROM maps types +        enum map_type{ +            MAP_NXXX, +            MAP_BXXX +        }; + +        /*! +         * Make a new mboard EEPROM handler. +         * \param map the map type enum +         * \param iface the interface to i2c +         * \return a new mboard EEPROM object +         */ +        static sptr make(map_type map, i2c_iface &iface); + +        //! Write the contents of this object to the EEPROM. +        virtual void commit(void) = 0; + +    }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MBOARD_EEPROM_HPP */ diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 4188568aa..e5e6a2512 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -250,22 +250,19 @@ mac_addr_t mac_addr_t::from_bytes(const byte_vector_t &bytes){  mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){ -    byte_vector_t bytes = boost::assign::list_of -        (0x00)(0x50)(0xC2)(0x85)(0x30)(0x00); // Matt's IAB +    byte_vector_t bytes;      try{ -        //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx -        //the IAB above will fill in for the shorter pattern -        if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17) -            throw std::runtime_error("expected exactly 5 or 17 characters"); +        if (mac_addr_str.size() != 17){ +            throw std::runtime_error("expected exactly 17 characters"); +        }          //split the mac addr hex string at the colons -        size_t i = 0;          BOOST_FOREACH(const std::string &hex_str, std::split_string(mac_addr_str, ":")){              int hex_num;              std::istringstream iss(hex_str);              iss >> std::hex >> hex_num; -            bytes[i++] = boost::uint8_t(hex_num); +            bytes.push_back(boost::uint8_t(hex_num));          }      } diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index eeb181e0b..3d832c356 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -23,6 +23,7 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/mboard_eeprom.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/multi_usrp.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/single_usrp.cpp diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp new file mode 100644 index 000000000..d05be11e6 --- /dev/null +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -0,0 +1,176 @@ +// +// 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_eeprom.hpp> +#include <uhd/types/mac_addr.hpp> +#include <uhd/utils/algorithm.hpp> +#include <boost/asio/ip/address_v4.hpp> +#include <boost/assign/list_of.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/foreach.hpp> + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Constants + **********************************************************************/ +static const size_t SERIAL_LEN = 9; +static const size_t NAME_MAX_LEN = 32 - SERIAL_LEN; + +/*********************************************************************** + * Utility functions + **********************************************************************/ + +//! create a string from a byte vector, return empty if invalid ascii +static const std::string bytes_to_string(const byte_vector_t &bytes){ +    std::string out; +    BOOST_FOREACH(boost::uint8_t byte, bytes){ +        if (byte == '\0') return out; +        if (byte < 32 or byte > 127) return ""; +        out += byte; +    } +    return out; +} + +//! create a byte vector from a string, null terminate unless max length +static const byte_vector_t string_to_bytes(const std::string &string, size_t max_length){ +    byte_vector_t bytes; +    for (size_t i = 0; i < std::min(string.size(), max_length); i++){ +        bytes.push_back(string[i]); +    } +    if (bytes.size() < max_length - 1) bytes.push_back('\0'); +    return bytes; +} + +/*********************************************************************** + * Implementation of NXXX load/store + **********************************************************************/ +static const boost::uint8_t NXXX_EEPROM_ADDR = 0x50; + +static const uhd::dict<std::string, boost::uint8_t> USRP_NXXX_OFFSETS = boost::assign::map_list_of +    ("rev-lsb-msb", 0x00) +    ("mac-addr", 0x02) +    ("ip-addr", 0x02 + sizeof(mac_addr_t)) +    //leave space here for other addresses (perhaps) +    ("name", 0x18) +    ("serial", 0x18 + NAME_MAX_LEN) +; + +static void load_nxxx(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ +    //extract the revision number +    byte_vector_t rev_lsb_msb = iface.read_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["rev-lsb-msb"], 2); +    boost::uint16_t rev = (boost::uint16_t(rev_lsb_msb[0]) << 0) | (boost::uint16_t(rev_lsb_msb[1]) << 8); +    mb_eeprom["rev"] = boost::lexical_cast<std::string>(rev); + +    //extract the addresses +    mb_eeprom["mac-addr"] = mac_addr_t::from_bytes(iface.read_eeprom( +        NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["mac-addr"], sizeof(mac_addr_t) +    )).to_string(); + +    boost::asio::ip::address_v4::bytes_type ip_addr_bytes; +    std::copy(iface.read_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["ip-addr"], 4), ip_addr_bytes); +    mb_eeprom["ip-addr"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); + +    //extract the name +    mb_eeprom["name"] = bytes_to_string(iface.read_eeprom( +        NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["name"], NAME_MAX_LEN +    )); + +    //extract the serial +    mb_eeprom["serial"] = bytes_to_string(iface.read_eeprom( +        NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["serial"], SERIAL_LEN +    )); +} + +static void store_nxxx(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ +    //parse the revision number +    boost::uint16_t rev = boost::lexical_cast<boost::uint16_t>(mb_eeprom["rev"]); +    byte_vector_t rev_lsb_msb = boost::assign::list_of +        (boost::uint8_t(rev >> 0)) +        (boost::uint8_t(rev >> 8)) +    ; +    iface.write_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["rev-lsb-msb"], rev_lsb_msb); + +    //store the addresses +    iface.write_eeprom( +        NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["mac-addr"], +        mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes() +    ); + +    byte_vector_t ip_addr_bytes(4); +    std::copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"]).to_bytes(), ip_addr_bytes); +    iface.write_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["ip-addr"], ip_addr_bytes); + +    //store the name +    iface.write_eeprom( +        NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["name"], +        string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN) +    ); + +    //store the serial +    iface.write_eeprom( +        NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["serial"], +        string_to_bytes(mb_eeprom["serial"], SERIAL_LEN) +    ); +} + +/*********************************************************************** + * Implementation of BXXX load/store + **********************************************************************/ +//TODO + +static void load_bxxx(mboard_eeprom_t &, i2c_iface &){ +     +} + +static void store_bxxx(const mboard_eeprom_t &, i2c_iface &){ +     +} + +/*********************************************************************** + * Implementation of mboard eeprom + **********************************************************************/ +class mboard_eeprom_impl : public mboard_eeprom_t{ +public: +    mboard_eeprom_impl(map_type map, i2c_iface &iface): +        _map(map), _iface(iface) +    { +        switch(_map){ +        case MAP_NXXX: load_nxxx(*this, _iface); break; +        case MAP_BXXX: load_bxxx(*this, _iface); break; +        } +    } + +    void commit(void){ +        switch(_map){ +        case MAP_NXXX: store_nxxx(*this, _iface); break; +        case MAP_BXXX: store_bxxx(*this, _iface); break; +        } +    } + +private: +    map_type _map; +    i2c_iface &_iface; +}; + +/*********************************************************************** + * Factory function for mboard eeprom + **********************************************************************/ +mboard_eeprom_t::sptr mboard_eeprom_t::make(map_type map, i2c_iface &iface){ +    return sptr(new mboard_eeprom_impl(map, iface)); +} | 
