From fff81b9a15e98acd280c36b4e045a68f33f511ef Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Wed, 8 Feb 2023 14:37:33 -0800 Subject: [PATCH] functional (#643) --- .../NeoPixelBrightness/NeoPixelBrightness.ino | 87 ------------ examples/NeoPixelBusLg/NeoPixelBusLg.ino | 105 ++++++++++++++ keywords.txt | 4 + src/NeoPixelBusLg.h | 130 ++++++++++++++++++ src/internal/NeoGamma.h | 21 ++- 5 files changed, 256 insertions(+), 91 deletions(-) delete mode 100644 examples/NeoPixelBrightness/NeoPixelBrightness.ino create mode 100644 examples/NeoPixelBusLg/NeoPixelBusLg.ino create mode 100644 src/NeoPixelBusLg.h diff --git a/examples/NeoPixelBrightness/NeoPixelBrightness.ino b/examples/NeoPixelBrightness/NeoPixelBrightness.ino deleted file mode 100644 index 15c1a968..00000000 --- a/examples/NeoPixelBrightness/NeoPixelBrightness.ino +++ /dev/null @@ -1,87 +0,0 @@ -// NeoPixelBrightness -// This example will cycle brightness from high to low of -// three pixels colored Red, Green, Blue. -// This demonstrates the use of the NeoPixelBrightnessBus -// with integrated brightness support -// -// There is serial output of the current state so you can -// confirm and follow along -// - -#include // instead of NeoPixelBus.h - -const uint16_t PixelCount = 3; // this example assumes 3 pixels, making it smaller will cause a failure -const uint8_t PixelPin = 14; // make sure to set this to the correct pin, ignored for Esp8266 - -#define colorSaturation 255 // saturation of color constants -RgbColor red(colorSaturation, 0, 0); -RgbColor green(0, colorSaturation, 0); -RgbColor blue(0, 0, colorSaturation); - -// Make sure to provide the correct color order feature -// for your NeoPixels -NeoPixelBrightnessBus strip(PixelCount, PixelPin); - -// you loose the original color the lower the dim value used -// here due to quantization -const uint8_t c_MinBrightness = 8; -const uint8_t c_MaxBrightness = 255; - -int8_t direction; // current direction of dimming - -void setup() -{ - Serial.begin(115200); - while (!Serial); // wait for serial attach - - Serial.println(); - Serial.println("Initializing..."); - Serial.flush(); - - // this resets all the neopixels to an off state - strip.Begin(); - strip.Show(); - - direction = -1; // default to dim first - - Serial.println(); - Serial.println("Running..."); - - // set our three original colors - strip.SetPixelColor(0, red); - strip.SetPixelColor(1, green); - strip.SetPixelColor(2, blue); - - strip.Show(); -} - - -void loop() -{ - uint8_t brightness = strip.GetBrightness(); - Serial.println(brightness); - - delay(100); - - // swap diection of dim when limits are reached - // - if (direction < 0 && brightness <= c_MinBrightness) - { - direction = 1; - } - else if (direction > 0 && brightness >= c_MaxBrightness) - { - direction = -1; - } - // apply dimming - brightness += direction; - - strip.SetPixelColor(0, red); - strip.SetPixelColor(1, green); - strip.SetPixelColor(2, blue); - strip.SetBrightness(brightness); - - // show the results - strip.Show(); -} - diff --git a/examples/NeoPixelBusLg/NeoPixelBusLg.ino b/examples/NeoPixelBusLg/NeoPixelBusLg.ino new file mode 100644 index 00000000..10b9b1ae --- /dev/null +++ b/examples/NeoPixelBusLg/NeoPixelBusLg.ino @@ -0,0 +1,105 @@ +// NeoPixelBusLg +// +// This example demonstrates the use of the NeoPixelBusLg +// with integrated luminance and gamma support +// +// There is serial output of the current state so you can +// confirm and follow along +// + +#include // instead of NeoPixelBus.h + +const uint16_t PixelCount = 96; // set to the number of pixels in your strip +const uint8_t PixelPin = 14; // make sure to set this to the correct pin, ignored for Esp8266 + +RgbColor red(255, 0, 0); +RgbColor green(0, 255, 0); +RgbColor blue(0, 0, 255); +RgbColor black(0, 0, 0); +RgbColor white(255, 255, 255); + +// Make sure to provide the correct color order feature +// for your NeoPixels +NeoPixelBusLg strip(PixelCount, PixelPin); + +// If speed is an issue and memory is not, then you can use the gama table variant +// which is much faster but uses 256 bytes of RAM +// NeoPixelBusLg strip(PixelCount, PixelPin); + +// If you want to turn gama correction off, then you can use the null gama method +// NeoPixelBusLg strip(PixelCount, PixelPin); + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + Serial.flush(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.SetLuminance(128); // (0-255) - initially at half brightness + strip.Show(); + + Serial.println(); + Serial.println("Running..."); +} + +void loop() +{ + static const uint8_t c_MinBrightness = 0; + static const uint8_t c_MaxBrightness = 255; + + static int8_t direction = -1; // start with dimming + + uint8_t luminance = strip.GetLuminance(); + + Serial.print(direction); + Serial.print(" "); + Serial.println(luminance); + + delay(200); + + // swap direction of luminance when limits are reached + // + if (direction < 0 && luminance <= c_MinBrightness) + { + direction = 1; + } + else if (direction > 0 && luminance >= c_MaxBrightness) + { + direction = -1; + } + else + { + luminance += direction; + } + + strip.SetLuminance(luminance); + + // draw something + // + uint16_t half = strip.PixelCount() / 2; + DrawGradiant(green, black, 0, half - 1); + DrawGradiant(black, red, half, strip.PixelCount() - 1); + + // show the results + strip.Show(); +} + +void DrawGradiant(RgbColor startColor, + RgbColor finishColor, + uint16_t startIndex, + uint16_t finishIndex) +{ + uint16_t delta = finishIndex - startIndex; + + for (uint16_t index = startIndex; index < finishIndex; index++) + { + float progress = static_cast(index - startIndex) / delta; + RgbColor color = RgbColor::LinearBlend(startColor, finishColor, progress); + strip.SetPixelColor(index, color); + } +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index 11541eb3..4e406808 100644 --- a/keywords.txt +++ b/keywords.txt @@ -7,6 +7,7 @@ ####################################### NeoPixelBus KEYWORD1 +NeoPixelBusLg KEYWORD1 NeoPixelSegmentBus KEYWORD1 RgbwColor KEYWORD1 RgbColor KEYWORD1 @@ -760,6 +761,9 @@ PixelCount KEYWORD2 SetPixelColor KEYWORD2 GetPixelColor KEYWORD2 SwapPixelColor KEYWORD2 +SetLuminance KEYWORD2 +GetLuminance KEYWORD2 +ApplyPostAdjustments KEYWORD2 SetString KEYWORD2 CalculateBrightness KEYWORD2 Dim KEYWORD2 diff --git a/src/NeoPixelBusLg.h b/src/NeoPixelBusLg.h new file mode 100644 index 00000000..29b46750 --- /dev/null +++ b/src/NeoPixelBusLg.h @@ -0,0 +1,130 @@ +/*------------------------------------------------------------------------- +NeoPixelBus library wrapper template class that provides luminance and gamma control + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#include "NeoPixelBus.h" + +template class NeoPixelBusLg : + public NeoPixelBus +{ +private: + typename T_COLOR_FEATURE::ColorObject ConvertColor(typename T_COLOR_FEATURE::ColorObject color) + { + // dim and then return gamma adjusted + color = color.Dim(_luminance); + return NeoGamma::Correct(color); + } + +public: + NeoPixelBusLg(uint16_t countPixels, uint8_t pin) : + NeoPixelBus(countPixels, pin), + _luminance(255) + { + } + + NeoPixelBusLg(uint16_t countPixels, uint8_t pin, NeoBusChannel channel) : + NeoPixelBus(countPixels, pin, channel), + _luminance(255) + { + } + + NeoPixelBusLg(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) : + NeoPixelBus(countPixels, pinClock, pinData), + _luminance(255) + { + } + + NeoPixelBusLg(uint16_t countPixels, uint8_t pinClock, uint8_t pinData, uint8_t pinLatch, uint8_t pinOutputEnable = NOT_A_PIN) : + NeoPixelBus(countPixels, pinClock, pinData, pinLatch, pinOutputEnable), + _luminance(255) + { + } + + NeoPixelBusLg(uint16_t countPixels) : + NeoPixelBus(countPixels), + _luminance(255) + { + } + + void SetLuminance(uint8_t luminance) + { + // does NOT affect current pixel data as there is no safe way + // to reconstruct the original color values after being + // modified with both luminance and gama without storing them + _luminance = luminance; + } + + uint8_t GetLuminance() const + { + return _luminance; + } + + void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color) + { + color = ConvertColor(color); + NeoPixelBus::SetPixelColor(indexPixel, color); + } + + /* + GetPixelColor is not overloaded as the original will be used + to just return the fully adjusted color value directly with + no reverse conversion since it is fraught with inaccuracy + */ + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color) + { + color = ConvertColor(color); + NeoPixelBus::ClearTo(color); + }; + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color, uint16_t first, uint16_t last) + { + color = ConvertColor(color); + NeoPixelBus::ClearTo(color, first, last); + } + + // if the Pixels buffer is manipulated directly, then this can be called + // to apply the luminance and gamma correction to those changes + void ApplyPostAdjustments() + { + if (this->IsDirty()) + { + for (uint16_t indexPixel = 0; indexPixel < NeoPixelBus::PixelCount(); indexPixel++) + { + typename T_COLOR_FEATURE::ColorObject color = NeoPixelBus::GetPixelColor(indexPixel); + color = ConvertColor(color); + NeoPixelBus::SetPixelColor(indexPixel, color); + } + this->Dirty(); + } + } + +protected: + uint8_t _luminance; +}; + + diff --git a/src/internal/NeoGamma.h b/src/internal/NeoGamma.h index 2c4cf96d..2df93244 100644 --- a/src/internal/NeoGamma.h +++ b/src/internal/NeoGamma.h @@ -60,19 +60,32 @@ class NeoGammaTableMethod static const uint8_t _table[256]; }; +// no gamma correction at all +class NeoGammaNullMethod +{ +public: + static uint8_t Correct(uint8_t value) + { + return value; + } + static uint16_t Correct(uint16_t value) + { + return value; + } +}; // use one of the method classes above as a converter for this template class template class NeoGamma { public: - RgbColor Correct(const RgbColor& original) + static RgbColor Correct(const RgbColor& original) { return RgbColor(T_METHOD::Correct(original.R), T_METHOD::Correct(original.G), T_METHOD::Correct(original.B)); } - RgbwColor Correct(const RgbwColor& original) + static RgbwColor Correct(const RgbwColor& original) { return RgbwColor(T_METHOD::Correct(original.R), T_METHOD::Correct(original.G), @@ -80,14 +93,14 @@ template class NeoGamma T_METHOD::Correct(original.W) ); } - Rgb48Color Correct(const Rgb48Color& original) + static Rgb48Color Correct(const Rgb48Color& original) { return Rgb48Color(T_METHOD::Correct(original.R), T_METHOD::Correct(original.G), T_METHOD::Correct(original.B)); } - Rgbw64Color Correct(const Rgbw64Color& original) + static Rgbw64Color Correct(const Rgbw64Color& original) { return Rgbw64Color(T_METHOD::Correct(original.R), T_METHOD::Correct(original.G),