diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-06-04 22:54:25 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:25 -0800 |
commit | 7fb8523c935cbcda7fd0dbcbad0ac8c2e6dd1fc7 (patch) | |
tree | 43bf48a0c4686c2607d1fbe0d799d9e376231112 | |
parent | 97b004131ad7cdd1daaac091bce1dcf6fd12ccaa (diff) | |
download | uhd-7fb8523c935cbcda7fd0dbcbad0ac8c2e6dd1fc7.tar.gz uhd-7fb8523c935cbcda7fd0dbcbad0ac8c2e6dd1fc7.tar.bz2 uhd-7fb8523c935cbcda7fd0dbcbad0ac8c2e6dd1fc7.zip |
lib: cores: Adapt spi_core_3000 for use with register_iface
Removes the requirement for a wb_iface, and also the requirement for
regs to be 4 addresses apart.
-rw-r--r-- | host/lib/include/uhdlib/usrp/cores/spi_core_3000.hpp | 13 | ||||
-rw-r--r-- | host/lib/usrp/cores/spi_core_3000.cpp | 129 |
2 files changed, 92 insertions, 50 deletions
diff --git a/host/lib/include/uhdlib/usrp/cores/spi_core_3000.hpp b/host/lib/include/uhdlib/usrp/cores/spi_core_3000.hpp index 81ea05a37..36486b5a1 100644 --- a/host/lib/include/uhdlib/usrp/cores/spi_core_3000.hpp +++ b/host/lib/include/uhdlib/usrp/cores/spi_core_3000.hpp @@ -13,17 +13,28 @@ #include <uhd/utils/noncopyable.hpp> #include <uhd/types/wb_iface.hpp> #include <boost/shared_ptr.hpp> +#include <memory> +#include <functional> class spi_core_3000 : uhd::noncopyable, public uhd::spi_iface { public: - typedef boost::shared_ptr<spi_core_3000> sptr; + using sptr = boost::shared_ptr<spi_core_3000>; + using poke32_fn_t = std::function<void(uint32_t, uint32_t)>; + using peek32_fn_t = std::function<uint32_t(uint32_t)>; virtual ~spi_core_3000(void) = 0; //! makes a new spi core from iface and slave base static sptr make(uhd::wb_iface::sptr iface, const size_t base, const size_t readback); + //! makes a new spi core from register iface and slave base + static sptr make(poke32_fn_t&& poke32_fn, + peek32_fn_t&& peek32_fn, + const size_t base, + const size_t reg_offset, + const size_t readback); + //! Set the spi clock divider to something usable virtual void set_divider(const double div) = 0; diff --git a/host/lib/usrp/cores/spi_core_3000.cpp b/host/lib/usrp/cores/spi_core_3000.cpp index f4b42f26d..ea476879b 100644 --- a/host/lib/usrp/cores/spi_core_3000.cpp +++ b/host/lib/usrp/cores/spi_core_3000.cpp @@ -1,82 +1,94 @@ // // Copyright 2013-2014 Ettus Research LLC // Copyright 2018 Ettus Research, a National Instruments Company +// Copyright 2019 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // #include <uhd/exception.hpp> -#include <uhd/utils/log.hpp> #include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <boost/thread/thread.hpp> //sleep +#include <boost/make_shared.hpp> +#include <chrono> +#include <mutex> +#include <thread> -#define SPI_DIV _base + 0 -#define SPI_CTRL _base + 4 -#define SPI_DATA _base + 8 -#define SPI_SHUTDOWN _base + 12 +namespace { +constexpr double DEFAULT_DIVIDER = 30.0; +} using namespace uhd; -spi_core_3000::~spi_core_3000(void){ +spi_core_3000::~spi_core_3000(void) +{ /* NOP */ } class spi_core_3000_impl : public spi_core_3000 { public: - spi_core_3000_impl(wb_iface::sptr iface, const size_t base, const size_t readback): - _iface(iface), _base(base), _readback(readback), _ctrl_word_cache(0), _divider_cache(0) + spi_core_3000_impl(poke32_fn_t&& poke32_fn, + peek32_fn_t&& peek32_fn, + const size_t base, + const size_t reg_offset, + const size_t readback) + : _poke32(std::move(poke32_fn)) + , _peek32(std::move(peek32_fn)) + , _spi_div_addr(base + 0 * reg_offset) + , _spi_ctrl_addr(base + 1 * reg_offset) + , _spi_data_addr(base + 2 * reg_offset) + , _spi_shutdown_addr(base + 3 * reg_offset) + , _readback_addr(readback) { - this->set_divider(30); + this->set_divider(DEFAULT_DIVIDER); } - uint32_t transact_spi( - int which_slave, - const spi_config_t &config, + uint32_t transact_spi(int which_slave, + const spi_config_t& config, uint32_t data, size_t num_bits, - bool readback - ){ - boost::lock_guard<boost::mutex> lock(_mutex); + bool readback) + { + std::lock_guard<std::mutex> lock(_mutex); - //load SPI divider + // load SPI divider size_t spi_divider = _div; if (config.use_custom_divider) { - //The resulting SPI frequency will be f_system/(2*(divider+1)) - //This math ensures the frequency will be equal to or less than the target - spi_divider = (config.divider-1)/2; + // The resulting SPI frequency will be f_system/(2*(divider+1)) + // This math ensures the frequency will be equal to or less than the target + spi_divider = (config.divider - 1) / 2; } - //conditionally send SPI divider + // conditionally send SPI divider if (spi_divider != _divider_cache) { - _iface->poke32(SPI_DIV, spi_divider); + _poke32(_spi_div_addr, spi_divider); _divider_cache = spi_divider; } - //load control word + // load control word uint32_t ctrl_word = 0; ctrl_word |= ((which_slave & 0xffffff) << 0); ctrl_word |= ((num_bits & 0x3f) << 24); - if (config.mosi_edge == spi_config_t::EDGE_FALL) ctrl_word |= (1 << 31); - if (config.miso_edge == spi_config_t::EDGE_RISE) ctrl_word |= (1 << 30); - - //conditionally send control word - if (_ctrl_word_cache != ctrl_word) - { - _iface->poke32(SPI_CTRL, ctrl_word); + if (config.mosi_edge == spi_config_t::EDGE_FALL) + ctrl_word |= (1 << 31); + if (config.miso_edge == spi_config_t::EDGE_RISE) + ctrl_word |= (1 << 30); + + // conditionally send control word + if (_ctrl_word_cache != ctrl_word) { + _poke32(_spi_ctrl_addr, ctrl_word); _ctrl_word_cache = ctrl_word; } - //load data word (must be in upper bits) + // load data word (must be in upper bits) const uint32_t data_out = data << (32 - num_bits); - //send data word - _iface->poke32(SPI_DATA, data_out); + // send data word + _poke32(_spi_data_addr, data_out); - //conditional readback - if (readback) - { - return _iface->peek32(_readback); + // conditional readback + if (readback) { + return _peek32(_readback_addr); } return 0; @@ -85,33 +97,52 @@ public: void set_shutdown(const bool shutdown) { _shutdown_cache = shutdown; - _iface->poke32(SPI_SHUTDOWN, _shutdown_cache); + _poke32(_spi_shutdown_addr, _shutdown_cache); } bool get_shutdown() { - return(_shutdown_cache); + return _shutdown_cache; } void set_divider(const double div) { - _div = size_t((div/2) - 0.5); + _div = size_t((div / 2) - 0.5); } private: - - wb_iface::sptr _iface; - const size_t _base; - const size_t _readback; - uint32_t _ctrl_word_cache; + poke32_fn_t _poke32; + peek32_fn_t _peek32; + const size_t _spi_div_addr; + const size_t _spi_ctrl_addr; + const size_t _spi_data_addr; + const size_t _spi_shutdown_addr; + const size_t _readback_addr; + uint32_t _ctrl_word_cache = 0; bool _shutdown_cache; - boost::mutex _mutex; + std::mutex _mutex; size_t _div; - size_t _divider_cache; + size_t _divider_cache = 0; }; -spi_core_3000::sptr spi_core_3000::make(wb_iface::sptr iface, const size_t base, const size_t readback) +spi_core_3000::sptr spi_core_3000::make( + wb_iface::sptr iface, const size_t base, const size_t readback) { - return sptr(new spi_core_3000_impl(iface, base, readback)); + return boost::make_shared<spi_core_3000_impl>( + [iface]( + const uint32_t addr, const uint32_t value) { iface->poke32(addr, value); }, + [iface](const uint32_t addr) { return iface->peek32(addr); }, + base, + 4, + readback); } +spi_core_3000::sptr spi_core_3000::make(spi_core_3000::poke32_fn_t&& poke32_fn, + spi_core_3000::peek32_fn_t&& peek32_fn, + const size_t base, + const size_t reg_offset, + const size_t readback) +{ + return boost::make_shared<spi_core_3000_impl>( + std::move(poke32_fn), std::move(peek32_fn), base, reg_offset, readback); +} |