aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-11-09 18:38:39 -0800
committerJosh Blum <josh@joshknows.com>2010-11-09 18:38:39 -0800
commit3bca8c492514564a065e34d3284cb468873fcc8c (patch)
tree73f11afc14eb62ac1c1ff5374dce9c3cb33c0278 /host
parent073518083f2c7044d4b0c16948a192c5623d0752 (diff)
parentc0dfc2cf47b98734c4218427c7c6f5eb92025a9c (diff)
downloaduhd-3bca8c492514564a065e34d3284cb468873fcc8c.tar.gz
uhd-3bca8c492514564a065e34d3284cb468873fcc8c.tar.bz2
uhd-3bca8c492514564a065e34d3284cb468873fcc8c.zip
Merge branch 'master' into usrp_e_next
Diffstat (limited to 'host')
-rw-r--r--host/config/Python.cmake35
-rw-r--r--host/docs/CMakeLists.txt1
-rw-r--r--host/docs/dboards.rst58
-rw-r--r--host/docs/identification.rst97
-rw-r--r--host/docs/index.rst1
-rw-r--r--host/docs/usrp1.rst30
-rw-r--r--host/docs/usrp2.rst21
-rw-r--r--host/include/uhd/types/dict.hpp8
-rw-r--r--host/include/uhd/types/dict.ipp10
-rw-r--r--host/include/uhd/usrp/CMakeLists.txt1
-rw-r--r--host/include/uhd/usrp/mboard_eeprom.hpp64
-rw-r--r--host/include/uhd/usrp/mboard_props.hpp3
-rw-r--r--host/lib/CMakeLists.txt19
-rw-r--r--host/lib/ic_reg_maps/CMakeLists.txt10
-rwxr-xr-xhost/lib/ic_reg_maps/gen_max2112_regs.py181
-rw-r--r--host/lib/types.cpp13
-rw-r--r--host/lib/usrp/CMakeLists.txt1
-rw-r--r--host/lib/usrp/dboard/CMakeLists.txt1
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp14
-rw-r--r--host/lib/usrp/dboard/db_dbsrx2.cpp439
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp4
-rw-r--r--host/lib/usrp/dboard/db_tvrx.cpp2
-rw-r--r--host/lib/usrp/dboard/db_unknown.cpp43
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp4
-rw-r--r--host/lib/usrp/mboard_eeprom.cpp194
-rw-r--r--host/lib/usrp/usrp1/CMakeLists.txt2
-rw-r--r--host/lib/usrp/usrp1/mboard_impl.cpp35
-rw-r--r--host/lib/usrp/usrp1/usrp1_iface.cpp4
-rw-r--r--host/lib/usrp/usrp1/usrp1_iface.hpp3
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp19
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.cpp5
-rw-r--r--host/lib/usrp/usrp2/fw_common.h8
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp8
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp75
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp3
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.hpp4
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp45
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp16
-rw-r--r--host/utils/CMakeLists.txt12
-rw-r--r--host/utils/uhd_usrp_probe.cpp8
-rw-r--r--host/utils/usrp1_serial_burner.cpp75
-rw-r--r--host/utils/usrp2_addr_burner.cpp91
-rw-r--r--host/utils/usrp_burn_db_eeprom.cpp6
-rw-r--r--host/utils/usrp_burn_mb_eeprom.cpp81
44 files changed, 1373 insertions, 381 deletions
diff --git a/host/config/Python.cmake b/host/config/Python.cmake
index 55ef6acca..95cdb4479 100644
--- a/host/config/Python.cmake
+++ b/host/config/Python.cmake
@@ -18,32 +18,31 @@
########################################################################
# Setup Python
########################################################################
-INCLUDE(FindPythonInterp)
+IF(NOT DEFINED PYTHON_EXECUTABLE)
+ INCLUDE(FindPythonInterp)
-IF(NOT PYTHONINTERP_FOUND)
- MESSAGE(FATAL_ERROR "Error: Python interpretor required by the build system.")
-ENDIF(NOT PYTHONINTERP_FOUND)
+ IF(NOT PYTHONINTERP_FOUND)
+ MESSAGE(FATAL_ERROR "Error: Python interpretor required by the build system.")
+ ENDIF(NOT PYTHONINTERP_FOUND)
+ENDIF(NOT DEFINED PYTHON_EXECUTABLE)
-MACRO(PYTHON_CHECK_MODULE module have)
- MESSAGE(STATUS "Checking for python module ${module}")
+MACRO(PYTHON_CHECK_MODULE desc mod cmd have)
+ MESSAGE(STATUS "Python checking for ${desc}")
EXECUTE_PROCESS(
- COMMAND ${PYTHON_EXECUTABLE} -c "import ${module}"
+ COMMAND ${PYTHON_EXECUTABLE} -c "
+#########################################
+try: import ${mod}
+except: exit(-1)
+try: assert ${cmd}
+except: exit(-1)
+#########################################"
RESULT_VARIABLE ${have}
)
IF(${have} EQUAL 0)
- MESSAGE(STATUS "Checking for python module ${module} - found")
+ MESSAGE(STATUS "Python checking for ${desc} - found")
SET(${have} TRUE)
ELSE(${have} EQUAL 0)
- MESSAGE(STATUS "Checking for python module ${module} - not found")
+ MESSAGE(STATUS "Python checking for ${desc} - not found")
SET(${have} FALSE)
ENDIF(${have} EQUAL 0)
ENDMACRO(PYTHON_CHECK_MODULE)
-
-########################################################################
-# Check Modules
-########################################################################
-PYTHON_CHECK_MODULE("Cheetah" HAVE_PYTHON_MODULE_CHEETAH)
-
-IF(NOT HAVE_PYTHON_MODULE_CHEETAH)
- MESSAGE(FATAL_ERROR "Error: Cheetah Templates required by the build system.")
-ENDIF(NOT HAVE_PYTHON_MODULE_CHEETAH)
diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt
index 65db3befc..4d3269543 100644
--- a/host/docs/CMakeLists.txt
+++ b/host/docs/CMakeLists.txt
@@ -20,6 +20,7 @@
########################################################################
SET(manual_sources
index.rst
+ identification.rst
build.rst
coding.rst
dboards.rst
diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst
index d93fb9d6a..7f205c404 100644
--- a/host/docs/dboards.rst
+++ b/host/docs/dboards.rst
@@ -26,9 +26,13 @@ The boards have no tunable elements or programmable gains.
Though the magic of aliasing, you can down-convert signals
greater than the Nyquist rate of the ADC.
-BasicRX Bandwidth (Hz): 250M
+BasicRX Bandwidth (Hz):
+ For Real-Mode (A or B subdevice): 250M
+ For Complex (AB or BA subdevice): 500M
-LFRX Bandwidth (Hz): 30M
+LFRX Bandwidth (Hz):
+ For Real-Mode (A or B subdevice): 33M
+ For Complex (AB or BA subdevice): 66M
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Basic TX and and LFTX
@@ -45,8 +49,12 @@ Though the magic of aliasing, you can up-convert signals
greater than the Nyquist rate of the DAC.
BasicTX Bandwidth (Hz): 250M
+ For Real-Mode (A or B subdevice): 250M
+ For Complex (AB or BA subdevice): 500M
-LFTX Bandwidth (Hz): 30M
+LFTX Bandwidth (Hz): 33M
+ For Real-Mode (A or B subdevice): 33M
+ For Complex (AB or BA subdevice): 66M
^^^^^^^^^^^^^^^^^^^^^^^^^^^
DBSRX
@@ -149,7 +157,7 @@ Modification usually involves moving/removing a SMT component
and burning a new daughterboard id into the eeprom.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-DBSRX
+DBSRX - Mod
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Due to different clocking capabilities,
@@ -179,3 +187,45 @@ With the daughterboard plugged-in, run the following commands:
* <args> are device address arguments (optional if only one USRP is on your machine)
* <slot> is the name of the daughterboard slot (optional if the USRP has only one slot)
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+RFX - Mod
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Older RFX boards require modifications to use the motherboard oscillator.
+If this is the case, UHD will print a warning about the modification.
+Please follow the modification procedures below:
+
+**Step 1: Disable the daughterboard clocks**
+
+Move R64 to R84, Move R142 to R153
+
+**Step 2: Connect the motherboard blocks**
+
+Move R35 to R36, Move R117 to R115
+These are all 0-ohm, so if you lose one, just short across the appropriate pads
+
+**Step 3: Burn the appropriate daughterboard id into the EEPROM**
+
+With the daughterboard plugged-in, run the following commands:
+::
+
+ cd <prefix>/share/uhd/utils
+ ./usrp_burn_db_eeprom --id=<rx_id> --unit=RX --args=<args> --slot=<slot>
+ ./usrp_burn_db_eeprom --id=<tx_id> --unit=TX --args=<args> --slot=<slot>
+
+* <rx_id> choose the appropriate RX ID for your daughterboard
+
+ * **RFX400:** 0x0024
+ * **RFX900:** 0x0025
+ * **RFX1800:** 0x0034
+ * **RFX1200:** 0x0026
+ * **RFX2400:** 0x0027
+* <tx_id> choose the appropriate TX ID for your daughterboard
+
+ * **RFX400:** 0x0028
+ * **RFX900:** 0x0029
+ * **RFX1800:** 0x0035
+ * **RFX1200:** 0x002a
+ * **RFX2400:** 0x002b
+* <args> are device address arguments (optional if only one USRP is on your machine)
+* <slot> is the name of the daughterboard slot (optional if the USRP has only one slot)
diff --git a/host/docs/identification.rst b/host/docs/identification.rst
new file mode 100644
index 000000000..49d36ec1a
--- /dev/null
+++ b/host/docs/identification.rst
@@ -0,0 +1,97 @@
+========================================================================
+UHD - Device Identification Notes
+========================================================================
+
+.. contents:: Table of Contents
+
+------------------------------------------------------------------------
+Identifying USRPs
+------------------------------------------------------------------------
+Every device has several ways of identifying it on the host system:
+
+* **Serial:** A globally unique identifier.
+* **Address:** A unique identifier on a network.
+* **Name:** An optional user-set identifier.
+
+The address is only applicable for network-based devices.
+See the USRP2 application notes.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Device discovery via command line
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+A "find devices" utility application comes bundled with the UHD.
+The find devices application will search for all devices on the host system and print the results.
+
+::
+
+ uhd_find_devices
+
+Device address arguments can be supplied to narrow the scope of the search.
+
+::
+
+ uhd_find_devices --args="type=usrp1"
+
+ -- OR --
+
+ uhd_find_devices --args="serial=12345678"
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Device discovery through the API
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The device::find() API call searches for devices and returns a list of discovered devices.
+
+::
+
+ uhd::device_addr_t hint; //an empty hint discovers all devices
+ uhd::device_addrs_t dev_addrs = uhd::device::find(hint);
+
+The hint argument can be populated to narrow the scope of the search.
+
+::
+
+ uhd::device_addr_t hint;
+ hint["type"] = "usrp1";
+ uhd::device_addrs_t dev_addrs = uhd::device::find(hint);
+
+ -- OR --
+
+ uhd::device_addr_t hint;
+ hint["serial"] = "12345678";
+ uhd::device_addrs_t dev_addrs = uhd::device::find(hint);
+
+------------------------------------------------------------------------
+Naming a USRP
+------------------------------------------------------------------------
+For convenience purposes, users may assign a custom name to their USRPs.
+The USRP can then be identified via name, rather than a difficult to remember serial or address.
+
+A name has the following properties:
+
+* is composed of ASCII characters
+* is between 0 and 20 characters
+* is not required to be unique
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Set a custom name
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Run the following commands:
+::
+
+ cd <prefix>/share/uhd/utils
+ ./usrp_burn_mb_eeprom --args=<optional device args> --key=name --val=lab1_xcvr
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Discovery via name
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The keyword "name" can be used to narrow the scope of the search.
+Example with the find devices utility:
+::
+
+ uhd_find_devices --args="name=lab1_xcvr"
+
+ -- OR --
+
+ uhd_find_devices --args="type=usrp1, name=lab1_xcvr"
diff --git a/host/docs/index.rst b/host/docs/index.rst
index 7f8129e2d..9d6d14d0f 100644
--- a/host/docs/index.rst
+++ b/host/docs/index.rst
@@ -21,6 +21,7 @@ Building the UHD
Application Notes
^^^^^^^^^^^^^^^^^^^^^
* `General Application Notes <./general.html>`_
+* `Device Identification Notes <./identification.html>`_
* `Firmware and FPGA Image Notes <./images.html>`_
* `USRP1 Application Notes <./usrp1.html>`_
* `USRP2 Application Notes <./usrp2.html>`_
diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst
index 3443fd871..be684e20e 100644
--- a/host/docs/usrp1.rst
+++ b/host/docs/usrp1.rst
@@ -4,36 +4,6 @@ UHD - USRP1 Application Notes
.. contents:: Table of Contents
-------------------------------------------------------------------------
-Addressing the device
-------------------------------------------------------------------------
-A USRP1 can be identified though its 8 digit serial number,
-designated by the "serial" key in the device address.
-
-The device address string representation for a USRP1 with serial 12345678:
-
-::
-
- serial=12345678
-
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Change the serial number
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The USRP1 serial number can be changed to any 8 byte string. Examples:
-
-::
-
- cd <prefix>/share/uhd/utils
- ./usrp1_serial_burner --new=87654321
-
- -- OR --
-
- ./usrp1_serial_burner --new=Beatrice
-
- -- OR --
-
- ./usrp1_serial_burner --old=12345678 --new=87654321
-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Specify a non-standard image
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index 0ddcaa4e5..d07175ce4 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -11,9 +11,14 @@ Load the images onto the SD card
Use the usrp2_card_burner.py with caution. If you specify the wrong device node,
you could overwrite your hard drive. Make sure that --dev= specifies the SD card.
-Use the *--list* option to get a list of possible raw devices.
-The list result will filter out disk partitions and devices too large to be the sd card.
-The list option has been implemented on Linux, Mac OS X, and Windows.
+**Warning!**
+It is possible to use 3rd party SD cards with the USRP2.
+However, certain types of SD cards will not interface with the CPLD:
+
+* Cards can be SDHC, which is not a supported interface.
+* Cards can have unexpected timing characteristics.
+
+For these reasons, we recommend that you use the SD card that was supplied with the USRP2.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use the card burner tool (unix)
@@ -28,6 +33,10 @@ Use the card burner tool (unix)
sudo ./usrp2_card_burner.py --dev=/dev/sd<XXX> --fpga=<path_to_fpga_image>
sudo ./usrp2_card_burner.py --dev=/dev/sd<XXX> --fw=<path_to_firmware_image>
+Use the *--list* option to get a list of possible raw devices.
+The list result will filter out disk partitions and devices too large to be the sd card.
+The list option has been implemented on Linux, Mac OS X, and Windows.
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use the card burner tool (windows)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -97,7 +106,7 @@ Run the following commands:
::
cd <prefix>/share/uhd/utils
- ./usrp_addr_burner --addr=192.168.10.2 --new-ip=192.168.10.3
+ ./usrp_burn_mb_eeprom --args=<optional device args> --key=ip-addr --val=192.168.10.3
**Method 2 (Linux Only):**
This method assumes that you do not know the IP address of your USRP2.
@@ -179,8 +188,8 @@ The LEDs reveal the following about the state of the device:
* **LED B:** undocumented
* **LED C:** receiving
* **LED D:** firmware loaded
-* **LED E:** undocumented
-* **LED F:** FPGA loaded
+* **LED E:** reference lock
+* **LED F:** CPLD loaded
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp
index b14fc5425..6166140a0 100644
--- a/host/include/uhd/types/dict.hpp
+++ b/host/include/uhd/types/dict.hpp
@@ -71,6 +71,14 @@ namespace uhd{
bool has_key(const Key &key) const;
/*!
+ * Get a value in the dict or default.
+ * \param key the key to look for
+ * \param def use if key not found
+ * \return the value or default
+ */
+ const Val &get(const Key &key, const Val &def) const;
+
+ /*!
* Get a value for the given key if it exists.
* If the key is not found throw an error.
* \param key the key to look for
diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp
index 85071e6fd..ba05d5272 100644
--- a/host/include/uhd/types/dict.ipp
+++ b/host/include/uhd/types/dict.ipp
@@ -28,7 +28,7 @@ namespace uhd{
namespace /*anon*/{
template<typename Key, typename Val>
- struct UHD_API key_not_found: std::out_of_range{
+ struct key_not_found: std::out_of_range{
key_not_found(const Key &key): std::out_of_range(
str(boost::format(
"key \"%s\" not found in dict(%s, %s)"
@@ -86,6 +86,14 @@ namespace uhd{
}
template <typename Key, typename Val>
+ const Val &dict<Key, Val>::get(const Key &key, const Val &def) const{
+ BOOST_FOREACH(const pair_t &p, _map){
+ if (p.first == key) return p.second;
+ }
+ return def;
+ }
+
+ template <typename Key, typename Val>
const Val &dict<Key, Val>::operator[](const Key &key) const{
BOOST_FOREACH(const pair_t &p, _map){
if (p.first == key) return p.second;
diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt
index abddf3951..cdf31df87 100644
--- a/host/include/uhd/usrp/CMakeLists.txt
+++ b/host/include/uhd/usrp/CMakeLists.txt
@@ -34,6 +34,7 @@ INSTALL(FILES
### utilities ###
dsp_utils.hpp
+ mboard_eeprom.hpp
misc_utils.hpp
subdev_spec.hpp
tune_helper.hpp
diff --git a/host/include/uhd/usrp/mboard_eeprom.hpp b/host/include/uhd/usrp/mboard_eeprom.hpp
new file mode 100644
index 000000000..f44275aad
--- /dev/null
+++ b/host/include/uhd/usrp/mboard_eeprom.hpp
@@ -0,0 +1,64 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_USRP_MBOARD_EEPROM_HPP
+#define INCLUDED_UHD_USRP_MBOARD_EEPROM_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/types/serial.hpp>
+#include <string>
+
+namespace uhd{ namespace usrp{
+
+ /*!
+ * The motherboard EEPROM object:
+ * Knows how to read and write the EEPROM for various USRPs.
+ * The class inherits from a string, string dictionary.
+ * Use the dictionary interface to get and set values.
+ * Commit to the EEPROM to save changed settings.
+ */
+ struct UHD_API mboard_eeprom_t : uhd::dict<std::string, std::string>{
+
+ //! Possible EEPROM maps types
+ enum map_type{
+ MAP_NXXX,
+ MAP_B1XX
+ };
+
+ //! Make a new empty mboard eeprom
+ mboard_eeprom_t(void);
+
+ /*!
+ * Make a new mboard EEPROM handler.
+ * \param iface the interface to i2c
+ * \param map the map type enum
+ */
+ mboard_eeprom_t(i2c_iface &iface, map_type map);
+
+ /*!
+ * Write the contents of this object to the EEPROM.
+ * \param iface the interface to i2c
+ * \param map the map type enum
+ */
+ void commit(i2c_iface &iface, map_type map);
+
+ };
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_USRP_MBOARD_EEPROM_HPP */
diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp
index 0f250f439..df94d1678 100644
--- a/host/include/uhd/usrp/mboard_props.hpp
+++ b/host/include/uhd/usrp/mboard_props.hpp
@@ -44,7 +44,8 @@ namespace uhd{ namespace usrp{
MBOARD_PROP_CLOCK_CONFIG = 'C', //rw, clock_config_t
MBOARD_PROP_TIME_NOW = 't', //rw, time_spec_t
MBOARD_PROP_TIME_NEXT_PPS = 'T', //wo, time_spec_t
- MBOARD_PROP_STREAM_CMD = 's' //wo, stream_cmd_t
+ MBOARD_PROP_STREAM_CMD = 's', //wo, stream_cmd_t
+ MBOARD_PROP_EEPROM_MAP = 'M' //wr, mboard_eeprom_t::sptr
};
}} //namespace
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 81845de21..e4de7bcc7 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -16,6 +16,25 @@
#
########################################################################
+# Check Python Modules
+########################################################################
+PYTHON_CHECK_MODULE(
+ "Python version 2.6 or greater"
+ "platform" "platform.python_version() >= '2.6'"
+ HAVE_PYTHON_PLAT_MIN_VERSION
+)
+
+PYTHON_CHECK_MODULE(
+ "Cheetah templates 2.0.0 or greater"
+ "Cheetah" "Cheetah.Version >= '2.0.0'"
+ HAVE_PYTHON_MODULE_CHEETAH
+)
+
+IF(NOT HAVE_PYTHON_PLAT_MIN_VERSION OR NOT HAVE_PYTHON_MODULE_CHEETAH)
+ MESSAGE(FATAL_ERROR "Error: python requirements not met for the build system.")
+ENDIF(NOT HAVE_PYTHON_PLAT_MIN_VERSION OR NOT HAVE_PYTHON_MODULE_CHEETAH)
+
+########################################################################
# Helpful Macros
########################################################################
MACRO(LIBUHD_APPEND_SOURCES)
diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt
index 25f34a280..a328fa033 100644
--- a/host/lib/ic_reg_maps/CMakeLists.txt
+++ b/host/lib/ic_reg_maps/CMakeLists.txt
@@ -60,6 +60,16 @@ LIBUHD_PYTHON_GEN_SOURCE(
)
LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_max2112_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/max2112_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_max2112_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/max2112_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9862_regs.py
${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9862_regs.hpp
)
diff --git a/host/lib/ic_reg_maps/gen_max2112_regs.py b/host/lib/ic_reg_maps/gen_max2112_regs.py
new file mode 100755
index 000000000..c2fc4e3e2
--- /dev/null
+++ b/host/lib/ic_reg_maps/gen_max2112_regs.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+#
+# 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/>.
+#
+
+########################################################################
+# Template for raw text data describing write registers
+# name addr[bit range inclusive] default optional enums
+########################################################################
+WRITE_REGS_TMPL="""\
+########################################################################
+## Note: offsets given from perspective of data bits (excludes address)
+########################################################################
+##
+########################################################################
+## N-Divider MSB (0) Write
+########################################################################
+frac 0[7] 1 invalid, frac
+n_divider_msb 0[0:6] 0
+########################################################################
+## N-Divider LSB (1) Write
+########################################################################
+n_divider_lsb 1[0:7] 0x23
+~n_divider n_divider_lsb, n_divider_msb
+########################################################################
+## Charge Pump (2) Write
+########################################################################
+cpmp 2[6:7] 0
+cplin 2[4:5] 1
+f_divider_mmsb 2[0:3] 0x2
+########################################################################
+## F-Divider MSB (3) Write
+########################################################################
+f_divider_msb 3[0:7] 0xF6
+########################################################################
+## F-Divider LSB (4) Write
+########################################################################
+f_divider_lsb 4[0:7] 0x84
+~f_divider f_divider_lsb, f_divider_msb, f_divider_mmsb
+########################################################################
+## XTAL-Divider R-Divider (5) Write
+########################################################################
+#set $xtal_divider_names = ', '.join(map(lambda x: 'div' + str(x), range(1,9)))
+xtal_divider 5[5:7] 0 $xtal_divider_names
+r_divider 5[0:4] 1
+########################################################################
+## PLL (6) Write
+########################################################################
+d24 6[7] 1 div2, div4 ## div2 for LO <= 1125M, div4 > 1125M
+cps 6[6] 1 i_cp_from_icp, i_cp_from_vas
+icp 6[5] 0 i_cp_600ua, i_cp_1200ua
+##reserved 6[0:4] 0
+########################################################################
+## VCO (7) Write
+########################################################################
+vco 7[3:7] 0x19
+vas 7[2] 1 disabled, enabled
+adl 7[1] 1 disabled, enabled
+ade 7[0] 1 disabled, enabled
+########################################################################
+## LPF (8) Write
+########################################################################
+lp 8[0:7] 0x4B ## map(lambda x: "%0.2f"%((4e6 + (x - 12) * 290e3)/1e6), range(255)) in MHz
+########################################################################
+## Control (9) Write
+########################################################################
+stby 9[7] 0 normal, disable_sig_and_synth
+##reserved 9[6] 0
+pwdn 9[5] 0 normal, invalid
+##reserved 9[4] 0
+bbg 9[0:3] 0 ## Baseband Gain in dB
+########################################################################
+## Shutdown (0xA) Write
+########################################################################
+##reserved 0xA[7] 0
+pll_shutdown 0xA[6] 0 normal, shutdown
+div_shutdown 0xA[5] 0 normal, shutdown
+vco_shutdown 0xA[4] 0 normal, shutdown
+bb_shutdown 0xA[3] 0 normal, shutdown
+rfmix_shutdown 0xA[2] 0 normal, shutdown
+rfvga_shutdown 0xA[1] 0 normal, shutdown
+fe_shutdown 0xA[0] 0 normal, shutdown
+########################################################################
+## Test (0xB) Write
+########################################################################
+cptst 0xB[5:7] 0
+##reserved 0xB[4] 0
+turbo 0xB[3] 1
+ld_mux 0xB[0:2] 0 refout=0, invalid
+"""
+
+########################################################################
+# Template for raw text data describing read registers
+# name addr[bit range inclusive] default optional enums
+########################################################################
+READ_REGS_TMPL="""\
+########################################################################
+## Status Byte-1 (0xC) Read
+########################################################################
+por 0xC[7] 0 read, reset
+vasa 0xC[6] 0 vas_fail, vas_win
+vase 0xC[5] 0 active, inactive
+ld 0xC[4] 0 unlocked, locked
+##reserved 0xC[0:3] 0
+########################################################################
+## Status Byte-2 (0xD) Read
+########################################################################
+vcosbr 0xD[3:7] 0 ## vco band readback
+adc 0xD[0:2] 0 ool0, lock0, vaslock0, vaslock1, vaslock2, vaslock3, lock1, ool1
+"""
+
+########################################################################
+# Template for methods in the body of the struct
+########################################################################
+BODY_TMPL="""\
+boost::uint8_t get_reg(boost::uint8_t addr){
+ boost::uint8_t reg = 0;
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
+ #end for
+ break;
+ #end for
+ }
+ return boost::uint8_t(reg);
+}
+
+void set_reg(boost::uint8_t addr, boost::uint8_t reg){
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ $reg.get_name() = $(reg.get_type())((reg >> $reg.get_shift()) & $reg.get_mask());
+ #end for
+ break;
+ #end for
+ }
+}
+"""
+
+SPLIT_REGS_HELPER_TMPL="""\
+#for $divname in ['n','f']
+void set_$(divname)_divider(boost::uint32_t $divname){
+ #for $regname in sorted(map(lambda r: r.get_name(), filter(lambda r: r.get_name().find(divname + '_divider') == 0, $regs)))
+ #end for
+}
+#end for
+"""
+ #$regname = boost::uint8_t($divname & $regs[regname].get_mask());
+ #$divname = boost::uint32_t($divname >> $regs[regname].get_shift());
+
+if __name__ == '__main__':
+ import common; common.generate(
+ name='max2112_write_regs',
+ regs_tmpl=WRITE_REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
+
+ import common; common.generate(
+ name='max2112_read_regs',
+ regs_tmpl=READ_REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ append=True,
+ )
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index 4188568aa..e5e6a2512 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -250,22 +250,19 @@ mac_addr_t mac_addr_t::from_bytes(const byte_vector_t &bytes){
mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
- byte_vector_t bytes = boost::assign::list_of
- (0x00)(0x50)(0xC2)(0x85)(0x30)(0x00); // Matt's IAB
+ byte_vector_t bytes;
try{
- //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx
- //the IAB above will fill in for the shorter pattern
- if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17)
- throw std::runtime_error("expected exactly 5 or 17 characters");
+ if (mac_addr_str.size() != 17){
+ throw std::runtime_error("expected exactly 17 characters");
+ }
//split the mac addr hex string at the colons
- size_t i = 0;
BOOST_FOREACH(const std::string &hex_str, std::split_string(mac_addr_str, ":")){
int hex_num;
std::istringstream iss(hex_str);
iss >> std::hex >> hex_num;
- bytes[i++] = boost::uint8_t(hex_num);
+ bytes.push_back(boost::uint8_t(hex_num));
}
}
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index c264252e1..bb7e83214 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -23,6 +23,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/mboard_eeprom.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/multi_usrp.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/single_usrp.cpp
diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt
index 8d3d11530..79cd42d18 100644
--- a/host/lib/usrp/dboard/CMakeLists.txt
+++ b/host/lib/usrp/dboard/CMakeLists.txt
@@ -25,5 +25,6 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_dbsrx.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_unknown.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_tvrx.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_dbsrx2.cpp
)
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index 4c49b3bff..f03dd43d1 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -31,6 +31,16 @@ using namespace uhd::usrp;
using namespace boost::assign;
/***********************************************************************
+ * Constants
+ **********************************************************************/
+static const uhd::dict<std::string, double> subdev_bandwidth_scalar = map_list_of
+ ("A", 1.0)
+ ("B", 1.0)
+ ("AB", 2.0)
+ ("BA", 2.0)
+;
+
+/***********************************************************************
* The basic and lf boards:
* They share a common class because only the frequency bounds differ.
**********************************************************************/
@@ -163,7 +173,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = 2*_max_freq; //we want complex double-sided
+ val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq;
return;
default: UHD_THROW_PROP_GET_ERROR();
@@ -274,7 +284,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = 2*_max_freq; //we want complex double-sided
+ val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq;
return;
default: UHD_THROW_PROP_GET_ERROR();
diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp
new file mode 100644
index 000000000..5a65e6123
--- /dev/null
+++ b/host/lib/usrp/dboard/db_dbsrx2.cpp
@@ -0,0 +1,439 @@
+//
+// 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/>.
+//
+
+// No RX IO Pins Used
+
+#include "max2112_regs.hpp"
+#include <uhd/utils/static.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/algorithm.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/usrp/dboard_base.hpp>
+#include <uhd/usrp/dboard_manager.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/format.hpp>
+#include <boost/thread.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <utility>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace boost::assign;
+
+/***********************************************************************
+ * The DBSRX2 constants
+ **********************************************************************/
+static const bool dbsrx2_debug = false;
+
+static const freq_range_t dbsrx2_freq_range(0.8e9, 2.4e9);
+
+static const int dbsrx2_ref_divider = 4; // Hitachi HMC426 divider (U7)
+
+static const prop_names_t dbsrx2_antennas = list_of("J3");
+
+static const uhd::dict<std::string, gain_range_t> dbsrx2_gain_ranges = map_list_of
+ ("GC1", gain_range_t(0, 73, float(0.05)))
+ ("BBG", gain_range_t(0, 15, 1))
+;
+
+/***********************************************************************
+ * The DBSRX2 dboard class
+ **********************************************************************/
+class dbsrx2 : public rx_dboard_base{
+public:
+ dbsrx2(ctor_args_t args);
+ ~dbsrx2(void);
+
+ void rx_get(const wax::obj &key, wax::obj &val);
+ void rx_set(const wax::obj &key, const wax::obj &val);
+
+private:
+ double _lo_freq;
+ double _bandwidth;
+ uhd::dict<std::string, float> _gains;
+ max2112_write_regs_t _max2112_write_regs;
+ max2112_read_regs_t _max2112_read_regs;
+ boost::uint8_t _max2112_addr(){ //0x60 or 0x61 depending on which side
+ return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61;
+ }
+
+ void set_lo_freq(double target_freq);
+ void set_gain(float gain, const std::string &name);
+ void set_bandwidth(double bandwidth);
+
+ void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){
+ start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0xB));
+ stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0xB));
+
+ for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t) - 1){
+ int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) - 1 ? sizeof(boost::uint32_t) - 1 : stop_reg - start_addr + 1;
+
+ //create buffer for register data (+1 for start address)
+ byte_vector_t regs_vector(num_bytes + 1);
+
+ //first byte is the address of first register
+ regs_vector[0] = start_addr;
+
+ //get the register data
+ for(int i=0; i<num_bytes; i++){
+ regs_vector[1+i] = _max2112_write_regs.get_reg(start_addr+i);
+ if(dbsrx2_debug) std::cerr << boost::format(
+ "DBSRX2: send reg 0x%02x, value 0x%04x, start_addr = 0x%04x, num_bytes %d"
+ ) % int(start_addr+i) % int(regs_vector[1+i]) % int(start_addr) % num_bytes << std::endl;
+ }
+
+ //send the data
+ this->get_iface()->write_i2c(
+ _max2112_addr(), regs_vector
+ );
+ }
+ }
+
+ void read_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){
+ static const boost::uint8_t status_addr = 0xC;
+ start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0xD));
+ stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0xD));
+
+ for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t)){
+ int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) ? sizeof(boost::uint32_t) : stop_reg - start_addr + 1;
+
+ //create address to start reading register data
+ byte_vector_t address_vector(1);
+ address_vector[0] = start_addr;
+
+ //send the address
+ this->get_iface()->write_i2c(
+ _max2112_addr(), address_vector
+ );
+
+ //create buffer for register data
+ byte_vector_t regs_vector(num_bytes);
+
+ //read from i2c
+ regs_vector = this->get_iface()->read_i2c(
+ _max2112_addr(), num_bytes
+ );
+
+ for(boost::uint8_t i=0; i < num_bytes; i++){
+ if (i + start_addr >= status_addr){
+ _max2112_read_regs.set_reg(i + start_addr, regs_vector[i]);
+ /*
+ if(dbsrx2_debug) std::cerr << boost::format(
+ "DBSRX2: set reg 0x%02x, value 0x%04x"
+ ) % int(i + start_addr) % int(_max2112_read_regs.get_reg(i + start_addr)) << std::endl;
+ */
+ }
+ if(dbsrx2_debug) std::cerr << boost::format(
+ "DBSRX2: read reg 0x%02x, value 0x%04x, start_addr = 0x%04x, num_bytes %d"
+ ) % int(start_addr+i) % int(regs_vector[i]) % int(start_addr) % num_bytes << std::endl;
+ }
+ }
+ }
+
+ /*!
+ * Is the LO locked?
+ * \return true for locked
+ */
+ bool get_locked(void){
+ read_reg(0xC, 0xD);
+
+ //mask and return lock detect
+ bool locked = (_max2112_read_regs.ld & _max2112_read_regs.vasa & _max2112_read_regs.vase) != 0;
+
+ if(dbsrx2_debug) std::cerr << boost::format(
+ "DBSRX2 locked: %d"
+ ) % locked << std::endl;
+
+ return locked;
+ }
+
+};
+
+/***********************************************************************
+ * Register the DBSRX2 dboard
+ **********************************************************************/
+// FIXME 0x67 is the default i2c address on USRP2
+// need to handle which side for USRP1 with different address
+static dboard_base::sptr make_dbsrx2(dboard_base::ctor_args_t args){
+ return dboard_base::sptr(new dbsrx2(args));
+}
+
+UHD_STATIC_BLOCK(reg_dbsrx2_dboard){
+ //register the factory function for the rx dbid
+ dboard_manager::register_dboard(0x0012, &make_dbsrx2, "DBSRX2");
+}
+
+/***********************************************************************
+ * Structors
+ **********************************************************************/
+dbsrx2::dbsrx2(ctor_args_t args) : rx_dboard_base(args){
+ //enable only the clocks we need
+ this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true);
+
+ //set the gpio directions and atr controls (identically)
+ this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr
+ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs
+
+ //send initial register settings
+ send_reg(0x0, 0xB);
+ //for (boost::uint8_t addr=0; addr<=12; addr++) this->send_reg(addr, addr);
+
+ //set defaults for LO, gains
+ set_lo_freq(dbsrx2_freq_range.min);
+ BOOST_FOREACH(const std::string &name, dbsrx2_gain_ranges.keys()){
+ set_gain(dbsrx2_gain_ranges[name].min, name);
+ }
+
+ set_bandwidth(40e6); // default bandwidth from datasheet
+ get_locked();
+
+ _max2112_write_regs.bbg = boost::math::iround(std::clip<float>(0, dbsrx2_gain_ranges["BBG"].min, dbsrx2_gain_ranges["BBG"].max));
+ send_reg(0x9, 0x9);
+}
+
+dbsrx2::~dbsrx2(void){
+}
+
+
+/***********************************************************************
+ * Tuning
+ **********************************************************************/
+void dbsrx2::set_lo_freq(double target_freq){
+ //target_freq = std::clip(target_freq, dbsrx2_freq_range.min, dbsrx2_freq_range.max);
+
+ //variables used in the calculation below
+ int scaler = target_freq > 1125e6 ? 2 : 4;
+ double ref_freq = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX);
+ int R, intdiv, fracdiv, ext_div;
+ double N;
+
+ //compute tuning variables
+ ext_div = dbsrx2_ref_divider; // 12MHz < ref_freq/ext_divider < 30MHz
+
+ R = 1; //Divide by 1 is the only tested value
+
+ N = (target_freq*R*ext_div)/(ref_freq); //actual spec range is (19, 251)
+ intdiv = int(std::floor(N)); // if (intdiv < 19 or intdiv > 251) continue;
+ fracdiv = boost::math::iround((N - intdiv)*double(1 << 20));
+
+ //calculate the actual freq from the values above
+ N = double(intdiv) + double(fracdiv)/double(1 << 20);
+ _lo_freq = (N*ref_freq)/(R*ext_div);
+
+ //load new counters into registers
+ _max2112_write_regs.set_n_divider(intdiv);
+ _max2112_write_regs.set_f_divider(fracdiv);
+ _max2112_write_regs.r_divider = R;
+ _max2112_write_regs.d24 = scaler == 4 ? max2112_write_regs_t::D24_DIV4 : max2112_write_regs_t::D24_DIV2;
+
+ //debug output of calculated variables
+ if (dbsrx2_debug) std::cerr
+ << boost::format("DBSRX2 tune:\n")
+ << boost::format(" R=%d, N=%f, scaler=%d, ext_div=%d\n") % R % N % scaler % ext_div
+ << boost::format(" int=%d, frac=%d, d24=%d\n") % intdiv % fracdiv % int(_max2112_write_regs.d24)
+ << boost::format(" Ref Freq=%fMHz\n") % (ref_freq/1e6)
+ << boost::format(" Target Freq=%fMHz\n") % (target_freq/1e6)
+ << boost::format(" Actual Freq=%fMHz\n") % (_lo_freq/1e6)
+ << std::endl;
+
+ //send the registers
+ send_reg(0x0, 0x7);
+
+ //FIXME: probably unnecessary to call get_locked here
+ //get_locked();
+
+}
+
+/***********************************************************************
+ * Gain Handling
+ **********************************************************************/
+/*!
+ * Convert a requested gain for the BBG vga into the integer register value.
+ * The gain passed into the function will be set to the actual value.
+ * \param gain the requested gain in dB
+ * \return 4 bit the register value
+ */
+static int gain_to_bbg_vga_reg(float &gain){
+ int reg = boost::math::iround(std::clip<float>(gain, dbsrx2_gain_ranges["BBG"].min, dbsrx2_gain_ranges["BBG"].max));
+
+ gain = float(reg);
+
+ if (dbsrx2_debug) std::cerr
+ << boost::format("DBSRX2 BBG Gain:\n")
+ << boost::format(" %f dB, bbg: %d") % gain % reg
+ << std::endl;
+
+ return reg;
+}
+
+/*!
+ * Convert a requested gain for the GC1 rf vga into the dac_volts value.
+ * The gain passed into the function will be set to the actual value.
+ * \param gain the requested gain in dB
+ * \return dac voltage value
+ */
+static float gain_to_gc1_rfvga_dac(float &gain){
+ //clip the input
+ gain = std::clip<float>(gain, dbsrx2_gain_ranges["GC1"].min, dbsrx2_gain_ranges["GC1"].max);
+
+ //voltage level constants
+ static const float max_volts = float(0.5), min_volts = float(2.7);
+ static const float slope = (max_volts-min_volts)/dbsrx2_gain_ranges["GC1"].max;
+
+ //calculate the voltage for the aux dac
+ float dac_volts = gain*slope + min_volts;
+
+ if (dbsrx2_debug) std::cerr
+ << boost::format("DBSRX2 GC1 Gain:\n")
+ << boost::format(" %f dB, dac_volts: %f V") % gain % dac_volts
+ << std::endl;
+
+ //the actual gain setting
+ gain = (dac_volts - min_volts)/slope;
+
+ return dac_volts;
+}
+
+void dbsrx2::set_gain(float gain, const std::string &name){
+ assert_has(dbsrx2_gain_ranges.keys(), name, "dbsrx2 gain name");
+ if (name == "BBG"){
+ _max2112_write_regs.bbg = gain_to_bbg_vga_reg(gain);
+ send_reg(0x9, 0x9);
+ }
+ else if(name == "GC1"){
+ //write the new voltage to the aux dac
+ this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, gain_to_gc1_rfvga_dac(gain));
+ }
+ else UHD_THROW_INVALID_CODE_PATH();
+ _gains[name] = gain;
+}
+
+/***********************************************************************
+ * Bandwidth Handling
+ **********************************************************************/
+void dbsrx2::set_bandwidth(double bandwidth){
+ //clip the input
+ bandwidth = std::clip<double>(bandwidth, 4e6, 40e6);
+
+ _max2112_write_regs.lp = int((bandwidth/1e6 - 4)/0.29 + 12);
+ _bandwidth = double(4 + (_max2112_write_regs.lp - 12) * 0.29)*1e6;
+
+ if (dbsrx2_debug) std::cerr
+ << boost::format("DBSRX2 Bandwidth:\n")
+ << boost::format(" %f MHz, lp: %f V") % (_bandwidth/1e6) % int(_max2112_write_regs.lp)
+ << std::endl;
+
+ this->send_reg(0x8, 0x8);
+}
+
+/***********************************************************************
+ * RX Get and Set
+ **********************************************************************/
+void dbsrx2::rx_get(const wax::obj &key_, wax::obj &val){
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_NAME:
+ val = get_rx_id().to_pp_string();
+ return;
+
+ case SUBDEV_PROP_OTHERS:
+ val = prop_names_t(); //empty
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ assert_has(_gains.keys(), key.name, "dbsrx2 gain name");
+ val = _gains[key.name];
+ return;
+
+ case SUBDEV_PROP_GAIN_RANGE:
+ assert_has(dbsrx2_gain_ranges.keys(), key.name, "dbsrx2 gain name");
+ val = dbsrx2_gain_ranges[key.name];
+ return;
+
+ case SUBDEV_PROP_GAIN_NAMES:
+ val = prop_names_t(dbsrx2_gain_ranges.keys());
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ val = _lo_freq;
+ return;
+
+ case SUBDEV_PROP_FREQ_RANGE:
+ val = dbsrx2_freq_range;
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ val = std::string("J3");
+ return;
+
+ case SUBDEV_PROP_ANTENNA_NAMES:
+ val = dbsrx2_antennas;
+ return;
+
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_QI;
+ return;
+
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_LO_LOCKED:
+ val = this->get_locked();
+ return;
+
+ case SUBDEV_PROP_BANDWIDTH:
+ val = _bandwidth;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+void dbsrx2::rx_set(const wax::obj &key_, const wax::obj &val){
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ this->set_lo_freq(val.as<double>());
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ this->set_gain(val.as<float>(), key.name);
+ return;
+
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
+ case SUBDEV_PROP_BANDWIDTH:
+ this->set_bandwidth(val.as<double>());
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
+
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 12e458d8c..152198c3a 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -458,7 +458,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = 2*20.0e6; //30MHz low-pass, we want complex double-sided
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
return;
default: UHD_THROW_PROP_GET_ERROR();
@@ -555,7 +555,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = 2*20.0e6; //30MHz low-pass, we want complex double-sided
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
return;
default: UHD_THROW_PROP_GET_ERROR();
diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp
index 1f3c76556..2873e3d54 100644
--- a/host/lib/usrp/dboard/db_tvrx.cpp
+++ b/host/lib/usrp/dboard/db_tvrx.cpp
@@ -460,7 +460,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = 6.0e6; //30MHz low-pass, we want complex double-sided
+ val = 6.0e6;
return;
default: UHD_THROW_PROP_GET_ERROR();
diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp
index a342471c4..d0359d124 100644
--- a/host/lib/usrp/dboard/db_unknown.cpp
+++ b/host/lib/usrp/dboard/db_unknown.cpp
@@ -24,19 +24,47 @@
#include <uhd/usrp/dboard_manager.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
+#include <boost/foreach.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <vector>
using namespace uhd;
using namespace uhd::usrp;
using namespace boost::assign;
/***********************************************************************
+ * Utility functions
+ **********************************************************************/
+static void warn_if_old_rfx(const dboard_id_t &dboard_id, const std::string &xx){
+ typedef boost::tuple<std::string, dboard_id_t, dboard_id_t> old_ids_t; //name, rx_id, tx_id
+ static const std::vector<old_ids_t> old_rfx_ids = list_of
+ (old_ids_t("Flex 400 Classic", 0x0004, 0x0008))
+ (old_ids_t("Flex 900 Classic", 0x0005, 0x0009))
+ (old_ids_t("Flex 1200 Classic", 0x0006, 0x000a))
+ (old_ids_t("Flex 1800 Classic", 0x0030, 0x0031))
+ (old_ids_t("Flex 2400 Classic", 0x0007, 0x000b))
+ ;
+ BOOST_FOREACH(const old_ids_t &old_id, old_rfx_ids){
+ std::string name; dboard_id_t rx_id, tx_id;
+ boost::tie(name, rx_id, tx_id) = old_id;
+ if (
+ (xx == "RX" and rx_id == dboard_id) or
+ (xx == "TX" and tx_id == dboard_id)
+ ) uhd::warning::post(str(boost::format(
+ "Detected %s daughterboard %s\n"
+ "This board requires modification to use.\n"
+ "See the daughterboard application notes.\n"
+ ) % xx % name));
+ }
+}
+
+/***********************************************************************
* The unknown boards:
* Like a basic board, but with only one subdev.
**********************************************************************/
class unknown_rx : public rx_dboard_base{
public:
unknown_rx(ctor_args_t args);
- ~unknown_rx(void);
void rx_get(const wax::obj &key, wax::obj &val);
void rx_set(const wax::obj &key, const wax::obj &val);
@@ -45,7 +73,6 @@ public:
class unknown_tx : public tx_dboard_base{
public:
unknown_tx(ctor_args_t args);
- ~unknown_tx(void);
void tx_get(const wax::obj &key, wax::obj &val);
void tx_set(const wax::obj &key, const wax::obj &val);
@@ -71,11 +98,7 @@ UHD_STATIC_BLOCK(reg_unknown_dboards){
* Unknown RX dboard
**********************************************************************/
unknown_rx::unknown_rx(ctor_args_t args) : rx_dboard_base(args){
- /* NOP */
-}
-
-unknown_rx::~unknown_rx(void){
- /* NOP */
+ warn_if_old_rfx(this->get_rx_id(), "RX");
}
void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
@@ -177,11 +200,7 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){
* Unknown TX dboard
**********************************************************************/
unknown_tx::unknown_tx(ctor_args_t args) : tx_dboard_base(args){
- /* NOP */
-}
-
-unknown_tx::~unknown_tx(void){
- /* NOP */
+ warn_if_old_rfx(this->get_tx_id(), "TX");
}
void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 647f1b975..572f5de97 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -527,7 +527,7 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = 2*30.0e6; //20MHz low-pass, we want complex double-sided
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
return;
default: UHD_THROW_PROP_GET_ERROR();
@@ -628,7 +628,7 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = 2*30.0e6; //20MHz low-pass, we want complex double-sided
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
return;
default: UHD_THROW_PROP_GET_ERROR();
diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp
new file mode 100644
index 000000000..076d0b279
--- /dev/null
+++ b/host/lib/usrp/mboard_eeprom.cpp
@@ -0,0 +1,194 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/usrp/mboard_eeprom.hpp>
+#include <uhd/types/mac_addr.hpp>
+#include <uhd/utils/algorithm.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Constants
+ **********************************************************************/
+static const size_t SERIAL_LEN = 9;
+static const size_t NAME_MAX_LEN = 32 - SERIAL_LEN;
+
+/***********************************************************************
+ * Utility functions
+ **********************************************************************/
+
+//! create a string from a byte vector, return empty if invalid ascii
+static const std::string bytes_to_string(const byte_vector_t &bytes){
+ std::string out;
+ BOOST_FOREACH(boost::uint8_t byte, bytes){
+ if (byte < 32 or byte > 127) return out;
+ out += byte;
+ }
+ return out;
+}
+
+//! create a byte vector from a string, null terminate unless max length
+static const byte_vector_t string_to_bytes(const std::string &string, size_t max_length){
+ byte_vector_t bytes;
+ for (size_t i = 0; i < std::min(string.size(), max_length); i++){
+ bytes.push_back(string[i]);
+ }
+ if (bytes.size() < max_length - 1) bytes.push_back('\0');
+ return bytes;
+}
+
+/***********************************************************************
+ * Implementation of NXXX load/store
+ **********************************************************************/
+static const boost::uint8_t NXXX_EEPROM_ADDR = 0x50;
+
+static const uhd::dict<std::string, boost::uint8_t> USRP_NXXX_OFFSETS = boost::assign::map_list_of
+ ("rev-lsb-msb", 0x00)
+ ("mac-addr", 0x02)
+ ("ip-addr", 0x08)
+ //leave space here for other addresses (perhaps)
+ ("serial", 0x18)
+ ("name", 0x18 + SERIAL_LEN)
+;
+
+static void load_nxxx(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
+ //extract the revision number
+ byte_vector_t rev_lsb_msb = iface.read_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["rev-lsb-msb"], 2);
+ boost::uint16_t rev = (boost::uint16_t(rev_lsb_msb.at(0)) << 0) | (boost::uint16_t(rev_lsb_msb.at(1)) << 8);
+ mb_eeprom["rev"] = boost::lexical_cast<std::string>(rev);
+
+ //extract the addresses
+ mb_eeprom["mac-addr"] = mac_addr_t::from_bytes(iface.read_eeprom(
+ NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["mac-addr"], 6
+ )).to_string();
+
+ boost::asio::ip::address_v4::bytes_type ip_addr_bytes;
+ std::copy(iface.read_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["ip-addr"], 4), ip_addr_bytes);
+ mb_eeprom["ip-addr"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
+
+ //extract the serial
+ mb_eeprom["serial"] = bytes_to_string(iface.read_eeprom(
+ NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["serial"], SERIAL_LEN
+ ));
+
+ //extract the name
+ mb_eeprom["name"] = bytes_to_string(iface.read_eeprom(
+ NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["name"], NAME_MAX_LEN
+ ));
+
+ //empty serial correction: use the mac address
+ if (mb_eeprom["serial"].empty()) mb_eeprom["serial"] = mb_eeprom["mac-addr"];
+}
+
+static void store_nxxx(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
+ //parse the revision number
+ if (mb_eeprom.has_key("rev")){
+ boost::uint16_t rev = boost::lexical_cast<boost::uint16_t>(mb_eeprom["rev"]);
+ byte_vector_t rev_lsb_msb = boost::assign::list_of
+ (boost::uint8_t(rev >> 0))
+ (boost::uint8_t(rev >> 8))
+ ;
+ iface.write_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["rev-lsb-msb"], rev_lsb_msb);
+ }
+
+ //store the addresses
+ if (mb_eeprom.has_key("mac-addr")) iface.write_eeprom(
+ NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["mac-addr"],
+ mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes()
+ );
+
+ if (mb_eeprom.has_key("ip-addr")){
+ byte_vector_t ip_addr_bytes(4);
+ std::copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"]).to_bytes(), ip_addr_bytes);
+ iface.write_eeprom(NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["ip-addr"], ip_addr_bytes);
+ }
+
+ //store the serial
+ if (mb_eeprom.has_key("serial")) iface.write_eeprom(
+ NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["serial"],
+ string_to_bytes(mb_eeprom["serial"], SERIAL_LEN)
+ );
+
+ //store the name
+ if (mb_eeprom.has_key("name")) iface.write_eeprom(
+ NXXX_EEPROM_ADDR, USRP_NXXX_OFFSETS["name"],
+ string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN)
+ );
+}
+
+/***********************************************************************
+ * Implementation of B1XX load/store
+ **********************************************************************/
+static const boost::uint8_t B1XX_EEPROM_ADDR = 0x50;
+static const size_t B1XXX_SERIAL_LEN = 8;
+
+static const uhd::dict<std::string, boost::uint8_t> USRP_B1XX_OFFSETS = boost::assign::map_list_of
+ ("serial", 0xf8)
+ ("name", 0xf8 - NAME_MAX_LEN)
+;
+
+static void load_b1xx(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
+ //extract the serial
+ mb_eeprom["serial"] = bytes_to_string(iface.read_eeprom(
+ B1XX_EEPROM_ADDR, USRP_B1XX_OFFSETS["serial"], B1XXX_SERIAL_LEN
+ ));
+
+ //extract the name
+ mb_eeprom["name"] = bytes_to_string(iface.read_eeprom(
+ B1XX_EEPROM_ADDR, USRP_B1XX_OFFSETS["name"], NAME_MAX_LEN
+ ));
+}
+
+static void store_b1xx(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
+ //store the serial
+ if (mb_eeprom.has_key("serial")) iface.write_eeprom(
+ B1XX_EEPROM_ADDR, USRP_B1XX_OFFSETS["serial"],
+ string_to_bytes(mb_eeprom["serial"], B1XXX_SERIAL_LEN)
+ );
+
+ //store the name
+ if (mb_eeprom.has_key("name")) iface.write_eeprom(
+ B1XX_EEPROM_ADDR, USRP_B1XX_OFFSETS["name"],
+ string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN)
+ );
+}
+
+/***********************************************************************
+ * Implementation of mboard eeprom
+ **********************************************************************/
+mboard_eeprom_t::mboard_eeprom_t(void){
+ /* NOP */
+}
+
+mboard_eeprom_t::mboard_eeprom_t(i2c_iface &iface, map_type map){
+ switch(map){
+ case MAP_NXXX: load_nxxx(*this, iface); break;
+ case MAP_B1XX: load_b1xx(*this, iface); break;
+ }
+}
+
+void mboard_eeprom_t::commit(i2c_iface &iface, map_type map){
+ switch(map){
+ case MAP_NXXX: store_nxxx(*this, iface); break;
+ case MAP_B1XX: store_b1xx(*this, iface); break;
+ }
+}
diff --git a/host/lib/usrp/usrp1/CMakeLists.txt b/host/lib/usrp/usrp1/CMakeLists.txt
index 67487f99e..022015231 100644
--- a/host/lib/usrp/usrp1/CMakeLists.txt
+++ b/host/lib/usrp/usrp1/CMakeLists.txt
@@ -40,7 +40,7 @@ ENDIF(ENABLE_USRP1 AND NOT HAVE_USB_SUPPORT)
IF(ENABLE_USRP1)
MESSAGE(STATUS " Building USRP1 support.")
- INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/../firmware/fx2/include)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/../firmware/fx2/common)
LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/clock_ctrl.cpp
diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp
index 669b20efa..c1f0f1d38 100644
--- a/host/lib/usrp/usrp1/mboard_impl.cpp
+++ b/host/lib/usrp/usrp1/mboard_impl.cpp
@@ -262,24 +262,10 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val)
{
named_prop_t key = named_prop_t::extract(key_);
- if(key_.type() == typeid(std::string)) {
- if(key.as<std::string>() == "serial") {
- uhd::byte_vector_t buf;
- buf.insert(buf.begin(), 248);
- boost::this_thread::sleep(boost::posix_time::milliseconds(100));
- _iface->write_i2c(I2C_DEV_EEPROM, buf);
- boost::this_thread::sleep(boost::posix_time::milliseconds(100));
- buf = _iface->read_i2c(I2C_DEV_EEPROM, 8);
- val = std::string(buf.begin(), buf.end());
- }
-
- return;
- }
-
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
case MBOARD_PROP_NAME:
- val = std::string("usrp1 mboard - " + (*_mboard_proxy)[std::string("serial")].as<std::string>());
+ val = std::string("usrp1 mboard - " + _iface->mb_eeprom["serial"]);
return;
case MBOARD_PROP_OTHERS:
@@ -336,6 +322,10 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val)
val = _tx_subdev_spec;
return;
+ case MBOARD_PROP_EEPROM_MAP:
+ val = _iface->mb_eeprom;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -351,14 +341,6 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)
std::cout << "USRP1 EEPROM image: " << usrp1_eeprom_image << std::endl;
_ctrl_transport->usrp_load_eeprom(val.as<std::string>());
}
-
- if(key.as<std::string>() == "serial") {
- std::string sernum = val.as<std::string>();
- uhd::byte_vector_t buf(sernum.begin(), sernum.end());
- buf.insert(buf.begin(), 248);
- _iface->write_i2c(I2C_DEV_EEPROM, buf);
- }
-
return;
}
@@ -395,6 +377,13 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)
_iface->poke32(FR_TX_MUX, calc_tx_mux(_tx_subdev_spec, _mboard_proxy->get_link()));
return;
+ case MBOARD_PROP_EEPROM_MAP:
+ // Step1: commit the map, writing only those values set.
+ // Step2: readback the entire eeprom map into the iface.
+ val.as<mboard_eeprom_t>().commit(*_iface, mboard_eeprom_t::MAP_B1XX);
+ _iface->mb_eeprom = mboard_eeprom_t(*_iface, mboard_eeprom_t::MAP_B1XX);
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp
index 64ced2905..691c51fe8 100644
--- a/host/lib/usrp/usrp1/usrp1_iface.cpp
+++ b/host/lib/usrp/usrp1/usrp1_iface.cpp
@@ -25,6 +25,7 @@
#include <iomanip>
using namespace uhd;
+using namespace uhd::usrp;
using namespace uhd::transport;
static const bool iface_debug = false;
@@ -36,7 +37,8 @@ public:
******************************************************************/
usrp1_iface_impl(usrp_ctrl::sptr ctrl_transport)
{
- _ctrl_transport = ctrl_transport;
+ _ctrl_transport = ctrl_transport;
+ mb_eeprom = mboard_eeprom_t(*this, mboard_eeprom_t::MAP_B1XX);
}
~usrp1_iface_impl(void)
diff --git a/host/lib/usrp/usrp1/usrp1_iface.hpp b/host/lib/usrp/usrp1/usrp1_iface.hpp
index 3f608584a..34a2330b5 100644
--- a/host/lib/usrp/usrp1/usrp1_iface.hpp
+++ b/host/lib/usrp/usrp1/usrp1_iface.hpp
@@ -18,6 +18,7 @@
#ifndef INCLUDED_USRP1_IFACE_HPP
#define INCLUDED_USRP1_IFACE_HPP
+#include <uhd/usrp/mboard_eeprom.hpp>
#include <uhd/types/serial.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
@@ -81,6 +82,8 @@ public:
boost::uint16_t index,
unsigned char* buff,
boost::uint16_t length) = 0;
+
+ uhd::usrp::mboard_eeprom_t mb_eeprom;
};
#endif /* INCLUDED_USRP1_IFACE_HPP */
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 314384e72..6016b0979 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -56,12 +56,14 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
//return an empty list of addresses when type is set to non-usrp1
if (hint.has_key("type") and hint["type"] != "usrp1") return usrp1_addrs;
+ //Return an empty list of addresses when an address is specified,
+ //since an address is intended for a different, non-USB, device.
+ if (hint.has_key("addr")) return usrp1_addrs;
+
//extract the firmware path for the USRP1
std::string usrp1_fw_image;
try{
- usrp1_fw_image = find_image_path(
- hint.has_key("fw")? hint["fw"] : "usrp1_fw.ihx"
- );
+ usrp1_fw_image = find_image_path(hint.get("fw", "usrp1_fw.ihx"));
}
catch(...){
uhd::warning::post(
@@ -91,11 +93,16 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
pid = USRP1_PRODUCT_ID;
BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) {
+ usrp1_iface::sptr iface = usrp1_iface::make(usrp_ctrl::make(usb_control::make(handle)));
device_addr_t new_addr;
new_addr["type"] = "usrp1";
+ new_addr["name"] = iface->mb_eeprom["name"];
new_addr["serial"] = handle->get_serial();
- //this is a found usrp1 when a hint serial is not specified or it matches
- if (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]){
+ //this is a found usrp1 when the hint serial and name match or blank
+ if (
+ (not hint.has_key("name") or hint["name"] == new_addr["name"]) and
+ (not hint.has_key("serial") or hint["serial"] == new_addr["serial"])
+ ){
usrp1_addrs.push_back(new_addr);
}
}
@@ -110,7 +117,7 @@ static device::sptr usrp1_make(const device_addr_t &device_addr){
//extract the FPGA path for the USRP1
std::string usrp1_fpga_image = find_image_path(
- device_addr.has_key("fpga")? device_addr["fpga"] : "usrp1_fpga.rbf"
+ device_addr.get("fpga", "usrp1_fpga.rbf")
);
//std::cout << "USRP1 FPGA image: " << usrp1_fpga_image << std::endl;
diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp
index 1e1c9b7b8..232f3b32a 100644
--- a/host/lib/usrp/usrp2/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.cpp
@@ -20,6 +20,7 @@
#include "usrp2_regs.hpp" //spi slave constants
#include <uhd/utils/assert.hpp>
#include <boost/cstdint.hpp>
+#include <boost/lexical_cast.hpp>
#include <iostream>
using namespace uhd;
@@ -83,8 +84,8 @@ public:
}
void enable_mimo_clock_out(bool enb){
- //FIXME TODO put this revision read in a common place
- boost::uint8_t rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0);
+ boost::uint16_t rev = boost::lexical_cast<boost::uint16_t>(_iface->mb_eeprom["rev"]);
+ boost::uint8_t rev_hi = boost::uint8_t(rev >> 8);
//calculate the low and high dividers
size_t divider = size_t(this->get_master_clock_rate()/10e6);
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index e812e1221..4ff31ddfd 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -52,14 +52,6 @@ extern "C" {
#define USRP2_I2C_ADDR_TX_DB (USRP2_I2C_DEV_EEPROM | 0x4)
#define USRP2_I2C_ADDR_RX_DB (USRP2_I2C_DEV_EEPROM | 0x5)
-////////////////////////////////////////////////////////////////////////
-// EEPROM Layout
-////////////////////////////////////////////////////////////////////////
-#define USRP2_EE_MBOARD_REV_LSB 0x00 //1 byte
-#define USRP2_EE_MBOARD_REV_MSB 0x01 //1 byte
-#define USRP2_EE_MBOARD_MAC_ADDR 0x02 //6 bytes
-#define USRP2_EE_MBOARD_IP_ADDR 0x0C //uint32, big-endian
-
typedef enum{
USRP2_CTRL_ID_HUH_WHAT = ' ',
//USRP2_CTRL_ID_FOR_SURE, //TODO error condition enums
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index bbe9c273f..83b70bddc 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -236,6 +236,11 @@ size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{
return bpp/_rx_otw_type.get_sample_size();
}
+static void handle_overflow(std::vector<usrp2_mboard_impl::sptr> &mboards, size_t chan){
+ std::cerr << "O" << std::flush;
+ mboards.at(chan/mboards.size())->handle_overflow();
+}
+
size_t usrp2_impl::recv(
const std::vector<void *> &buffs, size_t num_samps,
rx_metadata_t &metadata, const io_type_t &io_type,
@@ -248,6 +253,7 @@ size_t usrp2_impl::recv(
io_type, _rx_otw_type, //input and output types to convert
_mboards.front()->get_master_clock_freq(), //master clock tick rate
uhd::transport::vrt::if_hdr_unpack_be,
- boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout)
+ boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout),
+ boost::bind(&handle_overflow, _mboards, _1)
);
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index a0e6adfad..df98ba275 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -22,11 +22,7 @@
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/algorithm.hpp>
-#include <uhd/types/mac_addr.hpp>
-#include <uhd/types/dict.hpp>
#include <boost/bind.hpp>
-#include <boost/assign/list_of.hpp>
-#include <boost/asio/ip/address_v4.hpp>
#include <iostream>
using namespace uhd;
@@ -41,15 +37,9 @@ usrp2_mboard_impl::usrp2_mboard_impl(
size_t recv_frame_size
):
_index(index),
- _recv_frame_size(recv_frame_size)
+ _recv_frame_size(recv_frame_size),
+ _iface(usrp2_iface::make(ctrl_transport))
{
- //make a new interface for usrp2 stuff
- _iface = usrp2_iface::make(ctrl_transport);
-
- //extract the mboard rev numbers
- _rev_lo = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, 1).at(0);
- _rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0);
-
//contruct the interfaces to mboard perifs
_clock_ctrl = usrp2_clock_ctrl::make(_iface);
_codec_ctrl = usrp2_codec_ctrl::make(_iface);
@@ -176,7 +166,15 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){
_iface->poke32(U2_REG_TIME64_SECS, boost::uint32_t(time_spec.get_full_secs()));
}
+void usrp2_mboard_impl::handle_overflow(void){
+ _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1);
+ if (_continuous_streaming){ //re-issue the stream command if already continuous
+ this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
+ }
+}
+
void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
+ _continuous_streaming = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
_iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word(
stream_cmd, _recv_frame_size
));
@@ -192,35 +190,14 @@ static const std::string dboard_name = "0";
void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
named_prop_t key = named_prop_t::extract(key_);
- //handle the other props
- if (key_.type() == typeid(std::string)){
- if (key.as<std::string>() == "mac-addr"){
- byte_vector_t bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, 6);
- val = mac_addr_t::from_bytes(bytes).to_string();
- return;
- }
-
- if (key.as<std::string>() == "ip-addr"){
- boost::asio::ip::address_v4::bytes_type bytes;
- std::copy(_iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, 4), bytes);
- val = boost::asio::ip::address_v4(bytes).to_string();
- return;
- }
- }
-
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
case MBOARD_PROP_NAME:
- val = str(boost::format("usrp2 mboard%d - rev %d:%d") % _index % _rev_hi % _rev_lo);
+ val = str(boost::format("usrp2 mboard%d - rev %s") % _index % _iface->mb_eeprom["rev"]);
return;
- case MBOARD_PROP_OTHERS:{
- prop_names_t others = boost::assign::list_of
- ("mac-addr")
- ("ip-addr")
- ;
- val = others;
- }
+ case MBOARD_PROP_OTHERS:
+ val = prop_names_t();
return;
case MBOARD_PROP_RX_DBOARD:
@@ -281,6 +258,10 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
val = _tx_subdev_spec;
return;
+ case MBOARD_PROP_EEPROM_MAP:
+ val = _iface->mb_eeprom;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -289,21 +270,6 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
* MBoard Set Properties
**********************************************************************/
void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
- //handle the other props
- if (key.type() == typeid(std::string)){
- if (key.as<std::string>() == "mac-addr"){
- byte_vector_t bytes = mac_addr_t::from_string(val.as<std::string>()).to_bytes();
- _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, bytes);
- return;
- }
-
- if (key.as<std::string>() == "ip-addr"){
- byte_vector_t bytes(4);
- std::copy(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_bytes(), bytes);
- _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, bytes);
- return;
- }
- }
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
@@ -347,6 +313,13 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
));
return;
+ case MBOARD_PROP_EEPROM_MAP:
+ // Step1: commit the map, writing only those values set.
+ // Step2: readback the entire eeprom map into the iface.
+ val.as<mboard_eeprom_t>().commit(*_iface, mboard_eeprom_t::MAP_NXXX);
+ _iface->mb_eeprom = mboard_eeprom_t(*_iface, mboard_eeprom_t::MAP_NXXX);
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 2d450bfc6..eb2685efa 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -28,6 +28,7 @@
#include <algorithm>
using namespace uhd;
+using namespace uhd::usrp;
using namespace uhd::transport;
/*!
@@ -58,6 +59,8 @@ public:
"The fpga build is not compatible with the host code build."
) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num));
}
+
+ mb_eeprom = mboard_eeprom_t(*this, mboard_eeprom_t::MAP_NXXX);
}
~usrp2_iface_impl(void){
diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp
index 12fd4730a..bf36cbf6e 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.hpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.hpp
@@ -20,6 +20,7 @@
#include <uhd/transport/udp_simple.hpp>
#include <uhd/types/serial.hpp>
+#include <uhd/usrp/mboard_eeprom.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/cstdint.hpp>
@@ -102,6 +103,9 @@ public:
size_t num_bits,
bool readback
) = 0;
+
+ //motherboard eeprom map structure
+ uhd::usrp::mboard_eeprom_t mb_eeprom;
};
#endif /* INCLUDED_USRP2_IFACE_HPP */
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index a680708ad..5f549c4fd 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -21,6 +21,7 @@
#include <uhd/usrp/device_props.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
+#include <uhd/utils/warning.hpp>
#include <uhd/utils/algorithm.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
@@ -61,7 +62,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue;
//create a new hint with this broadcast address
- device_addr_t new_hint;
+ device_addr_t new_hint = hint;
new_hint["addr"] = if_addrs.bcast;
//call discover with the new hint and append results
@@ -101,19 +102,37 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
while(true){
size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem), DISCOVERY_TIMEOUT_MS);
//std::cout << len << "\n";
- if (len > offsetof(usrp2_ctrl_data_t, data)){
- //handle the received data
- switch(ntohl(ctrl_data_in->id)){
- case USRP2_CTRL_ID_WAZZUP_DUDE:
- //make a boost asio ipv4 with the raw addr in host byte order
- boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr));
- device_addr_t new_addr;
- new_addr["type"] = "usrp2";
- new_addr["addr"] = ip_addr.to_string();
- usrp2_addrs.push_back(new_addr);
- //dont break here, it will exit the while loop
- //just continue on to the next loop iteration
+ if (len > offsetof(usrp2_ctrl_data_t, data) and ntohl(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE){
+ //make a boost asio ipv4 with the raw addr in host byte order
+ boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr));
+ device_addr_t new_addr;
+ new_addr["type"] = "usrp2";
+ new_addr["addr"] = ip_addr.to_string();
+ //Attempt to read the name from the EEPROM and perform filtering.
+ //This operation can throw due to COMPAT mismatch. That is OK.
+ //We will allow the device to be found and the COMPAT mismatch
+ //will be thrown as an exception in the factory function.
+ try{
+ mboard_eeprom_t mb_eeprom = usrp2_iface::make(
+ udp_simple::make_connected(new_addr["addr"], num2str(USRP2_UDP_CTRL_PORT))
+ )->mb_eeprom;
+ new_addr["name"] = mb_eeprom["name"];
+ new_addr["serial"] = mb_eeprom["serial"];
+ if (
+ (not hint.has_key("name") or hint["name"] == new_addr["name"]) and
+ (not hint.has_key("serial") or hint["serial"] == new_addr["serial"])
+ ){
+ usrp2_addrs.push_back(new_addr);
+ }
}
+ catch(const std::exception &e){
+ uhd::warning::post(
+ std::string("Ignoring discovered device\n")
+ + e.what()
+ );
+ }
+ //dont break here, it will exit the while loop
+ //just continue on to the next loop iteration
}
if (len == 0) break; //timeout
}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 558726a2b..71f52878c 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -32,7 +32,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <uhd/transport/vrt_if_packet.hpp>
-#include <uhd/transport/udp_simple.hpp> //mtu
+#include <uhd/transport/udp_simple.hpp>
#include <uhd/transport/udp_zero_copy.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <uhd/usrp/subdev_spec.hpp>
@@ -92,15 +92,12 @@ public:
return _clock_ctrl->get_master_clock_rate();
}
+ void handle_overflow(void);
+
private:
size_t _index;
- int _rev_hi, _rev_lo;
const size_t _recv_frame_size;
-
- //properties for this mboard
- void get(const wax::obj &, wax::obj &);
- void set(const wax::obj &, const wax::obj &);
- uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec;
+ bool _continuous_streaming;
//interfaces
usrp2_iface::sptr _iface;
@@ -108,6 +105,11 @@ private:
usrp2_codec_ctrl::sptr _codec_ctrl;
usrp2_serdes_ctrl::sptr _serdes_ctrl;
+ //properties for this mboard
+ void get(const wax::obj &, wax::obj &);
+ void set(const wax::obj &, const wax::obj &);
+ uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec;
+
//rx and tx dboard methods and objects
uhd::usrp::dboard_manager::sptr _dboard_manager;
uhd::usrp::dboard_iface::sptr _dboard_iface;
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index 280c8dfaa..a9148de6d 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -57,23 +57,19 @@ INSTALL(TARGETS
########################################################################
# Utilities that get installed into the share path
########################################################################
-ADD_EXECUTABLE(usrp2_addr_burner usrp2_addr_burner.cpp)
-TARGET_LINK_LIBRARIES(usrp2_addr_burner uhd)
-
ADD_EXECUTABLE(usrp_burn_db_eeprom usrp_burn_db_eeprom.cpp)
TARGET_LINK_LIBRARIES(usrp_burn_db_eeprom uhd)
+ADD_EXECUTABLE(usrp_burn_mb_eeprom usrp_burn_mb_eeprom.cpp)
+TARGET_LINK_LIBRARIES(usrp_burn_mb_eeprom uhd)
+
ADD_EXECUTABLE(usrp1_init_eeprom usrp1_init_eeprom.cpp)
TARGET_LINK_LIBRARIES(usrp1_init_eeprom uhd)
-ADD_EXECUTABLE(usrp1_serial_burner usrp1_serial_burner.cpp)
-TARGET_LINK_LIBRARIES(usrp1_serial_burner uhd)
-
INSTALL(TARGETS
- usrp2_addr_burner
usrp_burn_db_eeprom
+ usrp_burn_mb_eeprom
usrp1_init_eeprom
- usrp1_serial_burner
RUNTIME DESTINATION ${PKG_DATA_DIR}/utils
)
diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp
index 8947034d7..8cea52fa6 100644
--- a/host/utils/uhd_usrp_probe.cpp
+++ b/host/utils/uhd_usrp_probe.cpp
@@ -26,6 +26,7 @@
#include <uhd/usrp/dsp_props.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dboard_id.hpp>
+#include <uhd/usrp/mboard_eeprom.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
@@ -123,10 +124,9 @@ static std::string get_mboard_pp_string(wax::obj mboard){
std::stringstream ss;
ss << boost::format("Mboard: %s") % mboard[usrp::MBOARD_PROP_NAME].as<std::string>() << std::endl;
//ss << std::endl;
- BOOST_FOREACH(const std::string &other_name, mboard[usrp::MBOARD_PROP_OTHERS].as<prop_names_t>()){
- try{
- ss << boost::format("%s: %s") % other_name % mboard[other_name].as<std::string>() << std::endl;
- } catch(...){}
+ usrp::mboard_eeprom_t mb_eeprom = mboard[usrp::MBOARD_PROP_EEPROM_MAP].as<usrp::mboard_eeprom_t>();
+ BOOST_FOREACH(const std::string &key, mb_eeprom.keys()){
+ if (not mb_eeprom[key].empty()) ss << boost::format("%s: %s") % key % mb_eeprom[key] << std::endl;
}
BOOST_FOREACH(const std::string &dsp_name, mboard[usrp::MBOARD_PROP_RX_DSP_NAMES].as<prop_names_t>()){
ss << make_border(get_dsp_pp_string("RX", mboard[named_prop_t(usrp::MBOARD_PROP_RX_DSP, dsp_name)]));
diff --git a/host/utils/usrp1_serial_burner.cpp b/host/utils/usrp1_serial_burner.cpp
deleted file mode 100644
index bf7d3d3bb..000000000
--- a/host/utils/usrp1_serial_burner.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// 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/usrp/device_props.hpp>
-#include <boost/program_options.hpp>
-#include <boost/format.hpp>
-#include <iostream>
-
-namespace po = boost::program_options;
-
-int UHD_SAFE_MAIN(int argc, char *argv[]){
- po::options_description desc("Allowed options");
- desc.add_options()
- ("help", "help message")
- ("old", po::value<std::string>(), "old USRP serial number (optional)")
- ("new", po::value<std::string>(), "new USRP serial number")
- ;
-
- 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("USRP serial burner %s") % desc << std::endl;
- return ~0;
- }
-
- if(vm.count("new") == 0) {
- std::cout << "error: must input --new arg" << std::endl;
- return ~0;
- }
-
- //load the options into the address
- uhd::device_addr_t device_addr;
- device_addr["type"] = "usrp1";
- if(vm.count("old")) device_addr["serial"] = vm["old"].as<std::string>();
-
- //find and create a control transport to do the writing.
-
- uhd::device_addrs_t found_addrs = uhd::device::find(device_addr);
-
- if (found_addrs.size() == 0){
- std::cerr << "No USRP devices found" << std::endl;
- return ~0;
- }
-
- for (size_t i = 0; i < found_addrs.size(); i++){
- uhd::device::sptr dev = uhd::device::make(found_addrs[i]);
- wax::obj mb = (*dev)[uhd::usrp::DEVICE_PROP_MBOARD];
- std::cout << "Writing serial number..." << std::endl;
- mb[std::string("serial")] = vm["new"].as<std::string>();
- std::cout << "Reading back serial number: " << mb[std::string("serial")].as<std::string>() << std::endl;
- }
-
-
- std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl;
- return 0;
-}
diff --git a/host/utils/usrp2_addr_burner.cpp b/host/utils/usrp2_addr_burner.cpp
deleted file mode 100644
index f0e3434b7..000000000
--- a/host/utils/usrp2_addr_burner.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//
-// 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/usrp/device_props.hpp>
-#include <boost/program_options.hpp>
-#include <boost/format.hpp>
-#include <iostream>
-
-namespace po = boost::program_options;
-
-int UHD_SAFE_MAIN(int argc, char *argv[]){
- po::options_description desc("Allowed options");
- desc.add_options()
- ("help", "help message")
- ("addr", po::value<std::string>(), "resolvable network address")
- ("new-ip", po::value<std::string>(), "new ip address (optional)")
- ("new-mac", po::value<std::string>(), "new mac address (optional)")
- ;
-
- 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("USRP2 Address Burner %s") % desc << std::endl;
- return ~0;
- }
-
- //load the options into the address
- uhd::device_addr_t device_addr;
- device_addr["type"] = "usrp2";
- if (vm.count("addr")){
- device_addr["addr"] = vm["addr"].as<std::string>();
- }
- else{
- std::cerr << "Error: missing addr option" << std::endl;
- return ~0;
- }
-
- //create a usrp2 device
- uhd::device::sptr u2_dev = uhd::device::make(device_addr);
- //FIXME usees the default mboard for now (until the mimo link is supported)
- wax::obj u2_mb = (*u2_dev)[uhd::usrp::DEVICE_PROP_MBOARD];
- std::cout << std::endl;
-
- //fetch and print current settings
- std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl;
- std::string curr_ip = u2_mb[std::string("ip-addr")].as<std::string>();
- std::cout << boost::format(" Current IP Address: %s") % curr_ip << std::endl;
- std::string curr_mac = u2_mb[std::string("mac-addr")].as<std::string>();
- std::cout << boost::format(" Current MAC Address: %s") % curr_mac << std::endl;
- std::cout << " Done" << std::endl << std::endl;
-
- //try to set the new ip (if provided)
- if (vm.count("new-ip")){
- std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl;
- std::string new_ip = vm["new-ip"].as<std::string>();
- std::cout << boost::format(" New IP Address: %s") % new_ip << std::endl;
- u2_mb[std::string("ip-addr")] = new_ip;
- std::cout << " Done" << std::endl << std::endl;
- }
-
- //try to set the new mac (if provided)
- if (vm.count("new-mac")){
- std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl;
- std::string new_mac = vm["new-mac"].as<std::string>();
- std::cout << boost::format(" New MAC Address: %s") % new_mac << std::endl;
- u2_mb[std::string("mac-addr")] = new_mac;
- std::cout << " Done" << std::endl << std::endl;
- }
-
- std::cout << "Power-cycle the usrp2 for the changes to take effect." << std::endl;
- return 0;
-}
diff --git a/host/utils/usrp_burn_db_eeprom.cpp b/host/utils/usrp_burn_db_eeprom.cpp
index 64ecf75d6..9afd71a22 100644
--- a/host/utils/usrp_burn_db_eeprom.cpp
+++ b/host/utils/usrp_burn_db_eeprom.cpp
@@ -58,10 +58,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//print the help message
if (vm.count("help")){
- std::cout << boost::format("USRP Burn DB EEPROM %s") % desc << std::endl;
+ std::cout << boost::format("USRP Burn Daughterboard 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"
+ "Omit the ID argument to perform readback,\n"
+ "Or specify a new ID to burn into the EEPROM.\n"
) << std::endl;
return ~0;
}
diff --git a/host/utils/usrp_burn_mb_eeprom.cpp b/host/utils/usrp_burn_mb_eeprom.cpp
new file mode 100644
index 000000000..20e1b58b1
--- /dev/null
+++ b/host/utils/usrp_burn_mb_eeprom.cpp
@@ -0,0 +1,81 @@
+//
+// 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/usrp/device_props.hpp>
+#include <uhd/usrp/mboard_props.hpp>
+#include <uhd/usrp/mboard_eeprom.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+
+namespace po = boost::program_options;
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ std::string args, key, val;
+
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
+ ("key", po::value<std::string>(&key), "the indentifier for a value in EEPROM")
+ ("val", po::value<std::string>(&val), "the new value to set, 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") or not vm.count("key")){
+ std::cout << boost::format("USRP Burn Motherboard EEPROM %s") % desc << std::endl;
+ std::cout << boost::format(
+ "Omit the value argument to perform a readback,\n"
+ "Or specify a new value to burn into the EEPROM.\n"
+ ) << std::endl;
+ return ~0;
+ }
+
+ std::cout << "Creating USRP device from address: " + args << std::endl;
+ uhd::device::sptr dev = uhd::device::make(args);
+ //FIXME the default mboard for now (may be others)
+ wax::obj mboard = (*dev)[uhd::usrp::DEVICE_PROP_MBOARD];
+ std::cout << std::endl;
+
+ if (true /*always readback*/){
+ std::cout << "Fetching current settings from EEPROM..." << std::endl;
+ uhd::usrp::mboard_eeprom_t mb_eeprom = \
+ mboard[uhd::usrp::MBOARD_PROP_EEPROM_MAP].as<uhd::usrp::mboard_eeprom_t>();
+ if (not mb_eeprom.has_key(key)){
+ std::cerr << boost::format("Cannot find value for EEPROM[%s]") % key << std::endl;
+ return ~0;
+ }
+ std::cout << boost::format(" EEPROM [\"%s\"] is \"%s\"") % key % mb_eeprom[key] << std::endl;
+ std::cout << std::endl;
+ }
+ if (vm.count("val")){
+ uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[key] = val;
+ std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % key % val << std::endl;
+ mboard[uhd::usrp::MBOARD_PROP_EEPROM_MAP] = mb_eeprom;
+ std::cout << "Power-cycle the USRP device for the changes to take effect." << std::endl;
+ std::cout << std::endl;
+ }
+
+ std::cout << "Done" << std::endl;
+ return 0;
+}