.. _program_listing_file_src_spi.cpp: Program Listing for File spi.cpp ================================ |exhale_lsh| :ref:`Return to documentation for file ` (``src/spi.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include #include #include #include extern "C" { #include #include #include #ifdef __linux__ #include #include #endif } #include "spi_bus/spi.hh" using iplo::SPI; void SPI::open() { if ((_fd = ::open(_fileName, O_RDWR | O_NONBLOCK)) < 0) { std::perror("Error opening SPI bus"); std::exit(-1); } } void SPI::close() const { if (::close(_fd) < 0) { std::perror("Error closing SPI bus"); std::exit(-1); } } SPI::SPI(const char* fileName) : _fileName(fileName) { open(); } SPI::SPI(const char* fileName, const SpiConfig& config) : _fileName(fileName) { open(); setConfig(config); } std::int32_t SPI::read(std::uint8_t* rxBuffer, std::uint8_t rxBufferLength) { #ifdef __linux__ // Mockup code for development on different platforms. struct spi_ioc_transfer spiMessage[1]; std::memset(spiMessage, 0, sizeof(spiMessage)); spiMessage[0].rx_buf = (unsigned long) rxBuffer; spiMessage[0].len = rxBufferLength; spiMessage[0].delay_usecs = _spiConfig.delayUs; return ::ioctl(_fd, SPI_IOC_MESSAGE(1), spiMessage); #else return rxBufferLength; #endif } std::int32_t SPI::write(std::uint8_t* txBuffer, std::uint8_t txBufferLength) { #ifdef __linux__ // Mockup code for development on different platforms. struct spi_ioc_transfer spiMessage[1]; std::memset(spiMessage, 0, sizeof(spiMessage)); spiMessage[0].tx_buf = (unsigned long) txBuffer; spiMessage[0].len = txBufferLength; spiMessage[0].delay_usecs = _spiConfig.delayUs; return ::ioctl(_fd, SPI_IOC_MESSAGE(1), spiMessage); #else return txBufferLength; #endif } std::int32_t SPI::xfer(std::uint8_t* txBuffer, std::uint8_t txBufferLength, std::uint8_t* rxBuffer, std::uint8_t rxBufferLength) { #ifdef __linux__ // Mockup code for development on different platforms. struct spi_ioc_transfer spiMessage[1]; std::memset(spiMessage, 0, sizeof(spiMessage)); spiMessage[0].rx_buf = (unsigned long) rxBuffer; spiMessage[0].tx_buf = (unsigned long) txBuffer; spiMessage[0].len = txBufferLength; spiMessage[0].delay_usecs = _spiConfig.delayUs; return ::ioctl(_fd, SPI_IOC_MESSAGE(1), spiMessage); #else return rxBufferLength; #endif } bool SPI::setSpeed(std::uint32_t speedHz) { #ifdef __linux__ // Mockup code for development on different platforms. if (::ioctl(_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speedHz) < 0) { return false; } if (::ioctl(_fd, SPI_IOC_RD_MAX_SPEED_HZ, &speedHz) < 0) { return false; } _spiConfig.speedHz = speedHz; // Only assign new value if properly set. return true; #else return bool(speedHz); #endif } bool SPI::setMode(std::uint8_t mode) { #ifdef __linux__ // Mockup code for development on different platforms. if (::ioctl(_fd, SPI_IOC_WR_MODE, &mode) < 0) { return false; } if (::ioctl(_fd, SPI_IOC_RD_MODE, &mode) < 0) { return false; } _spiConfig.mode = mode; // Only assign new value if properly set. return true; #else return bool(mode); #endif } bool SPI::setBitsPerWord(std::uint8_t bits) { #ifdef __linux__ // Mockup code for development on different platforms. if (::ioctl(_fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) { return false; } if (::ioctl(_fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) { return false; } _spiConfig.bitsPerWord = bits; // Only assign new value if properly set. return true; #else return bool(bits); #endif } bool SPI::setConfig(const SpiConfig& spiConfig) { if (!setMode(spiConfig.mode)) { std::perror("Error setting mode on SPI bus"); return false; } if (!setSpeed(spiConfig.speedHz)) { std::perror("Error setting speedHz for SPI bus"); return false; } if (!setBitsPerWord(spiConfig.bitsPerWord)) { std::perror("Error setting bits per word value"); return false; } return true; } SPI::~SPI() { close(); }