diff --git a/.gitmodules b/.gitmodules index 462e3f07..ee8a54b5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,5 @@ url = https://github.com/tvdzwan/protobuf.git [submodule "dependencies/external/rpi_ws281x"] path = dependencies/external/rpi_ws281x - url = https://github.com/penfold42/rpi_ws281x + url = https://github.com/penfold42/rpi_ws281x.git + branch = sk6812 diff --git a/include/leddevice/LedDevice.h b/include/leddevice/LedDevice.h index 548770c3..64018f10 100644 --- a/include/leddevice/LedDevice.h +++ b/include/leddevice/LedDevice.h @@ -5,6 +5,8 @@ // Utility includes #include +#include +#include /// /// Interface (pure virtual base class) for LedDevices. diff --git a/include/utils/ColorRgbw.h b/include/utils/ColorRgbw.h new file mode 100644 index 00000000..a06c6d24 --- /dev/null +++ b/include/utils/ColorRgbw.h @@ -0,0 +1,65 @@ +#pragma once + +// STL includes +#include +#include + +struct ColorRgbw; + +/// +/// Plain-Old-Data structure containing the red-green-blue color specification. Size of the +/// structure is exactly 3-bytes for easy writing to led-device +/// +struct ColorRgbw +{ + /// The red color channel + uint8_t red; + /// The green color channel + uint8_t green; + /// The blue color channel + uint8_t blue; + /// The white color channel + uint8_t white; + + /// 'Black' RgbColor (0, 0, 0, 0) + static ColorRgbw BLACK; + /// 'Red' RgbColor (255, 0, 0, 0) + static ColorRgbw RED; + /// 'Green' RgbColor (0, 255, 0, 0) + static ColorRgbw GREEN; + /// 'Blue' RgbColor (0, 0, 255, 0) + static ColorRgbw BLUE; + /// 'Yellow' RgbColor (255, 255, 0, 0) + static ColorRgbw YELLOW; + /// 'White' RgbColor (0, 0, 0, 255) + static ColorRgbw WHITE; +}; + +/// Assert to ensure that the size of the structure is 'only' 4 bytes +static_assert(sizeof(ColorRgbw) == 4, "Incorrect size of ColorRgbw"); + +/// +/// Stream operator to write ColorRgb to an outputstream (format "'{'[red]','[green]','[blue]'}'") +/// +/// @param os The output stream +/// @param color The color to write +/// @return The output stream (with the color written to it) +/// +inline std::ostream& operator<<(std::ostream& os, const ColorRgbw& color) +{ + os << "{" << unsigned(color.red) << "," << unsigned(color.green) << "," << unsigned(color.blue) << "," << unsigned(color.white) << "}"; + return os; +} + + +/// Compare operator to check if a color is 'smaller' than another color +inline bool operator<(const ColorRgbw & lhs, const ColorRgbw & rhs) +{ + return (lhs.red < rhs.red) && (lhs.green < rhs.green) && (lhs.blue < rhs.blue) && (lhs.white < rhs.white); +} + +/// Compare operator to check if a color is 'smaller' than or 'equal' to another color +inline bool operator<=(const ColorRgbw & lhs, const ColorRgbw & rhs) +{ + return (lhs.red <= rhs.red) && (lhs.green <= rhs.green) && (lhs.blue <= rhs.blue) && (lhs.white < rhs.white); +} diff --git a/include/utils/RgbToRgbw.h b/include/utils/RgbToRgbw.h new file mode 100644 index 00000000..99835512 --- /dev/null +++ b/include/utils/RgbToRgbw.h @@ -0,0 +1,4 @@ +#include +#include + +void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, std::string _whiteAlgorithm); diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index ed07249c..4013cf40 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -363,8 +363,11 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) const int dmanum = deviceConfig.get("dmanum", 5).asInt(); const int pwmchannel = deviceConfig.get("pwmchannel", 0).asInt(); const int invert = deviceConfig.get("invert", 0).asInt(); + const int rgbw = deviceConfig.get("rgbw", 0).asInt(); + const std::string& whiteAlgorithm = deviceConfig.get("white_algorithm","").asString(); - LedDeviceWS281x * ledDeviceWS281x = new LedDeviceWS281x(gpio, leds, freq, dmanum, pwmchannel, invert); + LedDeviceWS281x * ledDeviceWS281x = new LedDeviceWS281x(gpio, leds, freq, dmanum, pwmchannel, invert, + rgbw, whiteAlgorithm); device = ledDeviceWS281x; } #endif diff --git a/libsrc/leddevice/LedDeviceWS281x.cpp b/libsrc/leddevice/LedDeviceWS281x.cpp index 542ff80c..8349c70b 100644 --- a/libsrc/leddevice/LedDeviceWS281x.cpp +++ b/libsrc/leddevice/LedDeviceWS281x.cpp @@ -3,8 +3,11 @@ #include "LedDeviceWS281x.h" // Constructor -LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum, const int pwmchannel, const int invert) +LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum, const int pwmchannel, const int invert, const int rgbw, const std::string& whiteAlgorithm) { + _whiteAlgorithm = whiteAlgorithm; +std::cout << "whiteAlgorithm :" << whiteAlgorithm << ":\n"; + initialized = false; led_string.freq = freq; led_string.dmanum = dmanum; @@ -17,7 +20,11 @@ LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t led_string.channel[chan].invert = invert; led_string.channel[chan].count = leds; led_string.channel[chan].brightness = 255; - led_string.channel[chan].strip_type = WS2811_STRIP_RGB; + if (rgbw == 1) { + led_string.channel[chan].strip_type = SK6812_STRIP_GRBW; + } else { + led_string.channel[chan].strip_type = WS2811_STRIP_RGB; + } led_string.channel[!chan].gpionum = 0; led_string.channel[!chan].invert = invert; @@ -42,7 +49,19 @@ int LedDeviceWS281x::write(const std::vector &ledValues) { if (idx >= led_string.channel[chan].count) break; - led_string.channel[chan].leds[idx++] = ((uint32_t)color.red << 16) + ((uint32_t)color.green << 8) + color.blue; + + _temp_rgbw.red = color.red; + _temp_rgbw.green = color.green; + _temp_rgbw.blue = color.blue; + _temp_rgbw.white = 0; + + if (led_string.channel[chan].strip_type == SK6812_STRIP_GRBW) { + Rgb_to_Rgbw(color, &_temp_rgbw, _whiteAlgorithm); + } + + led_string.channel[chan].leds[idx++] = + ((uint32_t)_temp_rgbw.white << 24) + ((uint32_t)_temp_rgbw.red << 16) + ((uint32_t)_temp_rgbw.green << 8) + _temp_rgbw.blue; + } while (idx < led_string.channel[chan].count) led_string.channel[chan].leds[idx++] = 0; diff --git a/libsrc/leddevice/LedDeviceWS281x.h b/libsrc/leddevice/LedDeviceWS281x.h index 29209016..557598a8 100644 --- a/libsrc/leddevice/LedDeviceWS281x.h +++ b/libsrc/leddevice/LedDeviceWS281x.h @@ -18,9 +18,11 @@ public: /// @param dmanum The DMA channel to use, default is 5 /// @param pwmchannel The pwm channel to use /// @param invert Invert the output line to support an inverting level shifter + /// @param rgbw Send 32 bit rgbw colour data for sk6812 /// - LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, int dmanum, int pwmchannel, int invert); + LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, int dmanum, int pwmchannel, int invert, + int rgbw, const std::string& whiteAlgorithm); /// /// Destructor of the LedDevice, waits for DMA to complete and then cleans up @@ -42,6 +44,8 @@ private: ws2811_t led_string; int chan; bool initialized; + std::string _whiteAlgorithm; + ColorRgbw _temp_rgbw; }; #endif /* LEDDEVICEWS281X_H_ */ diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index 1b9e2982..caf0aabe 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -1,4 +1,3 @@ - # Define the current source locations SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils) @@ -12,6 +11,8 @@ add_library(hyperion-utils ${CURRENT_SOURCE_DIR}/ColorRgb.cpp ${CURRENT_HEADER_DIR}/ColorRgba.h ${CURRENT_SOURCE_DIR}/ColorRgba.cpp + ${CURRENT_HEADER_DIR}/ColorRgbw.h + ${CURRENT_SOURCE_DIR}/ColorRgbw.cpp ${CURRENT_HEADER_DIR}/Image.h ${CURRENT_HEADER_DIR}/Sleep.h @@ -32,6 +33,9 @@ add_library(hyperion-utils ${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h ${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp + ${CURRENT_HEADER_DIR}/RgbToRgbw.h + ${CURRENT_SOURCE_DIR}/RgbToRgbw.cpp + ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h ${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp diff --git a/libsrc/utils/ColorRgbw.cpp b/libsrc/utils/ColorRgbw.cpp new file mode 100644 index 00000000..af7cf9da --- /dev/null +++ b/libsrc/utils/ColorRgbw.cpp @@ -0,0 +1,10 @@ + +// Local includes +#include + +ColorRgbw ColorRgbw::BLACK = { 0, 0, 0, 0 }; +ColorRgbw ColorRgbw::RED = { 255, 0, 0, 0 }; +ColorRgbw ColorRgbw::GREEN = { 0, 255, 0, 0 }; +ColorRgbw ColorRgbw::BLUE = { 0, 0, 255, 0 }; +ColorRgbw ColorRgbw::YELLOW= { 255, 255, 0, 0 }; +ColorRgbw ColorRgbw::WHITE = { 0, 0, 0, 255 }; diff --git a/libsrc/utils/RgbToRgbw.cpp b/libsrc/utils/RgbToRgbw.cpp new file mode 100644 index 00000000..f71fa4fe --- /dev/null +++ b/libsrc/utils/RgbToRgbw.cpp @@ -0,0 +1,24 @@ +#include +#include + +void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, std::string _whiteAlgorithm) { + if (_whiteAlgorithm == "subtract_minimum") { + output->white = std::min(input.red, input.green); + output->white = std::min(output->white, input.blue); + output->red = input.red - output->white; + output->green = input.green - output->white; + output->blue = input.blue - output->white; + } + else if (_whiteAlgorithm == "sub_min_warm_adjust") { + } + else if ( (_whiteAlgorithm == "") || (_whiteAlgorithm == "white_off") ) { + output->red = input.red; + output->green = input.green; + output->blue = input.blue; + output->white = 0; + } + else { + std::cout << "ERROR: unknown whiteAlgorithm " << _whiteAlgorithm << std::endl; + } +} +