diff options
| author | Josh Blum <josh@joshknows.com> | 2010-04-26 12:19:00 -0700 | 
|---|---|---|
| committer | Josh Blum <josh@joshknows.com> | 2010-04-26 12:19:00 -0700 | 
| commit | f040d79d256bcdfcd931ab93e00b66f6af881a14 (patch) | |
| tree | 0bb82963278a64caaa04b1c5360f0d3e48059d42 | |
| parent | 15befa19de40fb82f30d71bf21a767e7d8054ba1 (diff) | |
| parent | 1217b8d67c3bef98195836fe10ab39576642b340 (diff) | |
| download | uhd-f040d79d256bcdfcd931ab93e00b66f6af881a14.tar.gz uhd-f040d79d256bcdfcd931ab93e00b66f6af881a14.tar.bz2 uhd-f040d79d256bcdfcd931ab93e00b66f6af881a14.zip | |
Merge branch 'eeprom' of git@ettus.sourcerepo.com:ettus/uhdpriv
36 files changed, 614 insertions, 273 deletions
| diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 7a6fbd993..8ff3b8c58 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -45,7 +45,6 @@  #include "clocks.h"  #include <vrt/bits.h>  #include "usrp2/fw_common.h" -#include <db.h>  #include <i2c.h>  #include <ethertype.h>  #include <arp_cache.h> @@ -257,12 +256,6 @@ void handle_udp_ctrl_packet(          memcpy(&ctrl_data_out.data.mac_addr, ethernet_mac_addr(), sizeof(eth_mac_addr_t));          break; -    case USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO: -        ctrl_data_out.id = USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE; -        ctrl_data_out.data.dboard_ids.tx_id = read_dboard_eeprom(I2C_ADDR_TX_A); -        ctrl_data_out.data.dboard_ids.rx_id = read_dboard_eeprom(I2C_ADDR_RX_A); -        break; -      /*******************************************************************       * SPI       ******************************************************************/ @@ -418,15 +411,6 @@ void handle_udp_ctrl_packet(          ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE;          break; -    /******************************************************************* -     * Hardware Rev Numbers -     ******************************************************************/ -    case USRP2_CTRL_ID_WHATS_THE_HARDWARE_REV_NOS_BRO: -        ctrl_data_out.data.hw_rev.major = u2_hw_rev_major; -        ctrl_data_out.data.hw_rev.minor = u2_hw_rev_minor; -        ctrl_data_out.id = USRP2_CTRL_ID_TAKE_THE_HARDWARE_REV_NOS_DUDE; -        break; -      default:          ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; diff --git a/firmware/microblaze/lib/Makefile.am b/firmware/microblaze/lib/Makefile.am index bd8972f5c..783895850 100644 --- a/firmware/microblaze/lib/Makefile.am +++ b/firmware/microblaze/lib/Makefile.am @@ -28,7 +28,6 @@ libu2fw_a_SOURCES = \  	bsm12.c \  	buffer_pool.c \  	clocks.c \ -	db_init.c \  	dbsm.c \  	eeprom.c \  	ethernet.c \ @@ -60,7 +59,6 @@ noinst_HEADERS = \  	bsm12.h \  	buffer_pool.h \  	clocks.h \ -	db.h \  	dbsm.h \  	eth_mac.h \  	eth_mac_regs.h \ diff --git a/firmware/microblaze/lib/db.h b/firmware/microblaze/lib/db.h deleted file mode 100644 index 358cb222b..000000000 --- a/firmware/microblaze/lib/db.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009 Free Software Foundation, Inc. - * - * 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/>. - */ - -/* - * Interface to daughterboard code - */ - -#ifndef INCLUDED_DB_H -#define INCLUDED_DB_H - -#include <usrp2_types.h> -#include <usrp2_i2c_addr.h> - -int read_dboard_eeprom(int i2c_addr); - -#endif /* INCLUDED_DB_H */ diff --git a/firmware/microblaze/lib/db_init.c b/firmware/microblaze/lib/db_init.c deleted file mode 100644 index 23805d9cd..000000000 --- a/firmware/microblaze/lib/db_init.c +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -/* - * Copyright 2008,2009 Free Software Foundation, Inc. - * - * 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 <memory_map.h> -#include <i2c.h> -#include <string.h> -#include <stdio.h> -#include <db.h> -#include <hal_io.h> -#include <nonstdio.h> - - -typedef enum { UDBE_OK, UDBE_NO_EEPROM, UDBE_INVALID_EEPROM } usrp_dbeeprom_status_t; - -static usrp_dbeeprom_status_t -read_raw_dboard_eeprom (unsigned char *buf, int i2c_addr) -{ -  if (!eeprom_read (i2c_addr, 0, buf, DB_EEPROM_CLEN)) -    return UDBE_NO_EEPROM; - -  if (buf[DB_EEPROM_MAGIC] != DB_EEPROM_MAGIC_VALUE) -    return UDBE_INVALID_EEPROM; - -  int sum = 0; -  unsigned int i; -  for (i = 0; i < DB_EEPROM_CLEN; i++) -    sum += buf[i]; - -  if ((sum & 0xff) != 0) -    return UDBE_INVALID_EEPROM; - -  return UDBE_OK; -} - - -/* - * Return DBID, -1 <none> or -2 <invalid eeprom contents> - */ -int -read_dboard_eeprom(int i2c_addr) -{ -  unsigned char buf[DB_EEPROM_CLEN]; - -  usrp_dbeeprom_status_t s = read_raw_dboard_eeprom (buf, i2c_addr); - -  //printf("\nread_raw_dboard_eeprom: %d\n", s); - -  switch (s){ -  case UDBE_OK: -    return (buf[DB_EEPROM_ID_MSB] << 8) | buf[DB_EEPROM_ID_LSB]; - -  case UDBE_NO_EEPROM: -  default: -    return -1; - -  case UDBE_INVALID_EEPROM: -    return -2; -  } -} diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index 76e83c660..399d834cb 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -25,7 +25,6 @@  #include "i2c.h"  #include "mdelay.h"  #include "clocks.h" -#include "db.h"  #include "usrp2_i2c_addr.h"  //#include "nonstdio.h" diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 4ef6278b9..bf8d71b21 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -76,7 +76,7 @@ ENDIF(WIN32)  # Setup Boost  ########################################################################  SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42") -FIND_PACKAGE(Boost 1.36 REQUIRED COMPONENTS +FIND_PACKAGE(Boost 1.37 REQUIRED COMPONENTS      date_time      filesystem      program_options diff --git a/host/docs/build.rst b/host/docs/build.rst index d28682764..81e61475e 100644 --- a/host/docs/build.rst +++ b/host/docs/build.rst @@ -40,7 +40,7 @@ CMake  ^^^^^^^^^^^^^^^^  Boost  ^^^^^^^^^^^^^^^^ -* **Version:** at least 3.6 unix, at least 4.0 windows +* **Version:** at least 3.7 unix, at least 4.0 windows  * **Required for:** build time + run time  * **Download URL:** http://www.boost.org/users/download/  * **Download URL (windows installer):** http://www.boostpro.com/download diff --git a/host/include/uhd/types/serial.hpp b/host/include/uhd/types/serial.hpp index b0fe5d7bd..c134725f5 100644 --- a/host/include/uhd/types/serial.hpp +++ b/host/include/uhd/types/serial.hpp @@ -30,6 +30,67 @@ namespace uhd{      typedef std::vector<boost::uint8_t> byte_vector_t;      /*! +     * The i2c interface class: +     * Provides i2c and eeprom functionality. +     * A subclass should only have to implement the i2c routines. +     * An eeprom implementation comes for free with the interface. +     * +     * The eeprom routines are implemented on top of i2c. +     * The built in eeprom implementation only does single +     * byte reads and byte writes over the i2c interface, +     * so it should be portable across multiple eeproms. +     * Override the eeprom routines if this is not acceptable. +     */ +    class UHD_API i2c_iface{ +    public: +        /*! +         * Write bytes over the i2c. +         * \param addr the address +         * \param buf the vector of bytes +         */ +        virtual void write_i2c( +            boost::uint8_t addr, +            const byte_vector_t &buf +        ) = 0; + +        /*! +         * Read bytes over the i2c. +         * \param addr the address +         * \param num_bytes number of bytes to read +         * \return a vector of bytes +         */ +        virtual byte_vector_t read_i2c( +            boost::uint8_t addr, +            size_t num_bytes +        ) = 0; + +        /*! +         * Write bytes to an eeprom. +         * \param addr the address +         * \param offset byte offset +         * \param buf the vector of bytes +         */ +        virtual void write_eeprom( +            boost::uint8_t addr, +            boost::uint8_t offset, +            const byte_vector_t &buf +        ); + +        /*! +         * Read bytes from an eeprom. +         * \param addr the address +         * \param offset byte offset +         * \param num_bytes number of bytes to read +         * \return a vector of bytes +         */ +        virtual byte_vector_t read_eeprom( +            boost::uint8_t addr, +            boost::uint8_t offset, +            size_t num_bytes +        ); +    }; + +    /*!       * The SPI configuration struct:       * Used to configure a SPI transaction interface.       */ diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index 23758041c..bbd124ed8 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -26,6 +26,7 @@ INSTALL(FILES      #### dboard headers ###      dboard_base.hpp +    dboard_eeprom.hpp      dboard_id.hpp      dboard_iface.hpp      dboard_manager.hpp diff --git a/host/include/uhd/usrp/dboard_eeprom.hpp b/host/include/uhd/usrp/dboard_eeprom.hpp new file mode 100644 index 000000000..108027b46 --- /dev/null +++ b/host/include/uhd/usrp/dboard_eeprom.hpp @@ -0,0 +1,60 @@ +// +// 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_DBOARD_EEPROM_HPP +#define INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP + +#include <uhd/config.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/types/serial.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + +struct UHD_API dboard_eeprom_t{ +    /*! +     * The dboard id that was read from eeprom or will be set to eeprom. +     */ +    dboard_id_t id; + +    /*! +     * Create a dboard eeprom struct from the bytes read out of eeprom. +     * The constructor will parse out the dboard id from a vector of bytes. +     * To be valid, the bytes vector should be at least num_bytes() long. +     * If the parsing fails due to bad checksum or incomplete length, +     * the dboard id in this struct will be set to dboard_id::NONE. +     * \param bytes the vector of bytes +     */ +    dboard_eeprom_t(const uhd::byte_vector_t &bytes = uhd::byte_vector_t(0)); + +    /*! +     * Get the bytes that would be written to dboard eeprom. +     * \return a vector of bytes +     */ +    uhd::byte_vector_t get_eeprom_bytes(void); + +    /*! +     * Get the number of bytes in the dboard eeprom segment. +     * Use this value when reading out of the dboard eeprom. +     * \return the number of bytes used by dboard eeprom +     */ +    static size_t num_bytes(void); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP */ diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index 79b8ee664..1214a1a2f 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -95,19 +95,19 @@ public:      /*!       * Write to an I2C peripheral.       * -     * \param i2c_addr I2C bus address (7-bits) -     * \param buf the data to write +     * \param addr I2C bus address (7-bits) +     * \param bytes the data to write       */ -    virtual void write_i2c(int i2c_addr, const byte_vector_t &buf) = 0; +    virtual void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes) = 0;      /*!       * Read from an I2C peripheral.       * -     * \param i2c_addr I2C bus address (7-bits) +     * \param addr I2C bus address (7-bits)       * \param num_bytes number of bytes to read       * \return the data read if successful, else a zero length string.       */ -    virtual byte_vector_t read_i2c(int i2c_addr, size_t num_bytes) = 0; +    virtual byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes) = 0;      /*!       * Write data to SPI bus peripheral. diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index 6de64b02d..007d85bb4 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -33,7 +33,6 @@ namespace uhd{ namespace usrp{   * Provide wax::obj access to the subdevs inside.   */  class UHD_API dboard_manager : boost::noncopyable{ -  public:      typedef boost::shared_ptr<dboard_manager> sptr; diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp index 3b290319f..0208a6c2c 100644 --- a/host/include/uhd/usrp/dboard_props.hpp +++ b/host/include/uhd/usrp/dboard_props.hpp @@ -29,7 +29,8 @@ namespace uhd{ namespace usrp{          DBOARD_PROP_NAME         = 'n', //ro, std::string          DBOARD_PROP_SUBDEV       = 's', //ro, wax::obj          DBOARD_PROP_SUBDEV_NAMES = 'S', //ro, prop_names_t -        DBOARD_PROP_USED_SUBDEVS = 'u'  //ro, prop_names_t +        DBOARD_PROP_USED_SUBDEVS = 'u', //ro, prop_names_t +        DBOARD_PROP_DBOARD_ID    = 'i'  //rw, dboard_id_t          //DBOARD_PROP_CODEC              //ro, wax::obj //----> not sure, dont have to deal with yet      };  diff --git a/host/include/uhd/utils/assert.hpp b/host/include/uhd/utils/assert.hpp index 842ed8dfa..773acd634 100644 --- a/host/include/uhd/utils/assert.hpp +++ b/host/include/uhd/utils/assert.hpp @@ -18,27 +18,27 @@  #ifndef INCLUDED_UHD_UTILS_ASSERT_HPP  #define INCLUDED_UHD_UTILS_ASSERT_HPP +#include <uhd/config.hpp>  #include <uhd/utils/algorithm.hpp>  #include <boost/format.hpp>  #include <boost/foreach.hpp>  #include <boost/lexical_cast.hpp> -#include <boost/current_function.hpp> +#include <boost/throw_exception.hpp> +#include <boost/exception/info.hpp>  #include <stdexcept> +#include <string>  namespace uhd{ -    class assert_error : public std::logic_error{ -    public: -        explicit assert_error(const std::string& what_arg) : logic_error(what_arg){ -            /* NOP */ -        } -    }; +    //! The exception to throw when assertions fail +    struct UHD_API assert_error : virtual std::exception, virtual boost::exception{}; -    #define ASSERT_THROW(_x) if (not (_x)) { \ -        throw uhd::assert_error(str(boost::format( \ -            "Assertion Failed:\n  %s:%d\n  %s\n  ---> %s <---" \ -        ) % __FILE__ % __LINE__ % BOOST_CURRENT_FUNCTION % std::string(#_x))); \ -    } +    //! The assertion info, the code that failed +    typedef boost::error_info<struct tag_assert_info, std::string> assert_info; + +    //! Throw an assert error with throw-site information +    #define ASSERT_THROW(_x) if (not (_x)) \ +        BOOST_THROW_EXCEPTION(uhd::assert_error() << uhd::assert_info(#_x))      /*!       * Check that an element is found in a container. @@ -58,17 +58,18 @@ namespace uhd{      ){          if (std::has(iterable, elem)) return;          std::string possible_values = ""; -        BOOST_FOREACH(T e, iterable){ -            if (e != iterable.begin()[0]) possible_values += ", "; +        size_t i = 0; +        BOOST_FOREACH(const T &e, iterable){ +            if (i++ > 0) possible_values += ", ";              possible_values += boost::lexical_cast<std::string>(e);          } -        throw uhd::assert_error(str(boost::format( +        boost::throw_exception(uhd::assert_error() << assert_info(str(boost::format(                  "Error: %s is not a valid %s. "                  "Possible values are: [%s]."              )              % boost::lexical_cast<std::string>(elem)              % what % possible_values -        )); +        )));      }  }//namespace uhd diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp index 6be0b2ce5..768655e36 100644 --- a/host/include/uhd/utils/props.hpp +++ b/host/include/uhd/utils/props.hpp @@ -21,27 +21,63 @@  #include <uhd/config.hpp>  #include <uhd/wax.hpp>  #include <boost/tuple/tuple.hpp> +#include <boost/throw_exception.hpp> +#include <boost/exception/info.hpp> +#include <stdexcept>  #include <vector>  #include <string>  namespace uhd{ -    //typedef for handling named properties +    //! The type for a vector of property names      typedef std::vector<std::string> prop_names_t; -    typedef boost::tuple<wax::obj, std::string> named_prop_t; + +    /*! +     * A named prop struct holds a key and a name. +     * Allows properties to be sub-sectioned by name. +     */ +    struct UHD_API named_prop_t{ +        wax::obj key; +        std::string name; + +        /*! +         * Create a new named prop from key and name. +         * \param key the property key +         * \param name the string name +         */ +        named_prop_t(const wax::obj &key, const std::string &name); +    };      /*!       * Utility function to separate a named property into its components.       * \param key a reference to the prop object       * \param name a reference to the name object +     * \return a tuple that can be used with boost::tie +     */ +    UHD_API boost::tuple<wax::obj, std::string> extract_named_prop( +        const wax::obj &key, +        const std::string &name = "" +    ); + +    //! The exception to throw for property errors +    struct UHD_API prop_error : virtual std::exception, virtual boost::exception{}; + +    //! The property error info (verbose or message) +    typedef boost::error_info<struct tag_prop_info, std::string> prop_info; + +    /*! +     * Throw an error when trying to get a write only property. +     * Throw-site information will be included with this error. +     */ +    #define UHD_THROW_PROP_WRITE_ONLY() \ +        BOOST_THROW_EXCEPTION(uhd::prop_error() << uhd::prop_info("cannot get write-only property")) + +    /*! +     * Throw an error when trying to set a read only property. +     * Throw-site information will be included with this error.       */ -    inline UHD_API named_prop_t //must be exported as part of the api to work (TODO move guts to cpp file) -    extract_named_prop(const wax::obj &key, const std::string &name = ""){ -        if (key.type() == typeid(named_prop_t)){ -            return key.as<named_prop_t>(); -        } -        return named_prop_t(key, name); -    } +    #define UHD_THROW_PROP_READ_ONLY() \ +        BOOST_THROW_EXCEPTION(uhd::prop_error() << uhd::prop_info("cannot set read-only property"))  } //namespace uhd diff --git a/host/include/uhd/utils/safe_main.hpp b/host/include/uhd/utils/safe_main.hpp index b682aa540..a4e4e06e8 100644 --- a/host/include/uhd/utils/safe_main.hpp +++ b/host/include/uhd/utils/safe_main.hpp @@ -19,6 +19,7 @@  #define INCLUDED_UHD_UTILS_SAFE_MAIN_HPP  #include <uhd/config.hpp> +#include <boost/exception/diagnostic_information.hpp>  #include <iostream>  #include <stdexcept> @@ -33,6 +34,8 @@  int main(int argc, char *argv[]){ \      try { \          return _main(argc, argv); \ +    } catch(const boost::exception &e){ \ +        std::cerr << "Error: " << boost::diagnostic_information(e) << std::endl; \      } catch(const std::exception &e) { \          std::cerr << "Error: " << e.what() << std::endl; \      } catch(...) { \ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 5495620ec..5252eda8f 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -50,11 +50,13 @@ SET(libuhd_sources      gain_handler.cpp      load_modules.cpp      types.cpp +    utils.cpp      wax.cpp      transport/convert_types.cpp      transport/if_addrs.cpp      transport/udp_simple.cpp      usrp/dboard_base.cpp +    usrp/dboard_eeprom.cpp      usrp/simple_usrp.cpp      usrp/dboard_manager.cpp      usrp/tune_helper.cpp diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 91887840c..08e41b62f 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -31,6 +31,8 @@  #include <boost/foreach.hpp>  #include <boost/format.hpp>  #include <boost/cstdint.hpp> +#include <boost/assign/list_of.hpp> +#include <boost/thread.hpp>  #include <stdexcept>  #include <complex> @@ -250,3 +252,30 @@ spi_config_t::spi_config_t(edge_t edge){      mosi_edge = edge;      miso_edge = edge;  } + +void i2c_iface::write_eeprom( +    boost::uint8_t addr, +    boost::uint8_t offset, +    const byte_vector_t &bytes +){ +    for (size_t i = 0; i < bytes.size(); i++){ +        //write a byte at a time, its easy that way +        byte_vector_t cmd = boost::assign::list_of(offset+i)(bytes[i]); +        this->write_i2c(addr, cmd); +        boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //worst case write +    } +} + +byte_vector_t i2c_iface::read_eeprom( +    boost::uint8_t addr, +    boost::uint8_t offset, +    size_t num_bytes +){ +    byte_vector_t bytes; +    for (size_t i = 0; i < num_bytes; i++){ +        //do a zero byte write to start read cycle +        this->write_i2c(addr, byte_vector_t(1, offset+i)); +        bytes.push_back(this->read_i2c(addr, 1).at(0)); +    } +    return bytes; +} diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index aad2398d8..c7b841efb 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -153,6 +153,8 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){      case SUBDEV_PROP_USE_LO_OFFSET:          val = false;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -174,9 +176,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){      case SUBDEV_PROP_FREQ:          return; // it wont do you much good, but you can set it -    default: throw std::runtime_error(str(boost::format( -            "Error: trying to set read-only property on %s subdev" -        ) % dboard_id::to_string(get_rx_id()))); +    default: UHD_THROW_PROP_READ_ONLY();      }  } @@ -248,6 +248,8 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){      case SUBDEV_PROP_USE_LO_OFFSET:          val = false;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -269,8 +271,6 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){      case SUBDEV_PROP_FREQ:          return; // it wont do you much good, but you can set it -    default: throw std::runtime_error(str(boost::format( -            "Error: trying to set read-only property on %s subdev" -        ) % dboard_id::to_string(get_tx_id()))); +    default: UHD_THROW_PROP_READ_ONLY();      }  } diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 76b2c6d7a..49ec9412c 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -396,6 +396,8 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){      case SUBDEV_PROP_USE_LO_OFFSET:          val = false;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -419,10 +421,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){          set_rx_ant(val.as<std::string>());          return; -    default: -        throw std::runtime_error(str(boost::format( -            "Error: trying to set read-only property on %s subdev" -        ) % dboard_id::to_string(get_rx_id()))); +    default: UHD_THROW_PROP_READ_ONLY();      }  } @@ -486,6 +485,8 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){      case SUBDEV_PROP_USE_LO_OFFSET:          val = true;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -509,9 +510,6 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){          ASSERT_THROW(val.as<std::string>() == "TX/RX");          return; -    default: -        throw std::runtime_error(str(boost::format( -            "Error: trying to set read-only property on %s subdev" -        ) % dboard_id::to_string(get_tx_id()))); +    default: UHD_THROW_PROP_READ_ONLY();      }  } diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 2c2843d3a..2052511f8 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -352,7 +352,8 @@ static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(float &gain){          gain = 5;          return max2829_regs_t::TX_BASEBAND_GAIN_5DB;      } -    ASSERT_THROW(false); +    BOOST_THROW_EXCEPTION(std::runtime_error("should not get here")); +    return max2829_regs_t::TX_BASEBAND_GAIN_0DB;  }  /*! @@ -474,6 +475,8 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){      case SUBDEV_PROP_USE_LO_OFFSET:          val = false;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -496,9 +499,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){          this->set_rx_ant(val.as<std::string>());          return; -    default: throw std::runtime_error(str(boost::format( -        "Error: trying to set read-only property on %s subdev" -    ) % dboard_id::to_string(get_rx_id()))); +    default: UHD_THROW_PROP_READ_ONLY();      }  } @@ -564,6 +565,8 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){      case SUBDEV_PROP_USE_LO_OFFSET:          val = false;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -586,8 +589,6 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){          this->set_tx_ant(val.as<std::string>());          return; -    default: throw std::runtime_error(str(boost::format( -        "Error: trying to set read-only property on %s subdev" -    ) % dboard_id::to_string(get_tx_id()))); +    default: UHD_THROW_PROP_READ_ONLY();      }  } diff --git a/host/lib/usrp/dboard_eeprom.cpp b/host/lib/usrp/dboard_eeprom.cpp new file mode 100644 index 000000000..00236c337 --- /dev/null +++ b/host/lib/usrp/dboard_eeprom.cpp @@ -0,0 +1,102 @@ +// +// 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/dboard_eeprom.hpp> +#include <uhd/utils/assert.hpp> +#include <boost/format.hpp> +#include <iostream> + +using namespace uhd; +using namespace uhd::usrp; + +static const bool _dboard_eeprom_debug = false; + +//////////////////////////////////////////////////////////////////////// +// format of daughterboard EEPROM +// 00: 0xDB code for ``I'm a daughterboard'' +// 01:   .. Daughterboard ID (LSB) +// 02:   .. Daughterboard ID (MSB) +// 03:   .. io bits  7-0 direction (bit set if it's an output from m'board) +// 04:   .. io bits 15-8 direction (bit set if it's an output from m'board) +// 05:   .. ADC0 DC offset correction (LSB) +// 06:   .. ADC0 DC offset correction (MSB) +// 07:   .. ADC1 DC offset correction (LSB) +// 08:   .. ADC1 DC offset correction (MSB) +//  ... +// 1f:   .. negative of the sum of bytes [0x00, 0x1e] + +#define DB_EEPROM_MAGIC         0x00 +#define DB_EEPROM_MAGIC_VALUE   0xDB +#define DB_EEPROM_ID_LSB        0x01 +#define DB_EEPROM_ID_MSB        0x02 +#define DB_EEPROM_OE_LSB        0x03 +#define DB_EEPROM_OE_MSB        0x04 +#define DB_EEPROM_OFFSET_0_LSB  0x05 // offset correction for ADC or DAC 0 +#define DB_EEPROM_OFFSET_0_MSB  0x06 +#define DB_EEPROM_OFFSET_1_LSB  0x07 // offset correction for ADC or DAC 1 +#define DB_EEPROM_OFFSET_1_MSB  0x08 +#define DB_EEPROM_CHKSUM        0x1f + +#define DB_EEPROM_CLEN          0x20 // length of common portion of eeprom + +#define DB_EEPROM_CUSTOM_BASE   DB_EEPROM_CLEN // first avail offset for +                                               //   daughterboard specific use +//////////////////////////////////////////////////////////////////////// + +//negative sum of bytes excluding checksum byte +static boost::uint8_t checksum(const byte_vector_t &bytes){ +    int sum = 0; +    for (size_t i = 0; i < std::min(bytes.size(), size_t(DB_EEPROM_CHKSUM)); i++){ +        sum -= int(bytes.at(i)); +    } +    if (_dboard_eeprom_debug) +        std::cout << boost::format("sum: 0x%02x") % sum << std::endl; +    return boost::uint8_t(sum); +} + +dboard_eeprom_t::dboard_eeprom_t(const byte_vector_t &bytes){ +    if (_dboard_eeprom_debug){ +        for (size_t i = 0; i < bytes.size(); i++){ +            std::cout << boost::format( +                "eeprom byte[0x%02x] = 0x%02x") % i % int(bytes.at(i) +            ) << std::endl; +        } +    } +    try{ +        ASSERT_THROW(bytes.size() >= DB_EEPROM_CLEN); +        ASSERT_THROW(bytes[DB_EEPROM_MAGIC] == DB_EEPROM_MAGIC_VALUE); +        ASSERT_THROW(bytes[DB_EEPROM_CHKSUM] == checksum(bytes)); +        id = \ +            (boost::uint16_t(bytes[DB_EEPROM_ID_LSB]) << 0) | +            (boost::uint16_t(bytes[DB_EEPROM_ID_MSB]) << 8) ; +    }catch(const uhd::assert_error &e){ +        id = dboard_id::NONE; +    } +} + +byte_vector_t dboard_eeprom_t::get_eeprom_bytes(void){ +    byte_vector_t bytes(DB_EEPROM_CLEN, 0); //defaults to all zeros +    bytes[DB_EEPROM_MAGIC] = DB_EEPROM_MAGIC_VALUE; +    bytes[DB_EEPROM_ID_LSB] = boost::uint8_t(id >> 0); +    bytes[DB_EEPROM_ID_MSB] = boost::uint8_t(id >> 8); +    bytes[DB_EEPROM_CHKSUM] = checksum(bytes); +    return bytes; +} + +size_t dboard_eeprom_t::num_bytes(void){ +    return DB_EEPROM_CLEN; +} diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 06f8c55b6..34b635934 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -177,10 +177,11 @@ static args_t get_dboard_args(      //verify that there is a registered constructor for this id      if (not get_id_to_args_map().has_key(dboard_id)){ -        throw std::runtime_error(str( +        /*throw std::runtime_error(str(              boost::format("Unregistered %s dboard id: %s")              % xx_type % dboard_id::to_string(dboard_id) -        )); +        ));*/ +        return get_dboard_args(dboard_id::NONE, xx_type);      }      //return the dboard args for this id diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index e9acddee6..9503c329b 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -24,7 +24,6 @@  #include <boost/assign/list_of.hpp>  #include <boost/asio.hpp> //htonl and ntohl  #include <boost/math/special_functions/round.hpp> -#include <algorithm>  #include "ad7922_regs.hpp" //aux adc  #include "ad5624_regs.hpp" //aux dac @@ -43,8 +42,8 @@ public:      void set_gpio_ddr(unit_t, boost::uint16_t);      boost::uint16_t read_gpio(unit_t); -    void write_i2c(int, const byte_vector_t &); -    byte_vector_t read_i2c(int, size_t); +    void write_i2c(boost::uint8_t, const byte_vector_t &); +    byte_vector_t read_i2c(boost::uint8_t, size_t);      double get_clock_rate(unit_t);      void set_clock_enabled(unit_t, bool); @@ -213,43 +212,12 @@ boost::uint32_t usrp2_dboard_iface::read_write_spi(  /***********************************************************************   * I2C   **********************************************************************/ -void usrp2_dboard_iface::write_i2c(int i2c_addr, const byte_vector_t &buf){ -    //setup the out data -    usrp2_ctrl_data_t out_data; -    out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO); -    out_data.data.i2c_args.addr = i2c_addr; -    out_data.data.i2c_args.bytes = buf.size(); - -    //limitation of i2c transaction size -    ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data)); - -    //copy in the data -    std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data); - -    //send and recv -    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE); +void usrp2_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ +    return _iface->write_i2c(addr, bytes);  } -byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){ -    //setup the out data -    usrp2_ctrl_data_t out_data; -    out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); -    out_data.data.i2c_args.addr = i2c_addr; -    out_data.data.i2c_args.bytes = num_bytes; - -    //limitation of i2c transaction size -    ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data)); - -    //send and recv -    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE); -    ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes); - -    //copy out the data -    byte_vector_t result(num_bytes); -    std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin()); -    return result; +byte_vector_t usrp2_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ +    return _iface->read_i2c(addr, num_bytes);  }  /*********************************************************************** diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index ee23dc83a..a68ae240e 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -33,22 +33,16 @@ using namespace uhd::usrp;   * Helper Methods   **********************************************************************/  void usrp2_impl::dboard_init(void){ -    //grab the dboard ids over the control line -    usrp2_ctrl_data_t out_data; -    out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO); -    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE); - -    //extract the dboard ids an convert them -    dboard_id_t rx_dboard_id = ntohs(in_data.data.dboard_ids.rx_id); -    dboard_id_t tx_dboard_id = ntohs(in_data.data.dboard_ids.tx_id); +    //read the dboard eeprom to extract the dboard ids +    _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); +    _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));      //create a new dboard interface and manager      dboard_iface::sptr _dboard_iface(          make_usrp2_dboard_iface(_iface, _clk_ctrl)      );      _dboard_manager = dboard_manager::make( -        rx_dboard_id, tx_dboard_id, _dboard_iface +        _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface      );      //load dboards @@ -125,19 +119,28 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){          val = _rx_subdevs_in_use;          return; -    //case DBOARD_PROP_CODEC: -    //    throw std::runtime_error("unhandled prop in usrp2 dboard"); +    case DBOARD_PROP_DBOARD_ID: +        val = _rx_db_eeprom.id; +        return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  }  void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ -    if (key.as<dboard_prop_t>() == DBOARD_PROP_USED_SUBDEVS){ +    switch(key.as<dboard_prop_t>()){ +    case DBOARD_PROP_USED_SUBDEVS:          _rx_subdevs_in_use = val.as<prop_names_t>();          update_rx_mux_config(); //if the val is bad, this will throw          return; -    } -    throw std::runtime_error("Cannot set on usrp2 dboard"); +    case DBOARD_PROP_DBOARD_ID: +        _rx_db_eeprom.id = val.as<dboard_id_t>(); +        _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes()); +        return; + +    default: UHD_THROW_PROP_READ_ONLY(); +    }  }  /*********************************************************************** @@ -165,17 +168,26 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){          val = _tx_subdevs_in_use;          return; -    //case DBOARD_PROP_CODEC: -    //    throw std::runtime_error("unhandled prop in usrp2 dboard"); +    case DBOARD_PROP_DBOARD_ID: +        val = _tx_db_eeprom.id; +        return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  }  void usrp2_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ -    if (key.as<dboard_prop_t>() == DBOARD_PROP_USED_SUBDEVS){ +    switch(key.as<dboard_prop_t>()){ +    case DBOARD_PROP_USED_SUBDEVS:          _tx_subdevs_in_use = val.as<prop_names_t>();          update_tx_mux_config(); //if the val is bad, this will throw          return; -    } -    throw std::runtime_error("Cannot set on usrp2 dboard"); +    case DBOARD_PROP_DBOARD_ID: +        _tx_db_eeprom.id = val.as<dboard_id_t>(); +        _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes()); +        return; + +    default: UHD_THROW_PROP_READ_ONLY(); +    }  } diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 204277ba7..379276f7d 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -117,6 +117,8 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){      case DSP_PROP_HOST_RATE:          val = get_master_clock_freq()/_ddc_decim;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -139,8 +141,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){          }          return; -    default: -        throw std::runtime_error("Error: trying to set read-only property on usrp2 ddc0"); +    default: UHD_THROW_PROP_READ_ONLY();      }  } @@ -200,6 +201,8 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){      case DSP_PROP_HOST_RATE:          val = get_master_clock_freq()/_duc_interp;          return; + +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -222,7 +225,6 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){          }          return; -    default: -        throw std::runtime_error("Error: trying to set read-only property on usrp2 duc0"); +    default: UHD_THROW_PROP_READ_ONLY();      }  } diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 640b37ec6..e80001ff2 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -34,7 +34,7 @@ extern "C" {  //defines the protocol version in this shared header  //increment this value when the protocol is changed -#define USRP2_PROTO_VERSION 1 +#define USRP2_PROTO_VERSION 2  //used to differentiate control packets over data port  #define USRP2_INVALID_VRT_HEADER 0 @@ -61,9 +61,6 @@ typedef enum{      USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE = 'M',      USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO = 'n', -    USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO = 'd', -    USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE = 'D', -      USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO = 's',      USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE = 'S', @@ -82,9 +79,6 @@ typedef enum{      USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO = 'r',      USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE = 'R', -    USRP2_CTRL_ID_WHATS_THE_HARDWARE_REV_NOS_BRO = 'y', -    USRP2_CTRL_ID_TAKE_THE_HARDWARE_REV_NOS_DUDE = 'Y', -      USRP2_CTRL_ID_PEACE_OUT = '~'  } usrp2_ctrl_id_t; @@ -107,10 +101,6 @@ typedef struct{          _SINS_ uint32_t ip_addr;          _SINS_ uint8_t mac_addr[6];          struct { -            _SINS_ uint16_t rx_id; -            _SINS_ uint16_t tx_id; -        } dboard_ids; -        struct {              _SINS_ uint8_t dev;              _SINS_ uint8_t miso_edge;              _SINS_ uint8_t mosi_edge; @@ -137,11 +127,6 @@ typedef struct{              _SINS_ uint32_t data;              _SINS_ uint8_t num_bytes; //1, 2, 4          } poke_args; -        struct { -            _SINS_ uint8_t major; -            _SINS_ uint8_t minor; -            _SINS_ uint8_t _pad[2]; -        } hw_rev;      } data;  } usrp2_ctrl_data_t; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index f94806c9f..2c185ec53 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -248,9 +248,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){          val = _clock_config;          return; -    default: -        throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard"); - +    default: UHD_THROW_PROP_WRITE_ONLY();      }  } @@ -306,8 +304,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){          issue_ddc_stream_cmd(val.as<stream_cmd_t>());          return; -    default: -        throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard"); - +    default: UHD_THROW_PROP_READ_ONLY();      }  } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 1b0dde1b4..27b6f8907 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -19,9 +19,11 @@  #include <uhd/utils/assert.hpp>  #include <uhd/types/dict.hpp>  #include <boost/thread.hpp> +#include <boost/foreach.hpp>  #include <boost/asio.hpp> //used for htonl and ntohl  #include <boost/assign/list_of.hpp>  #include <stdexcept> +#include <algorithm>  using namespace uhd; @@ -90,6 +92,48 @@ public:      }  /*********************************************************************** + * I2C + **********************************************************************/ +    void write_i2c(boost::uint8_t addr, const byte_vector_t &buf){ +        //setup the out data +        usrp2_ctrl_data_t out_data; +        out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO); +        out_data.data.i2c_args.addr = addr; +        out_data.data.i2c_args.bytes = buf.size(); + +        //limitation of i2c transaction size +        ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data)); + +        //copy in the data +        std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data); + +        //send and recv +        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); +        ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE); +    } + +    byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes){ +        //setup the out data +        usrp2_ctrl_data_t out_data; +        out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); +        out_data.data.i2c_args.addr = addr; +        out_data.data.i2c_args.bytes = num_bytes; + +        //limitation of i2c transaction size +        ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data)); + +        //send and recv +        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); +        ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE); +        ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes); + +        //copy out the data +        byte_vector_t result(num_bytes); +        std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin()); +        return result; +    } + +/***********************************************************************   * Send/Recv over control   **********************************************************************/      usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){ diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 6667c8998..7158c58d0 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -25,12 +25,21 @@  #include <boost/cstdint.hpp>  #include "fw_common.h" +//////////////////////////////////////////////////////////////////////// +// I2C addresses +//////////////////////////////////////////////////////////////////////// +#define I2C_DEV_EEPROM  0x50 // 24LC02[45]:  7-bits 1010xxx +#define	I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) +#define	I2C_ADDR_TX_DB  (I2C_DEV_EEPROM | 0x4) +#define	I2C_ADDR_RX_DB  (I2C_DEV_EEPROM | 0x5) +//////////////////////////////////////////////////////////////////////// +  /*!   * The usrp2 interface class:   * Provides a set of functions to implementation layer.   * Including spi, peek, poke, control...   */ -class usrp2_iface : boost::noncopyable{ +class usrp2_iface : public uhd::i2c_iface, boost::noncopyable{  public:      typedef boost::shared_ptr<usrp2_iface> sptr; diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 0fa56c339..11ad812e1 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -202,9 +202,10 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){          val = size_t(_max_tx_samples_per_packet);          return; +    default: UHD_THROW_PROP_WRITE_ONLY();      }  }  void usrp2_impl::set(const wax::obj &, const wax::obj &){ -    throw std::runtime_error("Cannot set in usrp2 device"); +    UHD_THROW_PROP_READ_ONLY();  } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index dbcee367b..1c9387744 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -25,6 +25,7 @@  #include <uhd/types/otw_type.hpp>  #include <uhd/types/stream_cmd.hpp>  #include <uhd/types/clock_config.hpp> +#include <uhd/usrp/dboard_eeprom.hpp>  #include <boost/shared_ptr.hpp>  #include <boost/function.hpp>  #include <uhd/transport/vrt.hpp> @@ -161,12 +162,14 @@ private:      void rx_dboard_set(const wax::obj &, const wax::obj &);      wax_obj_proxy::sptr _rx_dboard_proxy;      uhd::prop_names_t _rx_subdevs_in_use; +    uhd::usrp::dboard_eeprom_t _rx_db_eeprom;      //properties interface for tx dboard      void tx_dboard_get(const wax::obj &, wax::obj &);      void tx_dboard_set(const wax::obj &, const wax::obj &);      wax_obj_proxy::sptr _tx_dboard_proxy;      uhd::prop_names_t _tx_subdevs_in_use; +    uhd::usrp::dboard_eeprom_t _tx_db_eeprom;      void update_rx_mux_config(void);      void update_tx_mux_config(void); diff --git a/host/lib/utils.cpp b/host/lib/utils.cpp new file mode 100644 index 000000000..3a1e5aa3f --- /dev/null +++ b/host/lib/utils.cpp @@ -0,0 +1,44 @@ +// +// 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/utils/props.hpp> + +using namespace uhd; + +/*********************************************************************** + * Props + **********************************************************************/ +named_prop_t::named_prop_t( +    const wax::obj &key_, +    const std::string &name_ +){ +    key = key_; +    name = name_; +} + +typedef boost::tuple<wax::obj, std::string> named_prop_tuple; + +named_prop_tuple uhd::extract_named_prop( +    const wax::obj &key, +    const std::string &name +){ +    if (key.type() == typeid(named_prop_t)){ +        named_prop_t np = key.as<named_prop_t>(); +        return named_prop_tuple(np.key, np.name); +    } +    return named_prop_tuple(key, name); +} diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index bf2ec5db7..0669b491a 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -72,6 +72,8 @@ private:          case PROP_GAIN_NAMES:              val = _gain_values.keys();              return; + +        default: UHD_THROW_PROP_WRITE_ONLY();          }      } @@ -87,9 +89,7 @@ private:              _gain_values[name] = val.as<float>();              return; -        case PROP_GAIN_RANGE: -        case PROP_GAIN_NAMES: -            throw std::runtime_error("cannot set this property"); +        default: UHD_THROW_PROP_READ_ONLY();          }      } diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index aa01d1e35..3c2236379 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -23,4 +23,8 @@ ADD_EXECUTABLE(usrp2_burner usrp2_burner.cpp)  TARGET_LINK_LIBRARIES(usrp2_burner uhd)  INSTALL(TARGETS usrp2_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) +ADD_EXECUTABLE(uhd_burn_db_eeprom uhd_burn_db_eeprom.cpp) +TARGET_LINK_LIBRARIES(uhd_burn_db_eeprom uhd) +INSTALL(TARGETS uhd_burn_db_eeprom RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) +  INSTALL(PROGRAMS usrp2_recovery.py DESTINATION ${PKG_DATA_DIR}/utils) diff --git a/host/utils/uhd_burn_db_eeprom.cpp b/host/utils/uhd_burn_db_eeprom.cpp new file mode 100644 index 000000000..c07b43f16 --- /dev/null +++ b/host/utils/uhd_burn_db_eeprom.cpp @@ -0,0 +1,105 @@ +// +// 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/utils/safe_main.hpp> +#include <uhd/device.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/usrp/device_props.hpp> +#include <uhd/usrp/mboard_props.hpp> +#include <uhd/usrp/dboard_props.hpp> +#include <boost/program_options.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/format.hpp> +#include <boost/assign.hpp> +#include <iostream> +#include <sstream> + +using namespace uhd; +using namespace uhd::usrp; +namespace po = boost::program_options; + +//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; +    } +}; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ +    //command line variables +    std::string args, db_name, unit; +    static const uhd::dict<std::string, mboard_prop_t> unit_to_db_prop = boost::assign::map_list_of +        ("RX", MBOARD_PROP_RX_DBOARD) ("TX", MBOARD_PROP_TX_DBOARD) +    ; + +    po::options_description desc("Allowed options"); +    desc.add_options() +        ("help", "help message") +        ("args", po::value<std::string>(&args)->default_value(""),    "device address args [default = \"\"]") +        ("db",   po::value<std::string>(&db_name)->default_value(""), "dboard name [default = \"\"]") +        ("unit", po::value<std::string>(&unit)->default_value(""),    "which unit [RX or TX]") +        ("id",   po::value<std::string>(),                            "dboard id to burn (hex string), omit for readback") +    ; + +    po::variables_map vm; +    po::store(po::parse_command_line(argc, argv, desc), vm); +    po::notify(vm); + +    //print the help message +    if (vm.count("help")){ +        std::cout << boost::format("UHD Burn DB EEPROM %s") % desc << std::endl; +        std::cout << boost::format( +            "Omit the id argument to perform readback,\n" +            "Or specify a new id to burn into the eeprom.\n" +        ) << std::endl; +        return ~0; +    } + +    //check inputs +    if (not unit_to_db_prop.has_key(unit)){ +        std::cout << "Error: specify RX or TX for unit" << std::endl; +        return ~0; +    } + +    //make the device and extract the dboard w/ property +    device::sptr dev = device::make(args); +    wax::obj dboard = (*dev)[DEVICE_PROP_MBOARD][named_prop_t(unit_to_db_prop[unit], db_name)]; +    std::string prefix = (db_name == "")? unit : (unit + ":" + db_name); + +    //read the current dboard id from eeprom +    if (vm.count("id") == 0){ +        std::cout << boost::format("Getting dbid on %s dboard...") % prefix << std::endl; +        dboard_id_t id = dboard[DBOARD_PROP_DBOARD_ID].as<dboard_id_t>(); +        std::cout << boost::format("  Current dbid: %s") % dboard_id::to_string(id) << std::endl; +    } + +    //write a new dboard id to eeprom +    else{ +        dboard_id_t id = boost::lexical_cast<to_hex<dboard_id_t> >(vm["id"].as<std::string>()); +        std::cout << boost::format("Setting dbid on %s dboard...") % prefix << std::endl; +        std::cout << boost::format("  New dbid: %s") % dboard_id::to_string(id) << std::endl; +        dboard[DBOARD_PROP_DBOARD_ID] = id; +    } + +    std::cout << "  Done" << std::endl << std::endl; +    return 0; +} | 
