diff options
-rw-r--r-- | host/docs/usrp_e1xx.rst | 15 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/clock_ctrl.cpp | 21 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/fpga_downloader.cpp | 12 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_iface.cpp | 141 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_iface.hpp | 14 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 64 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.hpp | 22 | ||||
-rw-r--r-- | host/usrp_e_utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/usrp_e_utils/clkgen_config.hpp | 305 | ||||
-rw-r--r-- | host/usrp_e_utils/usrp-e-utility.cpp | 72 |
10 files changed, 196 insertions, 471 deletions
diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst index fcaa57716..4ac9d133a 100644 --- a/host/docs/usrp_e1xx.rst +++ b/host/docs/usrp_e1xx.rst @@ -53,21 +53,6 @@ Example: uhd_usrp_probe --args="master_clock_rate=52e6" -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Clock rate recovery - unbricking -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It is possible to set a clock rate such that the UHD can no longer communicate with the FPGA. -When this occurs, it is necessary to use the usrp-e-utility to recover the clock generator. -The recovery utility works by loading a special pass-through FPGA image so the computer -can talk directly to the clock generator over a SPI interface. - -Run the following commands to restore the clock generator to a usable state: -:: - - cd <install-path>/share/uhd/usrp_e_utilities - ./usrp-e-utility --fpga=../images/usrp_e100_pt_fpga.bin --reclk - - ------------------------------------------------------------------------ Clock Synchronization ------------------------------------------------------------------------ diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index f1b29840a..742959ae3 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -172,6 +172,12 @@ public: _chan_rate = 0.0; _out_rate = 0.0; + //perform soft-reset + _ad9522_regs.soft_reset = 1; + this->send_reg(0x000); + this->latch_regs(); + _ad9522_regs.soft_reset = 0; + //init the clock gen registers //Note: out0 should already be clocking the FPGA or this isnt going to work _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; @@ -437,8 +443,6 @@ private: } void calibrate_now(void){ - set_ignore_sync_fpga_plus_codec(false); //want vco cal to sync - //vco calibration routine: _ad9522_regs.vco_calibration_now = 0; this->send_reg(0x18); @@ -467,20 +471,9 @@ private: _ad9522_regs.get_read_reg(addr), 24 ); _ad9522_regs.set_reg(addr, reg); - if (_ad9522_regs.digital_lock_detect) goto finalize; + if (_ad9522_regs.digital_lock_detect) return; } UHD_MSG(error) << "USRP-E100 clock control: lock detection timeout" << std::endl; - finalize: - - set_ignore_sync_fpga_plus_codec(true); //never loose sync between these two - } - - void set_ignore_sync_fpga_plus_codec(bool enb){ - _ad9522_regs.divider0_ignore_sync = (enb)?1:0; // master FPGA clock ignores sync (always on, cannot be disabled by sync pulse) - _ad9522_regs.divider1_ignore_sync = (enb)?1:0; // codec clock ignores sync (always on, cannot be disabled by sync pulse) - this->send_reg(0x191); - this->send_reg(0x194); - this->latch_regs(); } void soft_sync(void){ diff --git a/host/lib/usrp/usrp_e100/fpga_downloader.cpp b/host/lib/usrp/usrp_e100/fpga_downloader.cpp index a7449d3b1..b8420796f 100644 --- a/host/lib/usrp/usrp_e100/fpga_downloader.cpp +++ b/host/lib/usrp/usrp_e100/fpga_downloader.cpp @@ -254,9 +254,9 @@ void usrp_e100_load_fpga(const std::string &bin_file){ UHD_MSG(status) << "Loading FPGA image: " << bin_file << "... " << std::flush; - if(std::system("/sbin/rmmod usrp_e") != 0){ - UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not unload usrp_e module" << std::endl; - } +// if(std::system("/sbin/rmmod usrp_e") != 0){ +// UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not unload usrp_e module" << std::endl; +// } prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); @@ -264,9 +264,9 @@ void usrp_e100_load_fpga(const std::string &bin_file){ send_file_to_fpga(bin_file, gpio_init_b, gpio_done); - if(std::system("/sbin/modprobe usrp_e") != 0){ - UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not load usrp_e module" << std::endl; - } +// if(std::system("/sbin/modprobe usrp_e") != 0){ +// UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not load usrp_e module" << std::endl; +// } } diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp index 55446da63..93c8cc7b5 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp @@ -18,14 +18,17 @@ #include "usrp_e100_iface.hpp" #include "usrp_e100_regs.hpp" #include <uhd/exception.hpp> +#include <uhd/utils/msg.hpp> #include <sys/ioctl.h> //ioctl #include <fcntl.h> //open, close #include <linux/usrp_e.h> //ioctl structures and constants +#include <boost/thread/thread.hpp> //sleep #include <boost/format.hpp> #include <boost/thread/mutex.hpp> #include <linux/i2c-dev.h> #include <linux/i2c.h> -#include <stdexcept> +#include <iostream> +#include <fstream> using namespace uhd; using namespace uhd::usrp; @@ -98,12 +101,9 @@ public: return _node_fd; } - /******************************************************************* - * Structors - ******************************************************************/ - usrp_e100_iface_impl(const std::string &node): - _i2c_dev_iface(i2c_dev_iface("/dev/i2c-3")) - { + void open(const std::string &node){ + UHD_MSG(status) << "Opening device node " << node << "..." << std::endl; + //open the device node and check file descriptor if ((_node_fd = ::open(node.c_str(), O_RDWR)) < 0){ throw uhd::io_error("Failed to open " + node); @@ -112,18 +112,30 @@ public: //check the module compatibility number int module_compat_num = ::ioctl(_node_fd, USRP_E_GET_COMPAT_NUMBER, NULL); if (module_compat_num != USRP_E_COMPAT_NUMBER){ - throw uhd::runtime_error(str(boost::format( - "Expected module compatibility number 0x%x, but got 0x%x:\n" - "The module build is not compatible with the host code build." - ) % USRP_E_COMPAT_NUMBER % module_compat_num)); + throw uhd::runtime_error(str(boost::format( + "Expected module compatibility number 0x%x, but got 0x%x:\n" + "The module build is not compatible with the host code build." + ) % USRP_E_COMPAT_NUMBER % module_compat_num)); + } + } + + void close(void){ + ::close(_node_fd); + _node_fd = -1; } + /******************************************************************* + * Structors + ******************************************************************/ + usrp_e100_iface_impl(void): + _node_fd(-1), + _i2c_dev_iface(i2c_dev_iface("/dev/i2c-3")) + { mb_eeprom = mboard_eeprom_t(get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100); } ~usrp_e100_iface_impl(void){ - //close the device node file descriptor - ::close(_node_fd); + if (_node_fd >= 0) this->close(); } /******************************************************************* @@ -245,6 +257,10 @@ public: size_t num_bits, bool readback ){ + if (which_slave == UE_SPI_SS_AD9522) return bitbang_spi( + bits, num_bits, readback + ); + //load data struct usrp_e_spi data; data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; @@ -263,11 +279,101 @@ public: //unload the data return data.data; } - + + boost::uint32_t bitbang_spi( + boost::uint32_t bits, + size_t num_bits, + bool readback + ){ + boost::uint32_t rb_bits = 0; + + _spi_bitbanger.spi_sen_gpio_write(0); + + for (size_t i = 0; i < num_bits; i++){ + _spi_bitbanger.spi_sclk_gpio_write(0); + _spi_bitbanger.spi_mosi_gpio_write((bits >> (num_bits-i-1)) & 0x1); + boost::this_thread::sleep(boost::posix_time::microseconds(10)); + if (readback) rb_bits = (rb_bits << 1) | _spi_bitbanger.spi_miso_gpio_read(); + _spi_bitbanger.spi_sclk_gpio_write(1); + boost::this_thread::sleep(boost::posix_time::microseconds(10)); + } + + _spi_bitbanger.spi_sen_gpio_write(1); + boost::this_thread::sleep(boost::posix_time::microseconds(100)); + + return rb_bits; + } + + class bitbang_spi_guts{ + public: + bitbang_spi_guts(void){ + //setup gpio pin directions + this->set_gpio_direction(spi_sclk_gpio, "out"); + this->set_gpio_direction(spi_sen_gpio, "out"); + this->set_gpio_direction(spi_mosi_gpio, "out"); + this->set_gpio_direction(spi_miso_gpio, "in"); + + //open the gpio pin values + _spi_sclk_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_sclk_gpio).c_str()); + _spi_sen_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_sen_gpio).c_str()); + _spi_mosi_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_mosi_gpio).c_str()); + _spi_miso_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_miso_gpio).c_str()); + } + + ~bitbang_spi_guts(void){ + this->set_gpio_direction(spi_sclk_gpio, "in"); + this->set_gpio_direction(spi_sen_gpio, "in"); + this->set_gpio_direction(spi_mosi_gpio, "in"); + } + + void spi_sclk_gpio_write(int val){ + _spi_sclk_gpio_value << val << std::endl << std::flush; + } + + void spi_sen_gpio_write(int val){ + _spi_sen_gpio_value << val << std::endl << std::flush; + } + + void spi_mosi_gpio_write(int val){ + _spi_mosi_gpio_value << val << std::endl << std::flush; + } + + int spi_miso_gpio_read(void){ + std::string val; + std::getline(_spi_miso_gpio_value, val); + _spi_miso_gpio_value.seekg(0); + return int(val.at(0) - '0') & 0x1; + } + + private: + enum{ + spi_sclk_gpio = 65, + spi_sen_gpio = 186, + spi_mosi_gpio = 145, + spi_miso_gpio = 147, + }; + + void set_gpio_direction(int gpio_num, const std::string &dir){ + std::ofstream export_file("/sys/class/gpio/export"); + export_file << gpio_num << std::endl << std::flush; + export_file.close(); + + std::ofstream dir_file(str(boost::format("/sys/class/gpio/gpio%d/direction") % gpio_num).c_str()); + dir_file << dir << std::endl << std::flush; + dir_file.close(); + } + + std::ofstream _spi_sclk_gpio_value, _spi_sen_gpio_value, _spi_mosi_gpio_value; + std::ifstream _spi_miso_gpio_value; + }; + + /******************************************************************* + * UART + ******************************************************************/ void write_uart(boost::uint8_t, const std::string &) { throw uhd::not_implemented_error("Unhandled command write_uart()"); } - + std::string read_uart(boost::uint8_t) { throw uhd::not_implemented_error("Unhandled command read_uart()"); } @@ -276,11 +382,12 @@ private: int _node_fd; i2c_dev_iface _i2c_dev_iface; boost::mutex _ctrl_mutex; + bitbang_spi_guts _spi_bitbanger; }; /*********************************************************************** * Public Make Function **********************************************************************/ -usrp_e100_iface::sptr usrp_e100_iface::make(const std::string &node){ - return sptr(new usrp_e100_iface_impl(node)); +usrp_e100_iface::sptr usrp_e100_iface::make(void){ + return sptr(new usrp_e100_iface_impl()); } diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp index d9fe96db7..7df99cf4e 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp @@ -46,10 +46,9 @@ public: /*! * Make a new usrp-e interface with the control transport. - * \param node the device node name * \return a new usrp-e interface object */ - static sptr make(const std::string &node); + static sptr make(void); /*! * Get the underlying file descriptor. @@ -58,6 +57,17 @@ public: virtual int get_file_descriptor(void) = 0; /*! + * Open a device node into this iface. + * \param node the device node name + */ + virtual void open(const std::string &node) = 0; + + /*! + * Close the open device node in this iface. + */ + virtual void close(void) = 0; + + /*! * Perform an ioctl call on the device node file descriptor. * This will throw when the internal ioctl call fails. * \param request the control word diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 5b039aafc..36db810a8 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -54,7 +54,7 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){ new_addr["type"] = "usrp-e"; new_addr["node"] = fs::system_complete(fs::path(hint["node"])).string(); try{ - usrp_e100_iface::sptr iface = usrp_e100_iface::make(new_addr["node"]); + usrp_e100_iface::sptr iface = usrp_e100_iface::make(); new_addr["name"] = iface->mb_eeprom["name"]; new_addr["serial"] = iface->mb_eeprom["serial"]; } @@ -88,39 +88,43 @@ static size_t hash_fpga_file(const std::string &file_path){ static device::sptr usrp_e100_make(const device_addr_t &device_addr){ //setup the main interface into fpga - std::string node = device_addr["node"]; - UHD_MSG(status) << boost::format("Opening USRP-E on %s") % node << std::endl; - usrp_e100_iface::sptr iface = usrp_e100_iface::make(node); + const std::string node = device_addr["node"]; + usrp_e100_iface::sptr iface = usrp_e100_iface::make(); + iface->open(node); - //extract the fpga path for usrp-e - std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", "usrp_e100_fpga.bin")); + //setup clock control here to ensure that the FPGA has a good clock before we continue + const double master_clock_rate = device_addr.cast<double>("master_clock_rate", USRP_E_DEFAULT_CLOCK_RATE); + usrp_e100_clock_ctrl::sptr clock_ctrl = usrp_e100_clock_ctrl::make(iface, master_clock_rate); - //compute a hash of the fpga file + //extract the fpga path for usrp-e and compute hash + const std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", USRP_E_FPGA_FILE_NAME)); const boost::uint32_t file_hash = boost::uint32_t(hash_fpga_file(usrp_e100_fpga_image)); //When the hash does not match: - // - unload the iface to free the node - // - load the fpga configuration file - // - re-open the iface on the node + // - close the device node + // - load the fpga bin file + // - re-open the device node if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){ - iface.reset(); + iface->close(); usrp_e100_load_fpga(usrp_e100_fpga_image); - sleep(1); ///\todo do this better one day. - UHD_MSG(status) << boost::format("re-Opening USRP-E on %s") % node << std::endl; - iface = usrp_e100_iface::make(node); + iface->open(node); } - //store the hash into the FPGA register - iface->poke32(UE_REG_SR_MISC_TEST32, file_hash); - - //check that the hash can be readback correctly - if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){ - UHD_MSG(error) << boost::format( - "The FPGA hash readback failed!\n" - "The FPGA is either clocked improperly\n" - "or the FPGA build is not compatible.\n" - ); + //Perform wishbone readback tests, these tests also write the hash + bool test_fail = false; + UHD_MSG(status) << "Performing wishbone readback test... " << std::flush; + for (size_t i = 0; i < 100; i++){ + iface->poke32(UE_REG_SR_MISC_TEST32, file_hash); + test_fail = iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash; + if (test_fail) break; //exit loop on any failure } + UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl; + + if (test_fail) UHD_MSG(error) << boost::format( + "The FPGA is either clocked improperly\n" + "or the FPGA build is not compatible.\n" + "Subsequent errors may follow...\n" + ); //check that the compatibility is correct const boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); @@ -133,7 +137,7 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){ ) % USRP_E_FPGA_COMPAT_NUM % fpga_compat_num)); } - return device::sptr(new usrp_e100_impl(iface, device_addr)); + return device::sptr(new usrp_e100_impl(device_addr, iface, clock_ctrl)); } UHD_STATIC_BLOCK(register_usrp_e100_device){ @@ -144,20 +148,18 @@ UHD_STATIC_BLOCK(register_usrp_e100_device){ * Structors **********************************************************************/ usrp_e100_impl::usrp_e100_impl( + const uhd::device_addr_t &device_addr, usrp_e100_iface::sptr iface, - const device_addr_t &device_addr + usrp_e100_clock_ctrl::sptr clock_ctrl ): _iface(iface), + _clock_ctrl(clock_ctrl), + _codec_ctrl(usrp_e100_codec_ctrl::make(_iface)), _data_xport(usrp_e100_make_mmap_zero_copy(_iface)), _recv_frame_size(std::min(_data_xport->get_recv_frame_size(), size_t(device_addr.cast<double>("recv_frame_size", 1e9)))), _send_frame_size(std::min(_data_xport->get_send_frame_size(), size_t(device_addr.cast<double>("send_frame_size", 1e9)))) { - //setup interfaces into hardware - const double master_clock_rate = device_addr.cast<double>("master_clock_rate", 64e6); - _clock_ctrl = usrp_e100_clock_ctrl::make(_iface, master_clock_rate); - _codec_ctrl = usrp_e100_codec_ctrl::make(_iface); - //initialize the mboard mboard_init(); diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp index 1c17863fb..0c6087a85 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp @@ -33,7 +33,9 @@ uhd::transport::zero_copy_if::sptr usrp_e100_make_mmap_zero_copy(usrp_e100_iface::sptr iface); -static const boost::uint16_t USRP_E_FPGA_COMPAT_NUM = 0x04; +static const std::string USRP_E_FPGA_FILE_NAME = "usrp_e100_fpga5.bin"; +static const boost::uint16_t USRP_E_FPGA_COMPAT_NUM = 0x05; +static const double USRP_E_DEFAULT_CLOCK_RATE = 64e6; //! load an fpga image from a bin file into the usrp-e fpga extern void usrp_e100_load_fpga(const std::string &bin_file); @@ -82,7 +84,11 @@ private: class usrp_e100_impl : public uhd::device{ public: //structors - usrp_e100_impl(usrp_e100_iface::sptr, const uhd::device_addr_t &); + usrp_e100_impl( + const uhd::device_addr_t &, + usrp_e100_iface::sptr, + usrp_e100_clock_ctrl::sptr + ); ~usrp_e100_impl(void); //the io interface @@ -96,6 +102,12 @@ private: //interface to ioctls and file descriptor usrp_e100_iface::sptr _iface; + //ad9522 clock control + usrp_e100_clock_ctrl::sptr _clock_ctrl; + + //ad9862 codec control + usrp_e100_codec_ctrl::sptr _codec_ctrl; + //handle io stuff uhd::transport::zero_copy_if::sptr _data_xport; UHD_PIMPL_DECL(io_impl) _io_impl; @@ -109,12 +121,6 @@ private: //configuration shadows uhd::clock_config_t _clock_config; - //ad9522 clock control - usrp_e100_clock_ctrl::sptr _clock_ctrl; - - //ad9862 codec control - usrp_e100_codec_ctrl::sptr _codec_ctrl; - //device functions and settings void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); diff --git a/host/usrp_e_utils/CMakeLists.txt b/host/usrp_e_utils/CMakeLists.txt index e7d6ae4b8..5f244a216 100644 --- a/host/usrp_e_utils/CMakeLists.txt +++ b/host/usrp_e_utils/CMakeLists.txt @@ -28,7 +28,6 @@ IF(ENABLE_USRP_E_UTILS) INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/lib/ic_reg_maps) SET(usrp_e_utils_sources - usrp-e-utility.cpp usrp-e-loopback.c usrp-e-timed.c usrp-e-wb-test.cpp diff --git a/host/usrp_e_utils/clkgen_config.hpp b/host/usrp_e_utils/clkgen_config.hpp deleted file mode 100644 index f39f8bb19..000000000 --- a/host/usrp_e_utils/clkgen_config.hpp +++ /dev/null @@ -1,305 +0,0 @@ -// -// Copyright 2011 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 USRP_E_UTILS_CLKGEN_CONFIG_HPP -#define USRP_E_UTILS_CLKGEN_CONFIG_HPP - -#include <iostream> -#include <sstream> -#include <fstream> -#include <string> -#include <cstdlib> - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <linux/spi/spidev.h> - -namespace usrp_e_clkgen_config_utility{ - -// Programming data for clock gen chip -static const unsigned int config_data[] = { - 0x000024, - 0x023201, - 0x000081, - 0x000400, - 0x00104c, - 0x001101, - 0x001200, - 0x001300, - 0x001414, - 0x001500, - 0x001604, - 0x001704, - 0x001807, - 0x001900, - //0x001a00,//for debug - 0x001a32, - 0x001b12, - 0x001c44, - 0x001d00, - 0x001e00, - 0x00f062, - 0x00f162, - 0x00f262, - 0x00f362, - 0x00f462, - 0x00f562, - 0x00f662, - 0x00f762, - 0x00f862, - 0x00f962, - 0x00fa62, - 0x00fb62, - 0x00fc00, - 0x00fd00, - 0x019021, - 0x019100, - 0x019200, - 0x019321, - 0x019400, - 0x019500, - 0x019611, - 0x019700, - 0x019800, - 0x019900, - 0x019a00, - 0x019b00, - 0x01e003, - 0x01e102, - 0x023000, - 0x023201, - 0x0b0201, - 0x0b0300, - 0x001fff, - 0x0a0000, - 0x0a0100, - 0x0a0200, - 0x0a0302, - 0x0a0400, - 0x0a0504, - 0x0a060e, - 0x0a0700, - 0x0a0810, - 0x0a090e, - 0x0a0a00, - 0x0a0bf0, - 0x0a0c0b, - 0x0a0d01, - 0x0a0e90, - 0x0a0f01, - 0x0a1001, - 0x0a11e0, - 0x0a1201, - 0x0a1302, - 0x0a1430, - 0x0a1580, - 0x0a16ff, - 0x023201, - 0x0b0301, - 0x023201, -}; - - -const unsigned int CLKGEN_SELECT = 145; - - -enum gpio_direction {IN, OUT}; - -class gpio { - public: - - gpio(unsigned int gpio_num, gpio_direction pin_direction, bool close_action); - ~gpio(); - - bool get_value(); - void set_value(bool state); - - private: - - unsigned int gpio_num; - - std::stringstream base_path; - std::fstream value_file; - std::fstream direction_file; - bool close_action; // True set to input and release, false do nothing -}; - -class spidev { - public: - - spidev(std::string dev_name); - ~spidev(); - - void send(char *wbuf, char *rbuf, unsigned int nbytes); - - private: - - int fd; - -}; - -gpio::gpio(unsigned int _gpio_num, gpio_direction pin_direction, bool close_action) -:close_action(close_action) -{ - std::fstream export_file; - - gpio_num = _gpio_num; - - export_file.open("/sys/class/gpio/export", std::ios::out); - if (!export_file.is_open()) ///\todo Poor error handling - std::cout << "Failed to open gpio export file." << std::endl; - - export_file << gpio_num << std::endl; - - base_path << "/sys/class/gpio/gpio" << gpio_num << std::flush; - - std::string direction_file_name; - - direction_file_name = base_path.str() + "/direction"; - - direction_file.open(direction_file_name.c_str()); - if (!direction_file.is_open()) - std::cout << "Failed to open direction file." << std::endl; - if (pin_direction == OUT) - direction_file << "out" << std::endl; - else - direction_file << "in" << std::endl; - - std::string value_file_name; - - value_file_name = base_path.str() + "/value"; - - value_file.open(value_file_name.c_str(), std::ios_base::in | std::ios_base::out); - if (!value_file.is_open()) - std::cout << "Failed to open value file." << std::endl; -} - -bool gpio::get_value() -{ - - std::string val; - - std::getline(value_file, val); - value_file.seekg(0); - - if (val == "0") - return false; - else if (val == "1") - return true; - else - std::cout << "Data read from value file|" << val << "|" << std::endl; - - return false; -} - -void gpio::set_value(bool state) -{ - - if (state) - value_file << "1" << std::endl; - else - value_file << "0" << std::endl; -} - -gpio::~gpio() -{ - if (close_action) { - std::fstream unexport_file; - - direction_file << "in" << std::endl; - - unexport_file.open("/sys/class/gpio/unexport", std::ios::out); - if (!unexport_file.is_open()) ///\todo Poor error handling - std::cout << "Failed to open gpio export file." << std::endl; - - unexport_file << gpio_num << std::endl; - - } - -} - -spidev::spidev(std::string fname) -{ - int ret; - int mode = 0; - int speed = 12000; - int bits = 24; - - fd = open(fname.c_str(), O_RDWR); - - ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); - ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); - ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); -} - - -spidev::~spidev() -{ - close(fd); -} - -void spidev::send(char *buf, char *rbuf, unsigned int nbytes) -{ - int ret; - - struct spi_ioc_transfer tr; - tr.tx_buf = (unsigned long) buf; - tr.rx_buf = (unsigned long) rbuf; - tr.len = nbytes; - tr.delay_usecs = 0; - tr.speed_hz = 12000; - tr.bits_per_word = 24; - - ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); - -} - -static void send_config_to_clkgen(gpio &chip_select, const unsigned int data[], unsigned int data_size) -{ - spidev spi("/dev/spidev1.0"); - unsigned int rbuf; - - for (unsigned int i = 0; i < data_size; i++) { - - //std::cout << "sending " << std::hex << data[i] << std::endl; - chip_select.set_value(0); - spi.send((char *)&data[i], (char *)&rbuf, 4); - chip_select.set_value(1); - unsigned int addr = (data[i] >> 8) & 0xfff; - if (addr == 0x232 || addr == 0x000){ - std::cout << "." << std::flush; - sleep(1); - } - }; - std::cout << std::endl; -} - -}//namespace usrp_e_clkgen_config_utility - -//int main(int argc, char *argv[]) -static void clock_genconfig_main(void) -{ - using namespace usrp_e_clkgen_config_utility; - gpio clkgen_select(CLKGEN_SELECT, OUT, true); - - send_config_to_clkgen(clkgen_select, config_data, sizeof(config_data)/sizeof(config_data[0])); -} - -#endif /*USRP_E_UTILS_CLKGEN_CONFIG_HPP*/ diff --git a/host/usrp_e_utils/usrp-e-utility.cpp b/host/usrp_e_utils/usrp-e-utility.cpp deleted file mode 100644 index 47a2c0900..000000000 --- a/host/usrp_e_utils/usrp-e-utility.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright 2011 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 <boost/program_options.hpp> -#include <boost/format.hpp> -#include <stdexcept> -#include <iostream> - -#include "fpga_downloader.cpp" -#include "clkgen_config.hpp" - -namespace po = boost::program_options; - -int UHD_SAFE_MAIN(int argc, char *argv[]){ - - //variables to be set by po - std::string fpga_path; - - //setup the program options - po::options_description desc("Allowed options"); - desc.add_options() - ("help", "help message") - ("fpga", po::value<std::string>(&fpga_path), "loads the specified FPGA file") - ("reclk", "runs the clock recovery") - ; - 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 USRP-E Utility %s") % desc << std::endl; - return ~0; - } - - bool loaded_fpga_image = false; - if (vm.count("fpga") != 0){ - std::cout << "USRP-E Utility loading the FPGA..." << std::endl << std::endl; - usrp_e100_load_fpga(fpga_path); - loaded_fpga_image = true; - sleep(1); - } - - if (vm.count("reclk") != 0){ - std::cout << "USRP-E Utility running the clock recovery..." << std::flush; - //if an image was not loaded or specified, we load pass-through - if (fpga_path.empty()) throw std::runtime_error( - "Please specify the path to the pass-though FPGA image for your device.\n" - " usrp-e-utility --reclk --fpga=/usr/share/uhd/images/usrp_e1xx_pt_fpga.bin" - ); - clock_genconfig_main(); - } - - std::cout << "Done!" << std::endl; - - return 0; -} |