From 96037da1cfdcf3230ced7e9884014954b62d7a7e Mon Sep 17 00:00:00 2001 From: penfold42 Date: Tue, 28 Jun 2016 06:43:35 +1000 Subject: [PATCH] Added support for sk6812RGBW leds (ab)using the SPI interface. (#61) right now it only uses RGB - white is set to zero --- libsrc/leddevice/CMakeLists.txt | 2 + libsrc/leddevice/LedDeviceFactory.cpp | 11 ++++ libsrc/leddevice/LedDeviceSk6812SPI.cpp | 67 +++++++++++++++++++++++++ libsrc/leddevice/LedDeviceSk6812SPI.h | 43 ++++++++++++++++ libsrc/leddevice/LedDeviceWs2812SPI.h | 4 -- 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 libsrc/leddevice/LedDeviceSk6812SPI.cpp create mode 100644 libsrc/leddevice/LedDeviceSk6812SPI.h diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index fa988195..41e70d1e 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -79,6 +79,7 @@ if(ENABLE_SPIDEV) ${CURRENT_SOURCE_DIR}/LedDeviceP9813.h ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h + ${CURRENT_SOURCE_DIR}/LedDeviceSk6812SPI.h ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h ) SET(Leddevice_SOURCES @@ -89,6 +90,7 @@ if(ENABLE_SPIDEV) ${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceSk6812SPI.cpp ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp ) endif() diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index a2e39f87..068eb98b 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -17,6 +17,7 @@ #include "LedDeviceP9813.h" #include "LedDeviceWs2801.h" #include "LedDeviceWs2812SPI.h" + #include "LedDeviceSk6812SPI.h" #include "LedDeviceAPA102.h" #endif @@ -147,6 +148,16 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) device = deviceWs2812SPI; } + else if (type == "sk6812spi") + { + const std::string output = deviceConfig["output"].asString(); + const unsigned rate = deviceConfig.get("rate",2857143).asInt(); + + LedDeviceSk6812SPI* deviceSk6812SPI = new LedDeviceSk6812SPI(output, rate); + deviceSk6812SPI->open(); + + device = deviceSk6812SPI; + } #endif #ifdef ENABLE_TINKERFORGE else if (type=="tinkerforge") diff --git a/libsrc/leddevice/LedDeviceSk6812SPI.cpp b/libsrc/leddevice/LedDeviceSk6812SPI.cpp new file mode 100644 index 00000000..42002580 --- /dev/null +++ b/libsrc/leddevice/LedDeviceSk6812SPI.cpp @@ -0,0 +1,67 @@ + +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +// hyperion local includes +#include "LedDeviceSk6812SPI.h" + +LedDeviceSk6812SPI::LedDeviceSk6812SPI(const std::string& outputDevice, const unsigned baudrate) : + LedSpiDevice(outputDevice, baudrate, 0), + mLedCount(0), + bitpair_to_byte { + 0b10001000, + 0b10001100, + 0b11001000, + 0b11001100, + } + +{ + // empty +} + +int LedDeviceSk6812SPI::write(const std::vector &ledValues) +{ + mLedCount = ledValues.size(); + +// 4 colours, 4 spi bytes per colour + 3 frame end latch bytes +#define COLOURS_PER_LED 3 +#define SPI_BYTES_PER_COLOUR 4 +#define SPI_BYTES_PER_LED COLOURS_PER_LED * SPI_BYTES_PER_COLOUR + + unsigned spi_size = mLedCount * SPI_BYTES_PER_LED + 3; + if(_spiBuffer.size() != spi_size){ + _spiBuffer.resize(spi_size, 0x00); + } + + unsigned spi_ptr = 0; + for (unsigned i=0; i< mLedCount; ++i) { + uint8_t white = 0; + uint32_t colorBits = + ((unsigned int)ledValues[i].red << 24) | + ((unsigned int)ledValues[i].green << 16) | + ((unsigned int)ledValues[i].blue << 8) | + white; + + for (int j=SPI_BYTES_PER_LED - 1; j>=0; j--) { + _spiBuffer[spi_ptr+j] = bitpair_to_byte[ colorBits & 0x3 ]; + colorBits >>= 2; + } + spi_ptr += SPI_BYTES_PER_LED; + } + _spiBuffer[spi_ptr++] = 0; + _spiBuffer[spi_ptr++] = 0; + _spiBuffer[spi_ptr++] = 0; + + return writeBytes(spi_size, _spiBuffer.data()); +} + +int LedDeviceSk6812SPI::switchOff() +{ + return write(std::vector(mLedCount, ColorRgb{0,0,0})); +} diff --git a/libsrc/leddevice/LedDeviceSk6812SPI.h b/libsrc/leddevice/LedDeviceSk6812SPI.h new file mode 100644 index 00000000..fc7ea01f --- /dev/null +++ b/libsrc/leddevice/LedDeviceSk6812SPI.h @@ -0,0 +1,43 @@ +#pragma once + +// STL includes +#include + +// hyperion incluse +#include "LedSpiDevice.h" + +/// +/// Implementation of the LedDevice interface for writing to Sk6801 led device. +/// +class LedDeviceSk6812SPI : public LedSpiDevice +{ +public: + /// + /// Constructs the LedDevice for a string containing leds of the type Sk6812SPI + /// + /// @param outputDevice The name of the output device (eg '/etc/SpiDev.0.0') + /// @param baudrate The used baudrate for writing to the output device + /// + + LedDeviceSk6812SPI(const std::string& outputDevice, + const unsigned baudrate); + + /// + /// Writes the led color values to the led-device + /// + /// @param ledValues The color-value per led + /// @return Zero on succes else negative + /// + virtual int write(const std::vector &ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + + /// the number of leds (needed when switching off) + size_t mLedCount; + std::vector _spiBuffer; + + uint8_t bitpair_to_byte[4]; +}; diff --git a/libsrc/leddevice/LedDeviceWs2812SPI.h b/libsrc/leddevice/LedDeviceWs2812SPI.h index 408e2b9f..2451c772 100644 --- a/libsrc/leddevice/LedDeviceWs2812SPI.h +++ b/libsrc/leddevice/LedDeviceWs2812SPI.h @@ -21,10 +21,6 @@ public: LedDeviceWs2812SPI(const std::string& outputDevice, const unsigned baudrate); - LedDeviceWs2812SPI(const std::string& outputDevice, - const unsigned baudrate, - const unsigned latchTime); - /// /// Writes the led color values to the led-device ///