diff options
author | Martin Braun <martin.braun@ettus.com> | 2017-04-25 17:00:34 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:03:52 -0800 |
commit | 151ba5fb06dfdb6fcc46ccfdabf5f1e064236981 (patch) | |
tree | fa941b0589b09a22957e8b7e3966679748a9b202 /mpm/lib/spi/spidev_iface.cpp | |
parent | 1262dfb3ccf5a9916685b3399587593174c6583e (diff) | |
download | uhd-151ba5fb06dfdb6fcc46ccfdabf5f1e064236981.tar.gz uhd-151ba5fb06dfdb6fcc46ccfdabf5f1e064236981.tar.bz2 uhd-151ba5fb06dfdb6fcc46ccfdabf5f1e064236981.zip |
mpm: Major refactoring
- Created clean interfaces for SPI and registers
- Severed most links to UHD
- Added a lockable class which allows exposing mutexes into Python
Diffstat (limited to 'mpm/lib/spi/spidev_iface.cpp')
-rw-r--r-- | mpm/lib/spi/spidev_iface.cpp | 153 |
1 files changed, 45 insertions, 108 deletions
diff --git a/mpm/lib/spi/spidev_iface.cpp b/mpm/lib/spi/spidev_iface.cpp index 919cf338e..fe37f16d5 100644 --- a/mpm/lib/spi/spidev_iface.cpp +++ b/mpm/lib/spi/spidev_iface.cpp @@ -15,14 +15,15 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#include "mpm/spi/spidev_iface.hpp" -#include <fcntl.h> -#include <sys/ioctl.h> -#include <linux/types.h> +#include <mpm/spi/spi_iface.hpp> +#include <mpm/exception.hpp> +extern "C" { +#include "spidev.h" +} #include <linux/spi/spidev.h> -#include <boost/format.hpp> +#include <boost/format.hpp> #include <iostream> using namespace mpm::spi; @@ -30,68 +31,29 @@ using namespace mpm::spi; /****************************************************************************** * Implementation *****************************************************************************/ -class spidev_iface_impl : public spidev_iface +class spidev_iface_impl : public spi_iface { public: spidev_iface_impl( - const std::string &device - ) { - int ret; - - _fd = open(device.c_str(), O_RDWR); - if (_fd < 0) { - throw std::runtime_error(str( - boost::format("Could not open spidev device %s") - % device - )); - } - - int MODE = 3; - ret = ioctl(_fd, SPI_IOC_WR_MODE32, &MODE); - if (ret == -1) { - throw std::runtime_error(str( - boost::format("Could not set spidev mode to %X for spidev %s") - % uint16_t(_mode) % device - )); - } - - ret = ioctl(_fd, SPI_IOC_RD_MODE32, &_mode); - if (ret == -1) { - throw std::runtime_error(str( - boost::format("Could not get spidev mode for spidev %s") - % device - )); - } - - ret = ioctl(_fd, SPI_IOC_WR_BITS_PER_WORD, &_bits); - if (ret == -1) { - throw std::runtime_error(str( - boost::format("Could not set spidev bits per word to %d for spidev %s") - % uint16_t(_bits) % device - )); - } + const std::string &device, + const int max_speed_hz + ) : _speed(max_speed_hz) + { - ret = ioctl(_fd, SPI_IOC_RD_BITS_PER_WORD, &_bits); - if (ret == -1) { - throw std::runtime_error(str( - boost::format("Could not get spidev bits per word for spidev %s") + if (!init_spi( + &_fd, + device.c_str(), + _mode, _speed, _bits, _delay + )) { + throw mpm::runtime_error(str( + boost::format("Could not initialize spidev device %s") % device )); } - - ret = ioctl(_fd, SPI_IOC_WR_MAX_SPEED_HZ, &_speed); - if (ret == -1) { - throw std::runtime_error(str( - boost::format("Could not set spidev max speed to %d for spidev %s") - % _speed % device - )); - } - - ret = ioctl(_fd, SPI_IOC_RD_MAX_SPEED_HZ, &_speed); - if (ret == -1) { - throw std::runtime_error(str( - boost::format("Could not get spidev max speed for spidev %s") + if (_fd < 0) { + throw mpm::runtime_error(str( + boost::format("Could not open spidev device %s") % device )); } @@ -102,60 +64,32 @@ public: close(_fd); } - uint32_t transact_spi( - int /* which_slave */, - const uhd::spi_config_t & /* config */, - uint32_t data, - size_t num_bits, - bool readback + uint32_t transfer24_8( + const uint32_t data_ ) { int ret(0); + uint32_t data = data_; uint8_t *tx_data = reinterpret_cast<uint8_t *>(&data); - assert(num_bits == 24); - uint8_t tx[] = {tx_data[2], tx_data[1], tx_data[0]}; - + // Create tx and rx buffers: + uint8_t tx[] = {tx_data[2], tx_data[1], tx_data[0]}; // FIXME guarantee endianness uint8_t rx[3]; // Buffer length must match tx buffer - struct spi_ioc_transfer tr; - tr.tx_buf = (unsigned long) &tx[0]; - tr.rx_buf = (unsigned long) &rx[0]; - tr.len = num_bits >> 3; - tr.speed_hz = _speed; - tr.delay_usecs = _delay; - tr.bits_per_word = _bits; - tr.cs_change = 0; - tr.tx_nbits = 1; // Standard SPI - tr.rx_nbits = 1; // Standard SPI - - ret = ioctl(_fd, SPI_IOC_MESSAGE(1), &tr); - if (ret < 1) - throw std::runtime_error("Could not send spidev message"); - - return rx[2]; // Assumes that only a single byte is being read. - } - - uint32_t read_spi( - int which_slave, - const uhd::spi_config_t &config, - uint32_t data, - size_t num_bits - ) { - return transact_spi( - which_slave, config, data, num_bits, true - ); - } + if (transfer( + _fd, + &tx[0], &rx[0], + 3, + _speed, _bits, _delay + ) != 0) { + throw mpm::runtime_error(str( + boost::format("SPI Transaction failed!") + )); + } - void write_spi( - int which_slave, - const uhd::spi_config_t &config, - uint32_t data, - size_t num_bits - ) { - transact_spi( - which_slave, config, data, num_bits, false - ); + // Assumes that only a single byte is being read. + // TODO the function does not advertise this. Should probably fix. + return uint32_t(rx[2]); } private: @@ -169,9 +103,12 @@ private: /****************************************************************************** * Factory *****************************************************************************/ -spidev_iface::sptr spidev_iface::make( - const std::string &device +spi_iface::sptr spi_iface::make_spidev( + const std::string &device, + const int speed_hz ) { - return sptr(new spidev_iface_impl(device)); + return std::make_shared<spidev_iface_impl>( + device, speed_hz + ); } |