aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-06-04 22:54:25 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:25 -0800
commit7fb8523c935cbcda7fd0dbcbad0ac8c2e6dd1fc7 (patch)
tree43bf48a0c4686c2607d1fbe0d799d9e376231112
parent97b004131ad7cdd1daaac091bce1dcf6fd12ccaa (diff)
downloaduhd-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.hpp13
-rw-r--r--host/lib/usrp/cores/spi_core_3000.cpp129
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);
+}