From 954112a88e49e11994fd062ebeeba5c461430be7 Mon Sep 17 00:00:00 2001 From: LordGrey <48840279+Lord-Grey@users.noreply.github.com> Date: Thu, 28 Oct 2021 18:54:54 +0100 Subject: [PATCH] APA102 protocol fix (#1352) (#1361) * Fix APA102 protocoll * Minor clean-ups * Revert updates --- bin/create_all_releases.sh | 6 ++- libsrc/leddevice/LedDevice.cpp | 1 + libsrc/leddevice/dev_spi/LedDeviceAPA102.cpp | 51 ++++++++++++++------ libsrc/leddevice/dev_spi/LedDeviceAPA102.h | 15 ++++++ libsrc/leddevice/dev_spi/LedDeviceSK9822.cpp | 4 -- libsrc/leddevice/dev_spi/ProviderSpi.cpp | 2 + libsrc/leddevice/schemas/schema-apa102.json | 14 +++--- 7 files changed, 65 insertions(+), 28 deletions(-) diff --git a/bin/create_all_releases.sh b/bin/create_all_releases.sh index cf3991e1..a80de1cc 100755 --- a/bin/create_all_releases.sh +++ b/bin/create_all_releases.sh @@ -16,9 +16,11 @@ make_release() mkdir -p deploy/${RELEASE} cd build-${RELEASE} + cmake -DCMAKE_INSTALL_PREFIX=/usr -DPLATFORM=${PLATFORM} $@ -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 + #cmake -DCMAKE_INSTALL_PREFIX=/usr -DPLATFORM=${PLATFORM} $@ -DCMAKE_BUILD_TYPE=Debug .. || exit 1 make -j $(nproc) || exit 1 - #strip bin/* + strip bin/* make package -j $(nproc) mv Hyperion-* ../deploy/${RELEASE} cd .. @@ -30,7 +32,7 @@ CMAKE_FLATC_FLAG="-DIMPORT_FLATC=../build-x86x64/flatc_export.cmake" make_release x86x64 x11 #make_release x32 x11 -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-x32.cmake" ${CMAKE_PROTOC_FLAG} ${CMAKE_FLATC_FLAG} -make_release rpi rpi -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} ${CMAKE_FLATC_FLAG} +#make_release rpi rpi -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} ${CMAKE_FLATC_FLAG} #make_release wetek wetek -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} ${CMAKE_FLATC_FLAG} #make_release imx6 imx6 -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-imx6.cmake" ${CMAKE_PROTOC_FLAG} ${CMAKE_FLATC_FLAG} diff --git a/libsrc/leddevice/LedDevice.cpp b/libsrc/leddevice/LedDevice.cpp index 27dc3e8c..ce22f2ab 100644 --- a/libsrc/leddevice/LedDevice.cpp +++ b/libsrc/leddevice/LedDevice.cpp @@ -275,6 +275,7 @@ bool LedDevice::switchOn() if ( powerOn() ) { _isOn = true; + _isInSwitchOff = false; rc = true; } } diff --git a/libsrc/leddevice/dev_spi/LedDeviceAPA102.cpp b/libsrc/leddevice/dev_spi/LedDeviceAPA102.cpp index bb4c3842..43f50a27 100644 --- a/libsrc/leddevice/dev_spi/LedDeviceAPA102.cpp +++ b/libsrc/leddevice/dev_spi/LedDeviceAPA102.cpp @@ -1,8 +1,19 @@ #include "LedDeviceAPA102.h" +// Constants +namespace { + +/// The value that determines the higher bits of the APA102 brightness control field +const int APA102_LEDFRAME_UPPER_BITS = 0xE0; + +} //End of constants + + LedDeviceAPA102::LedDeviceAPA102(const QJsonObject &deviceConfig) : ProviderSpi(deviceConfig) { + // Overwrite non supported/required features + _latchTime_ms = 0; } LedDevice* LedDeviceAPA102::construct(const QJsonObject &deviceConfig) @@ -17,32 +28,44 @@ bool LedDeviceAPA102::init(const QJsonObject &deviceConfig) // Initialise sub-class if ( ProviderSpi::init(deviceConfig) ) { + _brightnessControlMaxLevel = deviceConfig["brightnessControlMaxLevel"].toInt(APA102_BRIGHTNESS_MAX_LEVEL); + Info(_log, "[%s] Setting maximum brightness to [%d] = %d%%", QSTRING_CSTR(_activeDeviceType), _brightnessControlMaxLevel, _brightnessControlMaxLevel * 100 / APA102_BRIGHTNESS_MAX_LEVEL); const unsigned int startFrameSize = 4; - const unsigned int endFrameSize = qMax(((_ledCount + 15) / 16), 4); + //Endframe, add additional 4 bytes to cover SK9922 Reset frame (in case SK9922 were sold as AP102) - has no effect on APA102 + const unsigned int endFrameSize = (_ledCount/32) * 4 + 4; const unsigned int APAbufferSize = (_ledCount * 4) + startFrameSize + endFrameSize; - _ledBuffer.resize(APAbufferSize, 0xFF); - _ledBuffer[0] = 0x00; - _ledBuffer[1] = 0x00; - _ledBuffer[2] = 0x00; - _ledBuffer[3] = 0x00; + _ledBuffer.resize(APAbufferSize, 0x00); isInitOK = true; - } return isInitOK; } +void LedDeviceAPA102::bufferWithBrightness(std::vector &txBuf, const std::vector & ledValues, const int brightness) { + const int ledCount = static_cast(_ledCount); + + for (int iLed = 0; iLed < ledCount; ++iLed) + { + const ColorRgb &rgb = ledValues[iLed]; + const uint8_t red = rgb.red; + const uint8_t green = rgb.green; + const uint8_t blue = rgb.blue; + + /// The LED index in the buffer + const int b = 4 + iLed * 4; + + txBuf[b + 0] = brightness | APA102_LEDFRAME_UPPER_BITS; + txBuf[b + 1] = blue; + txBuf[b + 2] = green; + txBuf[b + 3] = red; + } +} + int LedDeviceAPA102::write(const std::vector &ledValues) { - for (signed iLed=0; iLed < static_cast( _ledCount); ++iLed) { - const ColorRgb& rgb = ledValues[iLed]; - _ledBuffer[4+iLed*4] = 0xFF; - _ledBuffer[4+iLed*4+1] = rgb.red; - _ledBuffer[4+iLed*4+2] = rgb.green; - _ledBuffer[4+iLed*4+3] = rgb.blue; - } + this->bufferWithBrightness(_ledBuffer, ledValues, _brightnessControlMaxLevel); return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } diff --git a/libsrc/leddevice/dev_spi/LedDeviceAPA102.h b/libsrc/leddevice/dev_spi/LedDeviceAPA102.h index 712ed75d..99a72eaf 100644 --- a/libsrc/leddevice/dev_spi/LedDeviceAPA102.h +++ b/libsrc/leddevice/dev_spi/LedDeviceAPA102.h @@ -4,6 +4,9 @@ // hyperion includes #include "ProviderSpi.h" +/// The maximal level supported by the APA brightness control field, 31 +const int APA102_BRIGHTNESS_MAX_LEVEL = 31; + /// /// Implementation of the LedDevice interface for writing to APA102 led device. /// @@ -43,6 +46,18 @@ private: /// @return Zero on success, else negative /// int write(const std::vector & ledValues) override; + + /// + /// @brief Writes the RGB-Color values to the SPI Tx buffer setting considering a given brightness level + /// + /// @param[in,out] txBuf The packed spi transfer buffer of the LED's color values + /// @param[in] ledValues The RGB-color per LED + /// @param[in] brightness The current brightness level 1 .. 31 + /// + void bufferWithBrightness(std::vector &txBuf, const std::vector & ledValues, const int brightness = APA102_BRIGHTNESS_MAX_LEVEL); + + /// The brighness level. Possibile values 1 .. 31. + int _brightnessControlMaxLevel; }; #endif // LEDEVICEAPA102_H diff --git a/libsrc/leddevice/dev_spi/LedDeviceSK9822.cpp b/libsrc/leddevice/dev_spi/LedDeviceSK9822.cpp index 808263d1..4562ac1b 100644 --- a/libsrc/leddevice/dev_spi/LedDeviceSK9822.cpp +++ b/libsrc/leddevice/dev_spi/LedDeviceSK9822.cpp @@ -39,10 +39,6 @@ bool LedDeviceSK9822::init(const QJsonObject &deviceConfig) _ledBuffer.resize(0, 0x00); _ledBuffer.resize(bufferSize, 0x00); - //_ledBuffer[0] = 0x00; - //_ledBuffer[1] = 0x00; - //_ledBuffer[2] = 0x00; - //_ledBuffer[3] = 0x00; isInitOK = true; } diff --git a/libsrc/leddevice/dev_spi/ProviderSpi.cpp b/libsrc/leddevice/dev_spi/ProviderSpi.cpp index f57c54f9..f0ce55c7 100644 --- a/libsrc/leddevice/dev_spi/ProviderSpi.cpp +++ b/libsrc/leddevice/dev_spi/ProviderSpi.cpp @@ -37,6 +37,7 @@ ProviderSpi::ProviderSpi(const QJsonObject &deviceConfig) { memset(&_spi, 0, sizeof(_spi)); _latchTime_ms = 1; + _isInSwitchOff = false; } ProviderSpi::~ProviderSpi() @@ -68,6 +69,7 @@ int ProviderSpi::open() int retval = -1; QString errortext; _isDeviceReady = false; + _isInSwitchOff = false; const int bitsPerWord = 8; diff --git a/libsrc/leddevice/schemas/schema-apa102.json b/libsrc/leddevice/schemas/schema-apa102.json index ec8f08fc..43bc649c 100644 --- a/libsrc/leddevice/schemas/schema-apa102.json +++ b/libsrc/leddevice/schemas/schema-apa102.json @@ -19,20 +19,18 @@ "default": false, "propertyOrder" : 3 }, - "latchTime": { + "brightnessControlMaxLevel": { "type": "integer", - "title":"edt_dev_spec_latchtime_title", - "default": 0, - "append" : "edt_append_ms", - "minimum": 0, - "maximum": 1000, - "access" : "expert", + "title":"edt_conf_color_brightness_title", + "default": 31, + "minimum": 1, + "maximum": 31, "propertyOrder" : 4 }, "rewriteTime": { "type": "integer", "title":"edt_dev_general_rewriteTime_title", - "default": 1000, + "default": 0, "append" : "edt_append_ms", "minimum": 0, "access" : "expert",