From 2b4adce2d4d0c7b3097fb26afe102d87fcb773cb Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Tue, 10 Dec 2013 18:59:49 +0000 Subject: [PATCH] Added first implementation of WS2811 Former-commit-id: e4fbe7a7f33c28e1f430b5159e6a5cf8c4fc4f9a --- libsrc/hyperion/CMakeLists.txt | 2 + libsrc/hyperion/Hyperion.cpp | 11 +++ libsrc/hyperion/device/LedDeviceWs2811.cpp | 88 ++++++++++++++++++++++ libsrc/hyperion/device/LedDeviceWs2811.h | 38 ++++++++++ 4 files changed, 139 insertions(+) create mode 100644 libsrc/hyperion/device/LedDeviceWs2811.cpp create mode 100644 libsrc/hyperion/device/LedDeviceWs2811.h diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 8a70c46a..2f18836a 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -46,6 +46,7 @@ SET(Hyperion_HEADERS ${CURRENT_SOURCE_DIR}/device/LedDeviceTest.h ${CURRENT_SOURCE_DIR}/device/LedDeviceSedu.h ${CURRENT_SOURCE_DIR}/device/LedDeviceWs2801.h + ${CURRENT_SOURCE_DIR}/device/LedDeviceWs2811.h ${CURRENT_SOURCE_DIR}/device/LedDeviceLpd6803.h ${CURRENT_SOURCE_DIR}/device/LedDeviceLpd8806.h ${CURRENT_SOURCE_DIR}/device/LedDeviceLightpack.h @@ -70,6 +71,7 @@ SET(Hyperion_SOURCES ${CURRENT_SOURCE_DIR}/device/LedDeviceSedu.cpp ${CURRENT_SOURCE_DIR}/device/LedDeviceTest.cpp ${CURRENT_SOURCE_DIR}/device/LedDeviceWs2801.cpp + ${CURRENT_SOURCE_DIR}/device/LedDeviceWs2811.cpp ${CURRENT_SOURCE_DIR}/device/LedDeviceLpd6803.cpp ${CURRENT_SOURCE_DIR}/device/LedDeviceLpd8806.cpp ${CURRENT_SOURCE_DIR}/device/LedDeviceAdalight.cpp diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 8c746ef9..07ee4335 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -21,6 +21,7 @@ #include "device/LedDeviceSedu.h" #include "device/LedDeviceTest.h" #include "device/LedDeviceWs2801.h" +#include "device/LedDeviceWs2811.h" #include "device/LedDeviceAdalight.h" #include "device/LedDeviceLightpack.h" #include "device/LedDeviceMultiLightpack.h" @@ -46,6 +47,16 @@ LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig) device = deviceWs2801; } + else if (type == "ws2811") + { + const std::string output = deviceConfig["output"].asString(); + const bool rate = deviceConfig["fast"].asBool(); + + LedDeviceWs2811 * deviceWs2811 = new LedDeviceWs2811(output, rate); + deviceWs2811->open(); + + device = deviceWs2811; + } else if (type == "lpd6803" || type == "ldp6803") { const std::string output = deviceConfig["output"].asString(); diff --git a/libsrc/hyperion/device/LedDeviceWs2811.cpp b/libsrc/hyperion/device/LedDeviceWs2811.cpp new file mode 100644 index 00000000..4e905e7a --- /dev/null +++ b/libsrc/hyperion/device/LedDeviceWs2811.cpp @@ -0,0 +1,88 @@ + +// Local hyperion includes +#include "LedDeviceWs2811.h" + +LedDeviceWs2811::LedDeviceWs2811(const std::string & deviceName, const bool fastDevice) : + LedRs232Device(deviceName, fastDevice?4000000:2000000) +{ + fillEncodeTable(); +} + +int LedDeviceWs2811::write(const std::vector & ledValues) +{ + if (_ledBuffer.size() != ledValues.size() * 3) + { + _ledBuffer.resize(ledValues.size() * 3); + } + + auto bufIt = _ledBuffer.begin(); + for (const ColorRgb & color : ledValues) + { + *bufIt = _byteToSignalTable[color.red ]; + ++bufIt; + *bufIt = _byteToSignalTable[color.green]; + ++bufIt; + *bufIt = _byteToSignalTable[color.blue ]; + ++bufIt; + } + + writeBytes(_ledBuffer.size() * 3, reinterpret_cast(_ledBuffer.data())); + + return 0; +} + +int LedDeviceWs2811::switchOff() +{ + write(std::vector(_ledBuffer.size()/3, ColorRgb::BLACK)); + return 0; +} + +void LedDeviceWs2811::fillEncodeTable() +{ + for (unsigned byteValue=0; byteValue<256; ++byteValue) + { + char byteSignal[4]; + for (unsigned iBit=0; iBit<8; iBit=2) + { + // Isolate two bits + char bitVal = (byteValue >> (6-iBit)) & 0x03; + + switch (bitVal) + { + case 0: + // _ _ + // | | _ _ _ _| |_ _ _ _| + // <----bits-----> + byteSignal[iBit/2] = 0x08; + break; + case 1: + // _ _ _ + // | | _ _ _ _| |_ _ _| + // <----bits-----> + byteSignal[iBit/2] = 0x0C;; + break; + case 2: + // _ _ _ + // | |_ _ _| |_ _ _ _| + // <----bits-----> + byteSignal[iBit/2] = 0x88; + break; + case 3: + // _ _ _ _ + // | |_ _ _| |_ _ _| + // <----bits-----> + byteSignal[iBit/2] = 0x8C; + break; + default: + // Should not happen + std::cerr << "two bits evaluated to other value: " << bitVal << std::endl; + } + } + const unsigned byteSignalVal = + (byteSignal[0] & 0x00ff) << 0 | + (byteSignal[1] & 0x00ff) << 8 | + (byteSignal[2] & 0x00ff) << 16 | + (byteSignal[3] & 0x00ff) << 24; + _byteToSignalTable.push_back(byteSignalVal); + } +} diff --git a/libsrc/hyperion/device/LedDeviceWs2811.h b/libsrc/hyperion/device/LedDeviceWs2811.h new file mode 100644 index 00000000..dfca9354 --- /dev/null +++ b/libsrc/hyperion/device/LedDeviceWs2811.h @@ -0,0 +1,38 @@ +#pragma once + +// Local hyperion includes +#include "LedRs232Device.h" + +class LedDeviceWs2811 : public LedRs232Device +{ +public: + /// + /// Constructs the LedDevice with Ws2811 attached via a serial port + /// + /// @param outputDevice The name of the output device (eg '/dev/ttyS0') + /// @param fastDevice The used baudrate for writing to the output device + /// + LedDeviceWs2811(const std::string& outputDevice, const bool fastDevice); + + /// + /// 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: + + void fillEncodeTable(); + + /** Translation table of byte to signal */ + std::vector _byteToSignalTable; + + /// The buffer containing the packed RGB values + std::vector _ledBuffer; +};