diff --git a/include/sta/raspi/gpio_pin.hpp b/include/sta/raspi/gpio_pin.hpp index 6230b1c..64d5ee6 100644 --- a/include/sta/raspi/gpio_pin.hpp +++ b/include/sta/raspi/gpio_pin.hpp @@ -31,10 +31,18 @@ namespace sta void setState(GpioPinState state) override; + static RaspiGpioPin DUMMY_GPIO; + private: uint8_t pin_; GpioMode mode_; }; + + class DummyGpioPin : RaspiGpioPin { + DummyGpioPin(); + + void setState(GpioPinState state) override; + } } // namespace sta #endif // STA_RASPI_GPIO_ENABLED diff --git a/include/sta/raspi/hal.hpp b/include/sta/raspi/hal.hpp index f3e008b..5b6173a 100644 --- a/include/sta/raspi/hal.hpp +++ b/include/sta/raspi/hal.hpp @@ -2,7 +2,7 @@ #define STA_CORE_RASPI_HAL_HPP #include -#include #include +#include #endif //STA_CORE_RASPI_HAL_HPP diff --git a/include/sta/raspi/spi.hpp b/include/sta/raspi/spi.hpp index 9758b19..cc8e741 100644 --- a/include/sta/raspi/spi.hpp +++ b/include/sta/raspi/spi.hpp @@ -1,19 +1,50 @@ #ifndef STA_CORE_RASPI_SPI_HPP #define STA_CORE_RASPI_SPI_HPP +#include +#ifdef STA_PLATFORM_RASPI + #include +#include namespace sta { - class RaspiSPI : SPI + class RaspiSPI : public SPI { + public: + RaspiSPI(const char * dev, const SPISettings & settings, Mutex * mutex = nullptr); + ~RaspiSPI(); + void transfer(uint8_t value) override; + void transfer16(uint16_t value) override; + void transfer(const uint8_t * buffer, size_t size) override; + void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) override; + void receive(uint8_t * buffer, size_t size) override; + + void fill(uint8_t value, size_t count) override; + + void acquire() override; + void release() override; + + private: + char * spidev_; + int spifd_; + bool open_; + + void update_setting(int setting, int value); }; class RaspiSPIDevice : SPIDevice { + public: + RaspiSPIDevice(RaspiSPI * intf); + void select() override; + + void deselect() override; }; } // namespace sta +#endif // STA_PLATFORM_RASPI + #endif // STA_CORE_RASPI_HPP \ No newline at end of file diff --git a/src/raspi/gpio_pin.cpp b/src/raspi/gpio_pin.cpp index a15fa43..01773d0 100644 --- a/src/raspi/gpio_pin.cpp +++ b/src/raspi/gpio_pin.cpp @@ -15,6 +15,22 @@ namespace sta { digitalWrite(pin_, state == GpioPinState::GPIO_LOW ? LOW : HIGH); } + + DummyGpioPin::DummyGpioPin() : RaspiGpioPin { -1 , GpioMode::GPIO_INPUT } + { + + } + + DummyGpioPin::setState(GpioPinState state) + { + // If this gets called, something is wrong! + STA_UNREACHABLE(); + } + + static DummyGpioPin dummyGpio; + + + RaspiGpioPin * RaspiGpioPin::DUMMY_GPIO = &dummyGpio; } // namespace sta diff --git a/src/raspi/spi.cpp b/src/raspi/spi.cpp new file mode 100644 index 0000000..135adb1 --- /dev/null +++ b/src/raspi/spi.cpp @@ -0,0 +1,188 @@ +#include +#ifdef STA_PLATFORM_RASPI + + +#include +#include +#include +#include + +#include +#include + +namespace sta +{ + + RaspiSPI::RaspiSPI(const char * dev, const SPISettings & settings, Mutex * mutex = nullptr) + : SPI(settings, mutex) + { + // Check validity of parameters. + STA_ASSERT(dev != nullptr); + STA_ASSERT(mutex != nullptr); + + open_ = false; + spidev_ = (char *)malloc(strlen(dev)+1); + + // Check if memory allocation was successful. + STA_ASSERT(spidev_ != nullptr); + + strcpy(spidev_ , dev); + } + + RaspiSPI::~RaspiSPI() + { + if (spidev_ != NULL ) { + free(spidev_); + spidev_ = NULL; + } + + if (open_) { + close(spifd_); + } + } + + void RaspiSPI::transfer(uint8_t value) + { + STA_ASSERT(open_); + + struct spi_ioc_transfer spi_message[1]; + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)&value; + spi_message[0].len = 1; + + int result = ioctl(m_spifd, SPI_IOC_MESSAGE(1), spi_message); + + STA_ASSERT(result == 0); + } + + void RaspiSPI::transfer16(uint16_t value) + { + STA_ASSERT(open_); + + struct spi_ioc_transfer spi_message[1]; + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)&value; + spi_message[0].len = 1; + + int result = ioctl(m_spifd, SPI_IOC_MESSAGE(1), spi_message); + + STA_ASSERT(result == 0); + } + + void RaspiSPI::transfer(const uint8_t * buffer, size_t size) + { + STA_ASSERT(open_); + STA_ASSERT(buffer != nullptr); + STA_ASSERT(size != 0); + + struct spi_ioc_transfer spi_message[1]; + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)buffer; + spi_message[0].len = size; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + STA_ASSERT(result == 0); + } + + void RaspiSPI::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) + { + STA_ASSERT(txBuffer != nullptr); + STA_ASSERT(rxBuffer != nullptr); + STA_ASSERT(size != 0); + + struct spi_ioc_transfer spi_message[1]; + memset(spi_message, 0, sizeof(spi_message)); + + spi_message[0].rx_buf = (unsigned long)rxBuffer; + spi_message[0].tx_buf = (unsigned long)txBuffer; + spi_message[0].len = size; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + STA_ASSERT(result == 0); + } + + void RaspiSPI::receive(uint8_t * buffer, size_t size) + { + STA_ASSERT(buffer != nullptr); + + struct spi_ioc_transfer spi_message[1]; + memset(spi_message, 0, sizeof(spi_message)); + + spi_message[0].rx_buf = (unsigned long)buffer; + spi_message[0].len = size; + return ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + } + + void RaspiSPI::fill(uint8_t value, size_t count) + { + STA_ASSERT(count != 0); + + uint8_t * buffer = new uint8_t[count]; + memset(buffer, value, count); + + struct spi_ioc_transfer spi_message[1]; + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)buffer; + spi_message[0].len = count; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + delete[] buffer; + } + + void RaspiSPI::update_setting(int setting, int value) + { + STA_ASSERT(open_); + + int result = ioctl(spifd_, setting, value); + STA_ASSERT(result >= 0); + } + + void RaspiSPI::acquire() + { + SPI::acquire(); + + STA_ASSERT(spidev_ != nullptr); + + /* open spidev device */ + if (open_ == true) + return; + + spifd_ = open(spidev_, O_RDWR); + STA_ASSERT(spifd_ < 0); + + open_ = true; + + update_setting(SPI_IOC_WR_MODE, &m_spiconfig.mode); + update_setting(SPI_IOC_RD_MODE, &m_spiconfig.mode); + update_setting(SPI_IOC_WR_BITS_PER_WORD, &m_spiconfig.bits_per_word); + update_setting(SPI_IOC_RD_BITS_PER_WORD, &m_spiconfig.bits_per_word); + uppdate_setting(SPI_IOC_WR_MAX_SPEED_HZ, &m_spiconfig.speed); + update_setting(SPI_IOC_RD_MAX_SPEED_HZ, &m_spiconfig.speed); + } + + void RaspiSPI::release() + { + SPI::release(); + } + + RaspiSPIDevice::RaspiSPIDevice(RaspiSPI * intf) : SPIDevice { intf, RaspiGpioPin::DUMMY_GPIO } + { + + } + + RaspiSPIDevice::select() + { + // do nothing since the raspi SPI API doesn't require GPIO interaction. + } + + RaspiSPIDevice::deselect() + { + // do nothing since the raspi SPI API doesn't require GPIO interaction. + } +} // namespace sta + + +#endif // STA_PlATFORM_RASPI