From 039eceb4b208b2ca5a3465d2f16c8d5a7c7276c7 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Fri, 23 Apr 2010 19:21:47 -0700
Subject: Moved reading the eeprom (dboard ids) onto the host.

Created a eeprom parser for the format in the dboard.
Removed the support from the microblaze code.
---
 host/include/uhd/usrp/CMakeLists.txt    |  1 +
 host/include/uhd/usrp/dboard_eeprom.hpp | 55 +++++++++++++++++++++++
 host/lib/CMakeLists.txt                 |  1 +
 host/lib/usrp/dboard_eeprom.cpp         | 78 +++++++++++++++++++++++++++++++++
 host/lib/usrp/usrp2/dboard_iface.cpp    | 36 +--------------
 host/lib/usrp/usrp2/dboard_impl.cpp     | 15 +++----
 host/lib/usrp/usrp2/fw_common.h         | 17 +------
 host/lib/usrp/usrp2/usrp2_iface.cpp     | 61 ++++++++++++++++++++++++++
 host/lib/usrp/usrp2/usrp2_iface.hpp     | 55 +++++++++++++++++++++++
 9 files changed, 259 insertions(+), 60 deletions(-)
 create mode 100644 host/include/uhd/usrp/dboard_eeprom.hpp
 create mode 100644 host/lib/usrp/dboard_eeprom.cpp

(limited to 'host')

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..6be88c85a
--- /dev/null
+++ b/host/include/uhd/usrp/dboard_eeprom.hpp
@@ -0,0 +1,55 @@
+//
+// 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
+     * \param buf the vector of bytes
+     */
+    dboard_eeprom_t(const uhd::byte_vector_t &buf = 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 to read out of eeprom.
+     * \return the number of bytes we are interested in
+     */
+    static size_t num_bytes(void);
+};
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP */
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 5495620ec..ffbf15484 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -55,6 +55,7 @@ SET(libuhd_sources
     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/usrp/dboard_eeprom.cpp b/host/lib/usrp/dboard_eeprom.cpp
new file mode 100644
index 000000000..a8fac602a
--- /dev/null
+++ b/host/lib/usrp/dboard_eeprom.cpp
@@ -0,0 +1,78 @@
+//
+// 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>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+////////////////////////////////////////////////////////////////////////
+// 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
+////////////////////////////////////////////////////////////////////////
+
+dboard_eeprom_t::dboard_eeprom_t(const byte_vector_t &buf){
+    try{
+        ASSERT_THROW(buf.size() >= num_bytes());
+        ASSERT_THROW(buf[DB_EEPROM_MAGIC] == DB_EEPROM_MAGIC_VALUE);
+        id = \
+            (boost::uint16_t(buf[DB_EEPROM_ID_LSB]) << 0) |
+            (boost::uint16_t(buf[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(3);
+    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);
+    return bytes;
+}
+
+size_t dboard_eeprom_t::num_bytes(void){
+    return 3;
+}
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index e9acddee6..9d9b745ae 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
 
@@ -214,42 +213,11 @@ 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);
+    return _iface->write_i2c(i2c_addr, buf);
 }
 
 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;
+    return _iface->read_i2c(i2c_addr, num_bytes);
 }
 
 /***********************************************************************
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index ee23dc83a..d697f11f0 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -18,6 +18,7 @@
 
 #include "usrp2_impl.hpp"
 #include "usrp2_regs.hpp"
+#include <uhd/usrp/dboard_eeprom.hpp>
 #include <uhd/usrp/subdev_props.hpp>
 #include <uhd/usrp/dboard_props.hpp>
 #include <uhd/utils/assert.hpp>
@@ -33,22 +34,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);
+    //extract the dboard ids
+    dboard_eeprom_t db_rx_eeprom(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes()));
+    dboard_eeprom_t db_tx_eeprom(_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
+        db_rx_eeprom.id, db_tx_eeprom.id, _dboard_iface
     );
 
     //load dboards
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;
@@ -106,10 +100,6 @@ typedef struct{
     union{
         _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;
@@ -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/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 1b0dde1b4..c639c0dfe 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;
 
@@ -89,6 +91,65 @@ public:
         return ntohl(out_data.data.spi_args.data);
     }
 
+/***********************************************************************
+ * 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;
+    }
+
+/***********************************************************************
+ * EEPROM
+ **********************************************************************/
+    void write_eeprom(boost::uint8_t addr, boost::uint8_t offset, const byte_vector_t &buf){
+        BOOST_FOREACH(boost::uint8_t byte, buf){
+            //write a byte at a time, its easy that way
+            byte_vector_t cmd = boost::assign::list_of(offset)(byte);
+            this->write_i2c(addr, cmd);
+        }
+    }
+
+    byte_vector_t read_eeprom(boost::uint8_t addr, boost::uint8_t offset, size_t num_bytes){
+        //do a zero byte write to start read cycle
+        write_i2c(addr, byte_vector_t(1, offset));
+        return read_i2c(addr, num_bytes);
+    }
+
 /***********************************************************************
  * Send/Recv over control
  **********************************************************************/
diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp
index 6667c8998..938359677 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.hpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.hpp
@@ -25,6 +25,15 @@
 #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.
@@ -93,6 +102,52 @@ public:
         bool readback
     ) = 0;
 
+    /*!
+     * Write bytes over the i2c.
+     * \param addr the address
+     * \param buf the vector of bytes
+     */
+    virtual void write_i2c(
+        boost::uint8_t addr,
+        const uhd::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 uhd::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 uhd::byte_vector_t &buf
+    ) = 0;
+
+    /*!
+     * 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 uhd::byte_vector_t read_eeprom(
+        boost::uint8_t addr,
+        boost::uint8_t offset,
+        size_t num_bytes
+    ) = 0;
+
     /*!
      * Get the master clock frequency.
      * \return the frequency in Hz
-- 
cgit v1.2.3


From 300ddf7807e5dd7662b09023ab80da26dd878626 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Sat, 24 Apr 2010 10:46:12 -0700
Subject: set dboard eeprom from dboard properties

---
 host/include/uhd/usrp/dboard_eeprom.hpp  | 17 ++++++++-----
 host/include/uhd/usrp/dboard_iface.hpp   | 10 ++++----
 host/include/uhd/usrp/dboard_manager.hpp |  1 -
 host/include/uhd/usrp/dboard_props.hpp   |  3 ++-
 host/lib/usrp/dboard_eeprom.cpp          | 25 +++++++++++++------
 host/lib/usrp/usrp2/dboard_iface.cpp     | 12 +++++-----
 host/lib/usrp/usrp2/dboard_impl.cpp      | 41 +++++++++++++++++++++++---------
 host/lib/usrp/usrp2/usrp2_iface.cpp      | 14 +++++++----
 host/lib/usrp/usrp2/usrp2_impl.hpp       |  3 +++
 9 files changed, 84 insertions(+), 42 deletions(-)

(limited to 'host')

diff --git a/host/include/uhd/usrp/dboard_eeprom.hpp b/host/include/uhd/usrp/dboard_eeprom.hpp
index 6be88c85a..108027b46 100644
--- a/host/include/uhd/usrp/dboard_eeprom.hpp
+++ b/host/include/uhd/usrp/dboard_eeprom.hpp
@@ -32,20 +32,25 @@ struct UHD_API dboard_eeprom_t{
     dboard_id_t id;
 
     /*!
-     * Create a dboard eeprom struct from the bytes read out of eeprom
-     * \param buf the vector of bytes
+     * 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 &buf = uhd::byte_vector_t(0));
+    dboard_eeprom_t(const uhd::byte_vector_t &bytes = uhd::byte_vector_t(0));
 
     /*!
-     * Get the bytes that would be written to dboard eeprom
+     * 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 to read out of eeprom.
-     * \return the number of bytes we are interested in
+     * 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);
 };
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/lib/usrp/dboard_eeprom.cpp b/host/lib/usrp/dboard_eeprom.cpp
index a8fac602a..5ce0b2328 100644
--- a/host/lib/usrp/dboard_eeprom.cpp
+++ b/host/lib/usrp/dboard_eeprom.cpp
@@ -53,26 +53,37 @@ using namespace uhd::usrp;
                                                //   daughterboard specific use
 ////////////////////////////////////////////////////////////////////////
 
-dboard_eeprom_t::dboard_eeprom_t(const byte_vector_t &buf){
+//negative sum of bytes excluding checksum byte
+static boost::uint8_t checksum(const byte_vector_t &bytes){
+    int sum;
+    for (size_t i = 0; i < DB_EEPROM_CHKSUM; i++){
+        sum += int(bytes.at(i));
+    }
+    return (-sum) & 0xff;
+}
+
+dboard_eeprom_t::dboard_eeprom_t(const byte_vector_t &bytes){
     try{
-        ASSERT_THROW(buf.size() >= num_bytes());
-        ASSERT_THROW(buf[DB_EEPROM_MAGIC] == DB_EEPROM_MAGIC_VALUE);
+        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(buf[DB_EEPROM_ID_LSB]) << 0) |
-            (boost::uint16_t(buf[DB_EEPROM_ID_MSB]) << 8) ;
+            (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(3);
+    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 3;
+    return DB_EEPROM_CLEN;
 }
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index 9d9b745ae..9503c329b 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -42,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);
@@ -212,12 +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){
-    return _iface->write_i2c(i2c_addr, buf);
+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){
-    return _iface->read_i2c(i2c_addr, num_bytes);
+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 d697f11f0..8952a9f75 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -18,7 +18,6 @@
 
 #include "usrp2_impl.hpp"
 #include "usrp2_regs.hpp"
-#include <uhd/usrp/dboard_eeprom.hpp>
 #include <uhd/usrp/subdev_props.hpp>
 #include <uhd/usrp/dboard_props.hpp>
 #include <uhd/utils/assert.hpp>
@@ -34,16 +33,16 @@ using namespace uhd::usrp;
  * Helper Methods
  **********************************************************************/
 void usrp2_impl::dboard_init(void){
-    //extract the dboard ids
-    dboard_eeprom_t db_rx_eeprom(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes()));
-    dboard_eeprom_t db_tx_eeprom(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));
+    //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(
-        db_rx_eeprom.id, db_tx_eeprom.id, _dboard_iface
+        _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface
     );
 
     //load dboards
@@ -120,19 +119,29 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
         val = _rx_subdevs_in_use;
         return;
 
+    case DBOARD_PROP_DBOARD_ID:
+        val = _rx_db_eeprom.id;
+        return;
+
     //case DBOARD_PROP_CODEC:
     //    throw std::runtime_error("unhandled prop in usrp2 dboard");
     }
 }
 
 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, _tx_db_eeprom.get_eeprom_bytes());
+        return;
+
+    default: throw std::runtime_error("Cannot set read-only property on usrp2 dboard");
+    }
 }
 
 /***********************************************************************
@@ -160,17 +169,27 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
         val = _tx_subdevs_in_use;
         return;
 
+    case DBOARD_PROP_DBOARD_ID:
+        val = _tx_db_eeprom.id;
+        return;
+
     //case DBOARD_PROP_CODEC:
     //    throw std::runtime_error("unhandled prop in usrp2 dboard");
     }
 }
 
 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: throw std::runtime_error("Cannot set read-only property on usrp2 dboard");
+    }
 }
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index c639c0dfe..76ee5d6fe 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -136,8 +136,8 @@ public:
 /***********************************************************************
  * EEPROM
  **********************************************************************/
-    void write_eeprom(boost::uint8_t addr, boost::uint8_t offset, const byte_vector_t &buf){
-        BOOST_FOREACH(boost::uint8_t byte, buf){
+    void write_eeprom(boost::uint8_t addr, boost::uint8_t offset, const byte_vector_t &bytes){
+        BOOST_FOREACH(boost::uint8_t byte, bytes){
             //write a byte at a time, its easy that way
             byte_vector_t cmd = boost::assign::list_of(offset)(byte);
             this->write_i2c(addr, cmd);
@@ -145,9 +145,13 @@ public:
     }
 
     byte_vector_t read_eeprom(boost::uint8_t addr, boost::uint8_t offset, size_t num_bytes){
-        //do a zero byte write to start read cycle
-        write_i2c(addr, byte_vector_t(1, offset));
-        return read_i2c(addr, num_bytes);
+        byte_vector_t bytes;
+        for (size_t i = 0; i < num_bytes; i++){
+            //do a zero byte write to start read cycle
+            write_i2c(addr, byte_vector_t(1, offset));
+            bytes.push_back(read_i2c(addr, 1).at(0));
+        }
+        return bytes;
     }
 
 /***********************************************************************
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);
 
-- 
cgit v1.2.3


From d1d6c859f0dbae5f044519d589d5ad3fcbb8643e Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Sat, 24 Apr 2010 17:42:39 -0700
Subject: added dboard id burner app

---
 host/utils/CMakeLists.txt         |   4 ++
 host/utils/uhd_burn_db_eeprom.cpp | 105 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)
 create mode 100644 host/utils/uhd_burn_db_eeprom.cpp

(limited to 'host')

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;
+}
-- 
cgit v1.2.3


From 61ec6711bb4bbae7a8a26cc631eeb88fb3e7d688 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Sun, 25 Apr 2010 22:05:50 -0700
Subject: Work on exceptions.

Added props exception macro to make the set/get prop switch statements easier.
Made use of boost throw exception macro for throw-site information in throw assert.
---
 host/CMakeLists.txt                      |  2 +-
 host/docs/build.rst                      |  2 +-
 host/include/uhd/utils/assert.hpp        | 33 ++++++++++++++++----------------
 host/include/uhd/utils/props.hpp         | 29 ++++++++++++++++++++++++++--
 host/include/uhd/utils/safe_main.hpp     |  3 +++
 host/lib/usrp/dboard/db_basic_and_lf.cpp | 12 ++++++------
 host/lib/usrp/dboard/db_rfx.cpp          | 14 ++++++--------
 host/lib/usrp/dboard/db_xcvr2450.cpp     | 15 ++++++++-------
 host/lib/usrp/usrp2/dboard_impl.cpp      | 10 ++++------
 host/lib/usrp/usrp2/dsp_impl.cpp         | 10 ++++++----
 host/lib/usrp/usrp2/mboard_impl.cpp      |  8 ++------
 host/lib/usrp/usrp2/usrp2_impl.cpp       |  3 ++-
 host/test/gain_handler_test.cpp          |  6 +++---
 13 files changed, 86 insertions(+), 61 deletions(-)

(limited to 'host')

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/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..bfbca4273 100644
--- a/host/include/uhd/utils/props.hpp
+++ b/host/include/uhd/utils/props.hpp
@@ -21,6 +21,9 @@
 #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>
 
@@ -35,14 +38,36 @@ namespace uhd{
      * \param key a reference to the prop object
      * \param name a reference to the name object
      */
-    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 = ""){
+    inline UHD_API named_prop_t 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);
     }
 
+    //! 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.
+     */
+    #define UHD_THROW_PROP_READ_ONLY() \
+        BOOST_THROW_EXCEPTION(uhd::prop_error() << uhd::prop_info("cannot set read-only property"))
+
 } //namespace uhd
 
 #endif /* INCLUDED_UHD_UTILS_PROPS_HPP */
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/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/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 8952a9f75..043609458 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -123,8 +123,7 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
         val = _rx_db_eeprom.id;
         return;
 
-    //case DBOARD_PROP_CODEC:
-    //    throw std::runtime_error("unhandled prop in usrp2 dboard");
+    default: UHD_THROW_PROP_WRITE_ONLY();
     }
 }
 
@@ -140,7 +139,7 @@ void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
         _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _tx_db_eeprom.get_eeprom_bytes());
         return;
 
-    default: throw std::runtime_error("Cannot set read-only property on usrp2 dboard");
+    default: UHD_THROW_PROP_READ_ONLY();
     }
 }
 
@@ -173,8 +172,7 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
         val = _tx_db_eeprom.id;
         return;
 
-    //case DBOARD_PROP_CODEC:
-    //    throw std::runtime_error("unhandled prop in usrp2 dboard");
+    default: UHD_THROW_PROP_WRITE_ONLY();
     }
 }
 
@@ -190,6 +188,6 @@ void usrp2_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){
         _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes());
         return;
 
-    default: throw std::runtime_error("Cannot set read-only property on usrp2 dboard");
+    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/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_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/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();
         }
     }
 
-- 
cgit v1.2.3


From 0c609b96574095affe12d9aaa53bead98faba4f3 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Mon, 26 Apr 2010 00:17:08 -0700
Subject: Added i2c interface to serial.hpp, using in usrp2_iface for i2c and
 eeprom.

---
 host/include/uhd/types/serial.hpp   | 61 +++++++++++++++++++++++++++++++++++++
 host/lib/types.cpp                  | 27 ++++++++++++++++
 host/lib/usrp/usrp2/usrp2_iface.cpp | 21 -------------
 host/lib/usrp/usrp2/usrp2_iface.hpp | 48 +----------------------------
 4 files changed, 89 insertions(+), 68 deletions(-)

(limited to 'host')

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
@@ -29,6 +29,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/lib/types.cpp b/host/lib/types.cpp
index 91887840c..a1b9b21a9 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -31,6 +31,7 @@
 #include <boost/foreach.hpp>
 #include <boost/format.hpp>
 #include <boost/cstdint.hpp>
+#include <boost/assign/list_of.hpp>
 #include <stdexcept>
 #include <complex>
 
@@ -250,3 +251,29 @@ 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
+){
+    BOOST_FOREACH(boost::uint8_t byte, bytes){
+        //write a byte at a time, its easy that way
+        byte_vector_t cmd = boost::assign::list_of(offset)(byte);
+        this->write_i2c(addr, cmd);
+    }
+}
+
+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));
+        bytes.push_back(this->read_i2c(addr, 1).at(0));
+    }
+    return bytes;
+}
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 76ee5d6fe..27b6f8907 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -133,27 +133,6 @@ public:
         return result;
     }
 
-/***********************************************************************
- * EEPROM
- **********************************************************************/
-    void write_eeprom(boost::uint8_t addr, boost::uint8_t offset, const byte_vector_t &bytes){
-        BOOST_FOREACH(boost::uint8_t byte, bytes){
-            //write a byte at a time, its easy that way
-            byte_vector_t cmd = boost::assign::list_of(offset)(byte);
-            this->write_i2c(addr, cmd);
-        }
-    }
-
-    byte_vector_t 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
-            write_i2c(addr, byte_vector_t(1, offset));
-            bytes.push_back(read_i2c(addr, 1).at(0));
-        }
-        return bytes;
-    }
-
 /***********************************************************************
  * Send/Recv over control
  **********************************************************************/
diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp
index 938359677..7158c58d0 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.hpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.hpp
@@ -39,7 +39,7 @@
  * 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;
 
@@ -102,52 +102,6 @@ public:
         bool readback
     ) = 0;
 
-    /*!
-     * Write bytes over the i2c.
-     * \param addr the address
-     * \param buf the vector of bytes
-     */
-    virtual void write_i2c(
-        boost::uint8_t addr,
-        const uhd::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 uhd::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 uhd::byte_vector_t &buf
-    ) = 0;
-
-    /*!
-     * 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 uhd::byte_vector_t read_eeprom(
-        boost::uint8_t addr,
-        boost::uint8_t offset,
-        size_t num_bytes
-    ) = 0;
-
     /*!
      * Get the master clock frequency.
      * \return the frequency in Hz
-- 
cgit v1.2.3


From 1217b8d67c3bef98195836fe10ab39576642b340 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Mon, 26 Apr 2010 12:16:37 -0700
Subject: Got eeprom read/write dboard ids working.

Moved named prop implementation into cpp,
and made named prop a struct (tuples are trouble).
---
 host/include/uhd/utils/props.hpp    | 29 ++++++++++++++++--------
 host/lib/CMakeLists.txt             |  1 +
 host/lib/types.cpp                  |  8 ++++---
 host/lib/usrp/dboard_eeprom.cpp     | 21 ++++++++++++++----
 host/lib/usrp/dboard_manager.cpp    |  5 +++--
 host/lib/usrp/usrp2/dboard_impl.cpp |  2 +-
 host/lib/utils.cpp                  | 44 +++++++++++++++++++++++++++++++++++++
 7 files changed, 91 insertions(+), 19 deletions(-)
 create mode 100644 host/lib/utils.cpp

(limited to 'host')

diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp
index bfbca4273..768655e36 100644
--- a/host/include/uhd/utils/props.hpp
+++ b/host/include/uhd/utils/props.hpp
@@ -29,24 +29,35 @@
 
 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
      */
-    inline UHD_API named_prop_t extract_named_prop(
+    UHD_API boost::tuple<wax::obj, std::string> 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);
-    }
+    );
 
     //! The exception to throw for property errors
     struct UHD_API prop_error : virtual std::exception, virtual boost::exception{};
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index ffbf15484..5252eda8f 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -50,6 +50,7 @@ SET(libuhd_sources
     gain_handler.cpp
     load_modules.cpp
     types.cpp
+    utils.cpp
     wax.cpp
     transport/convert_types.cpp
     transport/if_addrs.cpp
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index a1b9b21a9..08e41b62f 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -32,6 +32,7 @@
 #include <boost/format.hpp>
 #include <boost/cstdint.hpp>
 #include <boost/assign/list_of.hpp>
+#include <boost/thread.hpp>
 #include <stdexcept>
 #include <complex>
 
@@ -257,10 +258,11 @@ void i2c_iface::write_eeprom(
     boost::uint8_t offset,
     const byte_vector_t &bytes
 ){
-    BOOST_FOREACH(boost::uint8_t byte, 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)(byte);
+        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
     }
 }
 
@@ -272,7 +274,7 @@ byte_vector_t i2c_iface::read_eeprom(
     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));
+        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_eeprom.cpp b/host/lib/usrp/dboard_eeprom.cpp
index 5ce0b2328..00236c337 100644
--- a/host/lib/usrp/dboard_eeprom.cpp
+++ b/host/lib/usrp/dboard_eeprom.cpp
@@ -17,10 +17,14 @@
 
 #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''
@@ -55,14 +59,23 @@ using namespace uhd::usrp;
 
 //negative sum of bytes excluding checksum byte
 static boost::uint8_t checksum(const byte_vector_t &bytes){
-    int sum;
-    for (size_t i = 0; i < DB_EEPROM_CHKSUM; i++){
-        sum += int(bytes.at(i));
+    int sum = 0;
+    for (size_t i = 0; i < std::min(bytes.size(), size_t(DB_EEPROM_CHKSUM)); i++){
+        sum -= int(bytes.at(i));
     }
-    return (-sum) & 0xff;
+    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);
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_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 043609458..a68ae240e 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -136,7 +136,7 @@ void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
 
     case DBOARD_PROP_DBOARD_ID:
         _rx_db_eeprom.id = val.as<dboard_id_t>();
-        _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _tx_db_eeprom.get_eeprom_bytes());
+        _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes());
         return;
 
     default: UHD_THROW_PROP_READ_ONLY();
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);
+}
-- 
cgit v1.2.3