From 5a9e05ce5ba1b7c92b015551a10b0a2aca914cd1 Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Sun, 23 Aug 2020 16:10:16 +0200 Subject: [PATCH 1/9] make feature list clearer added hardware lighting mode close #172 --- README.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c5533061..c287b230 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ _This is not an official corsair project._ ## Features * Add support of Corsair DIY device protocol to Arduino. * Control LEDs with the [Corsair iCUE software](https://www.corsair.com/icue). -* Easy to use with [FastLED](http://fastled.io/). -* [Supported LED chipsets](https://github.com/FastLED/FastLED/wiki/Overview#chipsets). (e.g. WS2812B, WS2801) +* [Support common LED chipsets](https://github.com/FastLED/FastLED/wiki/Overview#chipsets). (e.g. WS2812B, WS2801) +* Support [FastLED](http://fastled.io/). * Supported platform: Arduino AVR -* Persistent settings for use without a USB connection. +* Hardware Lighting mode. * Use multiple devices at the same time. * Repeat or scale LED channels to arbitrary size. @@ -91,7 +91,9 @@ Now you can create lighting effects in the "Lighting Channel #" tabs. - [API Documentation](https://legion2.github.io/CorsairLightingProtocol/) - [How it works](#how-it-works) - [Use of multiple devices](#use-of-multiple-devices) -- [Repeat or scale LED channel](#repeat-or-scale-led-channel) +- [Repeat or scale LED channels](#repeat-or-scale-led-channels) +- [Increase the Brightness of the LEDs](#increase-the-brightness-of-the-leds) +- [Hardware Lighting mode](#hardware-lighting-mode) ## How it works This library uses the USB HID interface of the ATmega32U4. @@ -128,10 +130,9 @@ Upload the DeviceIDTool sketch and then open the Serial monitor with baudrate 11 The tool displays the current DeviceID, you can type in a new DeviceID that is saved on the Arduino. After that, you can upload another sketch. -## Repeat or scale LED channel +## Repeat or scale LED channels You can repeat or scale LED channel controlled by iCUE onto physical LED strips. -This is very useful if you have very long LED strips that are longer than 60/96/135 LEDs. -This is the maximum number iCUE supports. +This is very useful if you have very long LED strips that are longer than 60/96/135 LEDs, which is the maximum number iCUE supports. To repeat or scale a LED channel you must apply the `CLP::repeat` or the `CLP:scale` function in the update hook of the FastLEDController. See the [RepeatAndScale](examples/RepeatAndScale/RepeatAndScale.ino) example for the complete code. @@ -156,6 +157,13 @@ ledController.onUpdateHook(0, []() { }); ``` +## Hardware Lighting mode +The [Hardware Lighting mode](https://forum.corsair.com/v3/showthread.php?t=182874) can be configured in iCUE. +It allows you the set lighting effects that will be active when iCUE **is not** running. +This is the case when the PC is off, in sleep mode, booting or the user is logged out. +So if you want to have lighing effects in all these situations, use the Hardware Lighting mode. +If you don't want it, configure a static black color. + # License This project is licensed under the Apache 2.0 License. From 1091c4750f5ce1cd4ef35aee3bef6a25e6fb3fe4 Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Sun, 30 Aug 2020 18:07:16 +0200 Subject: [PATCH 2/9] added FPS counter based on simple Arduino loop "FPS" counter - v1.1 by Michael Braverman --- .../AdditionalFeatures/AdditionalFeatures.ino | 2 ++ examples/DebugSketch/DebugSketch.ino | 2 ++ src/CLPUtils.cpp | 16 ++++++++++++++++ src/CLPUtils.h | 8 ++++++++ 4 files changed, 28 insertions(+) diff --git a/examples/AdditionalFeatures/AdditionalFeatures.ino b/examples/AdditionalFeatures/AdditionalFeatures.ino index 5ba768c6..c928b682 100644 --- a/examples/AdditionalFeatures/AdditionalFeatures.ino +++ b/examples/AdditionalFeatures/AdditionalFeatures.ino @@ -58,5 +58,7 @@ void loop() { if (ledController.updateLEDs()) { FastLED.show(); + Serial.print(F("FPS: ")); + CLP::printFps(5000); } } diff --git a/examples/DebugSketch/DebugSketch.ino b/examples/DebugSketch/DebugSketch.ino index 12b230bc..c807fb04 100644 --- a/examples/DebugSketch/DebugSketch.ino +++ b/examples/DebugSketch/DebugSketch.ino @@ -48,6 +48,8 @@ void loop() { if (ledController.updateLEDs()) { if (printUpdate) Serial.println(F("updateLEDs")); FastLED.show(); + Serial.print(F("FPS: ")); + CLP::printFps(5000); } if (Serial.available()) { diff --git a/src/CLPUtils.cpp b/src/CLPUtils.cpp index 5140ddea..5a5cfc34 100644 --- a/src/CLPUtils.cpp +++ b/src/CLPUtils.cpp @@ -47,3 +47,19 @@ void CLP::printDeviceID(const uint8_t* deviceId) { if (i < 3) Serial.print(F(" ")); } } + +void CLP::printFps(const int interval) { + // Create static variables so that the code and variables can + // all be declared inside a function + static unsigned long lastMillis; + static unsigned long frameCount; + + unsigned long now = millis(); + frameCount++; + if (now - lastMillis >= interval) { + unsigned int framesPerSecond = frameCount / interval; + Serial.println(framesPerSecond); + frameCount = 0; + lastMillis = now; + } +} diff --git a/src/CLPUtils.h b/src/CLPUtils.h index 43b2788c..005d0f3e 100644 --- a/src/CLPUtils.h +++ b/src/CLPUtils.h @@ -61,4 +61,12 @@ void disableBuildInLEDs(); * @param deviceId the device id to print */ void printDeviceID(const uint8_t* deviceId); + +/* + * Measure and print the framerate at the given interval in milliseconds. The higher this value the more precise the + * result will be. This function should be called after FastLED.show() to count the FPS. + * + * @param interval the measurement interval in milliseconds + */ +void printFps(const int interval); } // namespace CLP From a4eb1ad88ef45e806c80c465943cb45909220445 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Sep 2020 08:57:32 +0200 Subject: [PATCH 3/9] Bump DoozyX/clang-format-lint-action from v0.8 to v0.9 (#177) Bumps [DoozyX/clang-format-lint-action](https://github.com/DoozyX/clang-format-lint-action) from v0.8 to v0.9. - [Release notes](https://github.com/DoozyX/clang-format-lint-action/releases) - [Commits](https://github.com/DoozyX/clang-format-lint-action/compare/v0.8...e885c632a5ce4da2198c0739e9b499b18c55187f) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 10908086..f556146b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,13 +9,13 @@ jobs: steps: - uses: actions/checkout@v2 - name: Check src format - uses: DoozyX/clang-format-lint-action@v0.8 + uses: DoozyX/clang-format-lint-action@v0.9 with: source: './src' extensions: 'h,cpp' clangFormatVersion: 9 - name: Check examples format - uses: DoozyX/clang-format-lint-action@v0.8 + uses: DoozyX/clang-format-lint-action@v0.9 with: source: './examples' extensions: 'h,cpp,ino' From 7e48b3896b9e13214b2486899b9ec67155d1b419 Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Wed, 2 Sep 2020 09:21:04 +0200 Subject: [PATCH 4/9] fixed fps counter --- examples/AdditionalFeatures/AdditionalFeatures.ino | 1 - examples/DebugSketch/DebugSketch.ino | 1 - src/CLPUtils.cpp | 5 +++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/AdditionalFeatures/AdditionalFeatures.ino b/examples/AdditionalFeatures/AdditionalFeatures.ino index c928b682..803b6f40 100644 --- a/examples/AdditionalFeatures/AdditionalFeatures.ino +++ b/examples/AdditionalFeatures/AdditionalFeatures.ino @@ -58,7 +58,6 @@ void loop() { if (ledController.updateLEDs()) { FastLED.show(); - Serial.print(F("FPS: ")); CLP::printFps(5000); } } diff --git a/examples/DebugSketch/DebugSketch.ino b/examples/DebugSketch/DebugSketch.ino index c807fb04..1a7281df 100644 --- a/examples/DebugSketch/DebugSketch.ino +++ b/examples/DebugSketch/DebugSketch.ino @@ -48,7 +48,6 @@ void loop() { if (ledController.updateLEDs()) { if (printUpdate) Serial.println(F("updateLEDs")); FastLED.show(); - Serial.print(F("FPS: ")); CLP::printFps(5000); } diff --git a/src/CLPUtils.cpp b/src/CLPUtils.cpp index 5a5cfc34..fbde0dd6 100644 --- a/src/CLPUtils.cpp +++ b/src/CLPUtils.cpp @@ -57,8 +57,9 @@ void CLP::printFps(const int interval) { unsigned long now = millis(); frameCount++; if (now - lastMillis >= interval) { - unsigned int framesPerSecond = frameCount / interval; - Serial.println(framesPerSecond); + double framesPerSecond = (frameCount * 1000.0) / interval; + Serial.print(F("FPS: ")); + Serial.println(framesPerSecond, 1); frameCount = 0; lastMillis = now; } From 3e91580f7776a767197352a416d0c12899130455 Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Wed, 2 Sep 2020 22:52:13 +0200 Subject: [PATCH 5/9] added note to fixIcueBrightness close #175 fixIcueBrightness should only be used with LS100 and LT100 --- README.md | 5 +++-- examples/AdditionalFeatures/AdditionalFeatures.ino | 6 ------ examples/AmbientBacklight/AmbientBacklight.ino | 2 ++ src/FastLEDControllerUtils.h | 5 +++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c287b230..12a299ba 100644 --- a/README.md +++ b/README.md @@ -147,10 +147,11 @@ For both functions it's **important**, that the CRGB arrays have at least the le This means if your LED channel from iCUE has 50 LEDs and you use the `repeat` function to control 100 physical LEDs you MUST declare the CRGB array at least with a length of 100. ## Increase the Brightness of the LEDs -By default iCUE only uses 50% of the LEDs brightness even if you set the brightness to max in the iCUE Device Settings. +When using LS100 or LT100 iCUE only uses 50% of the LEDs brightness even if you set the brightness to max in the iCUE Device Settings. But there are good news, we can increase the brightness with the Arduino so we can use the full brightness of our LEDs. -Add the `CLP::fixIcueBrightness` function to the `onUpdateHook` in the setup function as shown in the [example](examples/AdditionalFeatures/AdditionalFeatures.ino). +Add the `CLP::fixIcueBrightness` function to the `onUpdateHook` in the setup function as shown in the [example](examples/AmbientBacklight/AmbientBacklight.ino). If there are multiple functions called in `onUpdateHook`, `fixIcueBrightness` should be the first. +Only use this function with LS100 and LT100 devices! ```C++ ledController.onUpdateHook(0, []() { CLP::fixIcueBrightness(&ledController, 0); diff --git a/examples/AdditionalFeatures/AdditionalFeatures.ino b/examples/AdditionalFeatures/AdditionalFeatures.ino index 803b6f40..77b8af60 100644 --- a/examples/AdditionalFeatures/AdditionalFeatures.ino +++ b/examples/AdditionalFeatures/AdditionalFeatures.ino @@ -45,12 +45,6 @@ void setup() { FastLED.addLeds(ledsChannel2, 60); ledController.addLEDs(0, ledsChannel1, 60); ledController.addLEDs(1, ledsChannel2, 60); - - // modify the RGB values before they are shown on the LED strip - ledController.onUpdateHook(0, []() { - // increase the brightness of channel 1 when using iCUE, because iCUE only set brightness to max 50% - CLP::fixIcueBrightness(&ledController, 0); - }); } void loop() { diff --git a/examples/AmbientBacklight/AmbientBacklight.ino b/examples/AmbientBacklight/AmbientBacklight.ino index 2ba3548e..93fedd65 100644 --- a/examples/AmbientBacklight/AmbientBacklight.ino +++ b/examples/AmbientBacklight/AmbientBacklight.ino @@ -34,6 +34,8 @@ void setup() { ledController.addLEDs(0, ledsChannel1, 84); ledController.addLEDs(1, ledsChannel2, 105); ledController.onUpdateHook(0, []() { + // increase the brightness of channel 1 when using iCUE, because iCUE only set brightness to max 50% + CLP::fixIcueBrightness(&ledController, 0); // gamma correction with gamma value 2.0. Use napplyGamma_video for other gamma values. CLP::gammaCorrection(&ledController, 0); // napplyGamma_video(ledsChannel1, 84, 2.2); diff --git a/src/FastLEDControllerUtils.h b/src/FastLEDControllerUtils.h index f694331e..54db2e68 100644 --- a/src/FastLEDControllerUtils.h +++ b/src/FastLEDControllerUtils.h @@ -91,8 +91,9 @@ void reverse(FastLEDController* controller, uint8_t channelIndex); void gammaCorrection(FastLEDController* controller, uint8_t channelIndex); /** - * Increase the brightness of a LED channel when using iCUE Software lighting, because iCUE only send the RGB value in - * the range (0 - 127) which is only 50% of max possible brightness. This function doubles the received RGB value. + * Increase the brightness of a LED channel when using LS100 and LT100 with iCUE Software lighting, because iCUE only + * send the RGB value in the range (0 - 127) which is only 50% of max possible brightness. This function doubles the + * received RGB value. Only use this function with LS100 and LT100. * * @param controller the FastLEDController controlling the LEDs * @param channelIndex the index of the channel From f71caadf4986ea5d53b2cac2264b726d193a85de Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Mon, 7 Sep 2020 20:25:10 +0200 Subject: [PATCH 6/9] added tests for scaling long strips --- examples/UnitTests/UnitTests.ino | 56 +++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/examples/UnitTests/UnitTests.ino b/examples/UnitTests/UnitTests.ino index 7704ba5a..383b34da 100644 --- a/examples/UnitTests/UnitTests.ino +++ b/examples/UnitTests/UnitTests.ino @@ -86,6 +86,19 @@ testF(FastLEDControllerTest, simpleScaleIdentity) { } } +testF(FastLEDControllerTest, scaleLongStrip) { + CRGB leds[41]; + FastLEDController ledController(false); + fill_solid(leds, 41, CRGB::Black); + ledController.addLEDs(0, leds, 27); + + fill_solid(leds, 27, CRGB::White); + CLP::scale(&ledController, 0, 41); + for (int i = 0; i < 41; i++) { + assertCRGB(leds[i], CRGB::White); + } +} + testF(FastLEDControllerTest, LT100) { CRGB leds[30]; FastLEDController ledController(false); @@ -109,7 +122,7 @@ testF(FastLEDControllerTest, singleSegmentScaleUp) { CRGB leds[20]; FastLEDController ledController(false); fill_solid(leds, 20, CRGB::Black); - ledController.addLEDs(0, leds, 20); + ledController.addLEDs(0, leds, 10); fill_solid(leds, 10, CRGB::White); CLP::SegmentScaling segments[] = {{10, 20}}; @@ -256,6 +269,47 @@ testF(FastLEDControllerTest, SegmentScaleMixInverted) { } } +testF(FastLEDControllerTest, SegmentScaleMonitor) { + CRGB leds[130]; + FastLEDController ledController(false); + fill_solid(leds, 130, CRGB::Black); + ledController.addLEDs(0, leds, 84); + + fill_solid(leds, 15, CRGB::White); + fill_solid(leds + 15, 27, CRGB::Red); + fill_solid(leds + 42, 15, CRGB::Blue); + fill_solid(leds + 57, 27, CRGB::Green); + CLP::SegmentScaling segments[] = {{15, 24}, {27, 41}, {15, 24}, {27, 41}}; + CLP::scaleSegments(&ledController, 0, segments, 4); + + for (int i = 0; i < 24; i++) { + assertCRGB(leds[i], CRGB::White); + } + for (int i = 24; i < 65; i++) { + assertCRGB(leds[i], CRGB::Red); + } + for (int i = 65; i < 89; i++) { + assertCRGB(leds[i], CRGB::Red); + } + for (int i = 89; i < 130; i++) { + assertCRGB(leds[i], CRGB::Green); + } +} + +testF(FastLEDControllerTest, SegmentScaleLongStrip) { + CRGB leds[41]; + FastLEDController ledController(false); + fill_solid(leds, 41, CRGB::Black); + ledController.addLEDs(0, leds, 27); + + fill_solid(leds, 27, CRGB::White); + CLP::SegmentScaling segments[] = {{27, 41}}; + CLP::scaleSegments(&ledController, 0, segments, 1); + for (int i = 0; i < 41; i++) { + assertCRGB(leds[i], CRGB::White); + } +} + void setup() { delay(1000); Serial.begin(115200); From 3b66fbfc6f490a0d4499724e3a84e6892e333e34 Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Tue, 8 Sep 2020 21:18:54 +0200 Subject: [PATCH 7/9] added assertCRGBArray to unit test --- examples/UnitTests/UnitTests.ino | 140 +++++++++++-------------------- 1 file changed, 50 insertions(+), 90 deletions(-) diff --git a/examples/UnitTests/UnitTests.ino b/examples/UnitTests/UnitTests.ino index 383b34da..9f8452c4 100644 --- a/examples/UnitTests/UnitTests.ino +++ b/examples/UnitTests/UnitTests.ino @@ -28,6 +28,11 @@ protected: assertEqual(actual.g, expected.g); assertEqual(actual.b, expected.b); } + void assertCRGBArray(const CRGB* const leds, int from, int to, const CRGB& expected) { + for (int i = from; i <= to; i++) { + assertCRGB(leds[i], expected); + } + } }; test(getLEDs) { @@ -47,9 +52,7 @@ testF(FastLEDControllerTest, simpleScaleUp) { fill_solid(leds, 10, CRGB::White); CLP::scale(&ledController, 0, 20); - for (int i = 0; i < 10; i++) { - assertCRGB(leds[i], CRGB::White); - } + assertCRGBArray(leds, 0, 9, CRGB::White); } testF(FastLEDControllerTest, simpleScaleDown) { @@ -61,12 +64,21 @@ testF(FastLEDControllerTest, simpleScaleDown) { fill_solid(leds, 10, CRGB::White); CLP::scale(&ledController, 0, 10); - for (int i = 0; i < 5; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 5; i < 10; i++) { - assertCRGB(leds[i], CRGB::Black); - } + assertCRGBArray(leds, 0, 4, CRGB::White); + assertCRGBArray(leds, 5, 9, CRGB::Black); +} + +testF(FastLEDControllerTest, simpleScaleDownBoundaries) { + CRGB leds[20]; + FastLEDController ledController(false); + fill_solid(leds, 20, CRGB::Black); + ledController.addLEDs(0, leds, 20); + + fill_solid(leds, 1, CRGB::White); + CLP::scale(&ledController, 0, 10); + + assertCRGBArray(leds, 0, 0, CRGB::White); + assertCRGBArray(leds, 1, 9, CRGB::Black); } testF(FastLEDControllerTest, simpleScaleIdentity) { @@ -78,12 +90,8 @@ testF(FastLEDControllerTest, simpleScaleIdentity) { fill_solid(leds, 10, CRGB::White); CLP::scale(&ledController, 0, 10); - for (int i = 0; i < 10; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 10; i < 20; i++) { - assertCRGB(leds[i], CRGB::Black); - } + assertCRGBArray(leds, 0, 9, CRGB::White); + assertCRGBArray(leds, 10, 19, CRGB::Black); } testF(FastLEDControllerTest, scaleLongStrip) { @@ -94,9 +102,8 @@ testF(FastLEDControllerTest, scaleLongStrip) { fill_solid(leds, 27, CRGB::White); CLP::scale(&ledController, 0, 41); - for (int i = 0; i < 41; i++) { - assertCRGB(leds[i], CRGB::White); - } + + assertCRGBArray(leds, 0, 40, CRGB::White); } testF(FastLEDControllerTest, LT100) { @@ -110,12 +117,8 @@ testF(FastLEDControllerTest, LT100) { CLP::SegmentScaling segments[2] = {{1, 4}, {26, 26}}; CLP::scaleSegments(&ledController, 0, segments, 2); - for (int i = 0; i < 4; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 4; i < 30; i++) { - assertCRGB(leds[i], CRGB::Blue); - } + assertCRGBArray(leds, 0, 3, CRGB::White); + assertCRGBArray(leds, 4, 29, CRGB::Blue); } testF(FastLEDControllerTest, singleSegmentScaleUp) { @@ -128,9 +131,7 @@ testF(FastLEDControllerTest, singleSegmentScaleUp) { CLP::SegmentScaling segments[] = {{10, 20}}; CLP::scaleSegments(&ledController, 0, segments, 1); - for (int i = 0; i < 20; i++) { - assertCRGB(leds[i], CRGB::White); - } + assertCRGBArray(leds, 0, 19, CRGB::White); } testF(FastLEDControllerTest, multiScaleUp) { @@ -143,12 +144,8 @@ testF(FastLEDControllerTest, multiScaleUp) { CLP::SegmentScaling segments[] = {{5, 10}, {5, 20}}; CLP::scaleSegments(&ledController, 0, segments, 2); - for (int i = 0; i < 10; i++) { - assertCRGB(leds[i], CRGB::Black); - } - for (int i = 10; i < 30; i++) { - assertCRGB(leds[i], CRGB::White); - } + assertCRGBArray(leds, 0, 9, CRGB::Black); + assertCRGBArray(leds, 10, 29, CRGB::White); } testF(FastLEDControllerTest, multiScaleDown) { @@ -161,12 +158,8 @@ testF(FastLEDControllerTest, multiScaleDown) { CLP::SegmentScaling segments[] = {{10, 5}, {20, 5}}; CLP::scaleSegments(&ledController, 0, segments, 2); - for (int i = 0; i < 5; i++) { - assertCRGB(leds[i], CRGB::Black); - } - for (int i = 5; i < 10; i++) { - assertCRGB(leds[i], CRGB::White); - } + assertCRGBArray(leds, 0, 4, CRGB::Black); + assertCRGBArray(leds, 5, 9, CRGB::White); } testF(FastLEDControllerTest, singleSegmentScaleDown) { @@ -179,12 +172,8 @@ testF(FastLEDControllerTest, singleSegmentScaleDown) { CLP::SegmentScaling segments[] = {{20, 10}}; CLP::scaleSegments(&ledController, 0, segments, 1); - for (int i = 0; i < 5; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 5; i < 10; i++) { - assertCRGB(leds[i], CRGB::Black); - } + assertCRGBArray(leds, 0, 4, CRGB::White); + assertCRGBArray(leds, 5, 9, CRGB::Black); } testF(FastLEDControllerTest, SegmentScaleOverlap) { @@ -197,12 +186,8 @@ testF(FastLEDControllerTest, SegmentScaleOverlap) { CLP::SegmentScaling segments[] = {{5, 10}, {10, 5}}; CLP::scaleSegments(&ledController, 0, segments, 2); - for (int i = 0; i < 10; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 10; i < 15; i++) { - assertCRGB(leds[i], CRGB::Black); - } + assertCRGBArray(leds, 0, 9, CRGB::White); + assertCRGBArray(leds, 10, 14, CRGB::Black); } testF(FastLEDControllerTest, SegmentScaleOverlapInverted) { @@ -215,12 +200,8 @@ testF(FastLEDControllerTest, SegmentScaleOverlapInverted) { CLP::SegmentScaling segments[] = {{10, 5}, {5, 10}}; CLP::scaleSegments(&ledController, 0, segments, 2); - for (int i = 0; i < 5; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 5; i < 15; i++) { - assertCRGB(leds[i], CRGB::Black); - } + assertCRGBArray(leds, 0, 4, CRGB::White); + assertCRGBArray(leds, 5, 14, CRGB::Black); } testF(FastLEDControllerTest, SegmentScaleMix) { @@ -235,15 +216,9 @@ testF(FastLEDControllerTest, SegmentScaleMix) { CLP::SegmentScaling segments[] = {{5, 10}, {20, 5}, {5, 10}}; CLP::scaleSegments(&ledController, 0, segments, 3); - for (int i = 0; i < 10; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 10; i < 15; i++) { - assertCRGB(leds[i], CRGB::Red); - } - for (int i = 15; i < 25; i++) { - assertCRGB(leds[i], CRGB::Blue); - } + assertCRGBArray(leds, 0, 9, CRGB::White); + assertCRGBArray(leds, 10, 14, CRGB::Red); + assertCRGBArray(leds, 15, 24, CRGB::Blue); } testF(FastLEDControllerTest, SegmentScaleMixInverted) { @@ -258,15 +233,9 @@ testF(FastLEDControllerTest, SegmentScaleMixInverted) { CLP::SegmentScaling segments[] = {{10, 5}, {5, 20}, {10, 5}}; CLP::scaleSegments(&ledController, 0, segments, 3); - for (int i = 0; i < 5; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 5; i < 25; i++) { - assertCRGB(leds[i], CRGB::Red); - } - for (int i = 25; i < 30; i++) { - assertCRGB(leds[i], CRGB::Blue); - } + assertCRGBArray(leds, 0, 4, CRGB::White); + assertCRGBArray(leds, 5, 24, CRGB::Red); + assertCRGBArray(leds, 25, 29, CRGB::Blue); } testF(FastLEDControllerTest, SegmentScaleMonitor) { @@ -282,18 +251,10 @@ testF(FastLEDControllerTest, SegmentScaleMonitor) { CLP::SegmentScaling segments[] = {{15, 24}, {27, 41}, {15, 24}, {27, 41}}; CLP::scaleSegments(&ledController, 0, segments, 4); - for (int i = 0; i < 24; i++) { - assertCRGB(leds[i], CRGB::White); - } - for (int i = 24; i < 65; i++) { - assertCRGB(leds[i], CRGB::Red); - } - for (int i = 65; i < 89; i++) { - assertCRGB(leds[i], CRGB::Red); - } - for (int i = 89; i < 130; i++) { - assertCRGB(leds[i], CRGB::Green); - } + assertCRGBArray(leds, 0, 23, CRGB::White); + assertCRGBArray(leds, 24, 64, CRGB::Red); + assertCRGBArray(leds, 65, 88, CRGB::Blue); + assertCRGBArray(leds, 89, 129, CRGB::Green); } testF(FastLEDControllerTest, SegmentScaleLongStrip) { @@ -305,9 +266,8 @@ testF(FastLEDControllerTest, SegmentScaleLongStrip) { fill_solid(leds, 27, CRGB::White); CLP::SegmentScaling segments[] = {{27, 41}}; CLP::scaleSegments(&ledController, 0, segments, 1); - for (int i = 0; i < 41; i++) { - assertCRGB(leds[i], CRGB::White); - } + + assertCRGBArray(leds, 0, 40, CRGB::White); } void setup() { From a5aa8f49c552cb2ba1654bf9b26fce99685479b6 Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Tue, 8 Sep 2020 21:55:57 +0200 Subject: [PATCH 8/9] fixed the scaling boundary conditions close #181 changed the scaling factor and use round instead of ceil to mitigate floating point errors --- examples/UnitTests/UnitTests.ino | 8 +++++--- src/FastLEDControllerUtils.cpp | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/examples/UnitTests/UnitTests.ino b/examples/UnitTests/UnitTests.ino index 9f8452c4..57a33458 100644 --- a/examples/UnitTests/UnitTests.ino +++ b/examples/UnitTests/UnitTests.ino @@ -74,11 +74,13 @@ testF(FastLEDControllerTest, simpleScaleDownBoundaries) { fill_solid(leds, 20, CRGB::Black); ledController.addLEDs(0, leds, 20); - fill_solid(leds, 1, CRGB::White); - CLP::scale(&ledController, 0, 10); + leds[0] = CRGB::White; + leds[19] = CRGB::Red; + CLP::scale(&ledController, 0, 5); assertCRGBArray(leds, 0, 0, CRGB::White); - assertCRGBArray(leds, 1, 9, CRGB::Black); + assertCRGBArray(leds, 1, 3, CRGB::Black); + assertCRGBArray(leds, 4, 4, CRGB::Red); } testF(FastLEDControllerTest, simpleScaleIdentity) { diff --git a/src/FastLEDControllerUtils.cpp b/src/FastLEDControllerUtils.cpp index 4f867f85..270f841b 100644 --- a/src/FastLEDControllerUtils.cpp +++ b/src/FastLEDControllerUtils.cpp @@ -34,26 +34,26 @@ void CLP::transformLLFanToStrip(FastLEDController* controller, uint8_t channelIn } /** - * Instead of scaling the zero based index we must scale the one based position. - * So, we first add 1 to the index, scale it, round it up to the next integer - * and then substract 1 to get the index. - * * @param index the index which should be scaled * @param scaleFactor the factor for the scaling * @return the scaled index */ -int scaleIndexAsPosition(int index, const float scaleFactor) { return ceil((index + 1) * scaleFactor) - 1; } +inline int scaleIndex(const int index, const float scaleFactor) { return round(index * scaleFactor); } + +float scaleFactorOf(const int numberLEDsBefore, const int numberLEDsAfter) { + return (float)(numberLEDsBefore - 1) / (numberLEDsAfter - 1); +} void CLP::scale(FastLEDController* controller, uint8_t channelIndex, int scaleToSize) { auto leds = controller->getLEDs(channelIndex); - const float scaleFactor = (float)controller->getLEDCount(channelIndex) / scaleToSize; + const float scaleFactor = scaleFactorOf(controller->getLEDCount(channelIndex), scaleToSize); if (scaleFactor < 1.0f) { for (int ledIndex = scaleToSize - 1; ledIndex >= 0; ledIndex--) { - leds[ledIndex] = leds[scaleIndexAsPosition(ledIndex, scaleFactor)]; + leds[ledIndex] = leds[scaleIndex(ledIndex, scaleFactor)]; } } else { for (int ledIndex = 0; ledIndex < scaleToSize; ledIndex++) { - leds[ledIndex] = leds[scaleIndexAsPosition(ledIndex, scaleFactor)]; + leds[ledIndex] = leds[scaleIndex(ledIndex, scaleFactor)]; } } } @@ -78,11 +78,11 @@ void CLP::scaleSegments(FastLEDController* controller, uint8_t channelIndex, con for (int i = 0; i < segmentsCount; i++) { const int segmentLength = segments[i].segmentLength; const int scaleToSize = min(segments[i].scaleToSize, segmentLength); - const float scaleFactor = (float)segmentLength / scaleToSize; + const float scaleFactor = scaleFactorOf(segmentLength, scaleToSize); for (int ledIndex = 0; ledIndex < scaleToSize; ledIndex++) { leds[ledStripIndexAfterScaling + ledIndex] = - leds[ledStripIndexBeforeScaling + scaleIndexAsPosition(ledIndex, scaleFactor)]; + leds[ledStripIndexBeforeScaling + scaleIndex(ledIndex, scaleFactor)]; } ledStripIndexAfterScaling += scaleToSize; ledStripIndexBeforeScaling += segmentLength; @@ -95,12 +95,12 @@ void CLP::scaleSegments(FastLEDController* controller, uint8_t channelIndex, con ledStripIndexAfterScaling = totalLengthAfterScaling; // scale up segments beginning with the last segment to not override other segments for (int i = segmentsCount - 1; i >= 0; i--) { - const float scaleFactor = (float)downScaledSegments[i].segmentLength / downScaledSegments[i].scaleToSize; + const float scaleFactor = scaleFactorOf(downScaledSegments[i].segmentLength, downScaledSegments[i].scaleToSize); ledStripIndexAfterScaling -= downScaledSegments[i].scaleToSize; ledStripIndexBeforeScaling -= downScaledSegments[i].segmentLength; for (int ledIndex = downScaledSegments[i].scaleToSize - 1; ledIndex >= 0; ledIndex--) { leds[ledStripIndexAfterScaling + ledIndex] = - leds[ledStripIndexBeforeScaling + scaleIndexAsPosition(ledIndex, scaleFactor)]; + leds[ledStripIndexBeforeScaling + scaleIndex(ledIndex, scaleFactor)]; } } } From 46d70a97a7d0ca9776b4a27baf32baf9ebd7f119 Mon Sep 17 00:00:00 2001 From: Leon Kiefer Date: Tue, 8 Sep 2020 22:52:24 +0200 Subject: [PATCH 9/9] release 0.14.2 --- extra/doxygen.conf | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/doxygen.conf b/extra/doxygen.conf index 7df7e6e1..326f5c86 100644 --- a/extra/doxygen.conf +++ b/extra/doxygen.conf @@ -38,7 +38,7 @@ PROJECT_NAME = "Corsair Lighting Protocol" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.1 +PROJECT_NUMBER = 0.14.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/library.properties b/library.properties index a3d67dc1..42785776 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Corsair Lighting Protocol -version=0.14.1 +version=0.14.2 author=Leon Kiefer maintainer=Leon Kiefer sentence=Control LED strips via USB from a PC.