From 7e84f7b759e2840778ae5aa0449f692b5c828654 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Mon, 6 Nov 2023 11:32:59 -0800 Subject: [PATCH] Sm16825e (#742) * Neo5WordFeature * rgbww80color * expose Rgbwc and Rgbcw feature --- src/internal/NeoColorFeatures.h | 5 +- src/internal/NeoColors.h | 1 + src/internal/colors/RgbColorIndexes.h | 3 +- src/internal/colors/Rgbww80Color.cpp | 220 +++++++++++ src/internal/colors/Rgbww80Color.h | 364 ++++++++++++++++++ src/internal/colors/RgbwwColor.cpp | 20 +- src/internal/colors/RgbwwColor.h | 2 +- src/internal/features/Neo5WordFeature.h | 87 +++++ src/internal/features/NeoSm168x3Features.h | 161 ++++++++ ...Sm168xxFeatures.h => NeoSm168x4Features.h} | 132 +------ src/internal/features/NeoSm168x5Features.h | 161 ++++++++ 11 files changed, 1013 insertions(+), 143 deletions(-) create mode 100644 src/internal/colors/Rgbww80Color.cpp create mode 100644 src/internal/colors/Rgbww80Color.h create mode 100644 src/internal/features/Neo5WordFeature.h create mode 100644 src/internal/features/NeoSm168x3Features.h rename src/internal/features/{NeoSm168xxFeatures.h => NeoSm168x4Features.h} (58%) create mode 100644 src/internal/features/NeoSm168x5Features.h diff --git a/src/internal/NeoColorFeatures.h b/src/internal/NeoColorFeatures.h index b33a170b..cd88e6d8 100644 --- a/src/internal/NeoColorFeatures.h +++ b/src/internal/NeoColorFeatures.h @@ -42,6 +42,7 @@ License along with NeoPixel. If not, see #include "features/Neo6xxByteFeature.h" #include "features/Neo3WordFeature.h" #include "features/Neo4WordFeature.h" +#include "features/Neo5WordFeature.h" // NeoPixel Features // @@ -52,7 +53,9 @@ License along with NeoPixel. If not, see #include "features/NeoRgbwxxFeatures.h" #include "features/NeoRgbcwxFeatures.h" -#include "features/NeoSm168xxFeatures.h" +#include "features/NeoSm168x3Features.h" +#include "features/NeoSm168x4Features.h" +#include "features/NeoSm168x5Features.h" #include "features/NeoTm1814Features.h" #include "features/NeoTm1914Features.h" diff --git a/src/internal/NeoColors.h b/src/internal/NeoColors.h index dd26204a..9d4bdd43 100644 --- a/src/internal/NeoColors.h +++ b/src/internal/NeoColors.h @@ -43,6 +43,7 @@ License along with NeoPixel. If not, see #include "colors/Rgbw64Color.h" #include "colors/RgbwwColor.h" +#include "colors/Rgbww80Color.h" #include "colors/SegmentDigit.h" diff --git a/src/internal/colors/RgbColorIndexes.h b/src/internal/colors/RgbColorIndexes.h index ea2bac0b..9267fd9d 100644 --- a/src/internal/colors/RgbColorIndexes.h +++ b/src/internal/colors/RgbColorIndexes.h @@ -32,4 +32,5 @@ const uint8_t ColorIndexG = 1; const uint8_t ColorIndexB = 2; const uint8_t ColorIndexW = 3; const uint8_t ColorIndexWW = 3; // warmer white -const uint8_t ColorIndexCW = 4; // cooler white \ No newline at end of file +const uint8_t ColorIndexCW = 4; // cooler white +const uint8_t ColorIndexY = 4; \ No newline at end of file diff --git a/src/internal/colors/Rgbww80Color.cpp b/src/internal/colors/Rgbww80Color.cpp new file mode 100644 index 00000000..9914ae4f --- /dev/null +++ b/src/internal/colors/Rgbww80Color.cpp @@ -0,0 +1,220 @@ +/*------------------------------------------------------------------------- +Rgbww80Color provides a color object that can be directly consumed by NeoPixelBus + +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 +. +-------------------------------------------------------------------------*/ + + +#include +#include "../NeoSettings.h" +#include "RgbColorBase.h" +#include "RgbColor.h" +#include "RgbwColor.h" +#include "Rgb48Color.h" +#include "Rgbw64Color.h" +#include "HslColor.h" +#include "HsbColor.h" +#include "HtmlColor.h" + +#include "Rgbww80Color.h" + +Rgbww80Color::Rgbww80Color(const RgbwColor& color) +{ + *this = Rgbw64Color(color); +}; + +Rgbww80Color::Rgbww80Color(const Rgbw64Color& color) : + R(color.R), + G(color.G), + B(color.B), + WW(color.W), + CW(color.W) +{ +}; + +uint16_t Rgbww80Color::CalculateBrightness() const +{ + uint16_t colorB = static_cast((static_cast(R) + static_cast(G) + static_cast(B)) / 3); + uint16_t whiteB = static_cast((static_cast(WW) + static_cast(CW)) / 2); + + return (whiteB > colorB) ? whiteB : colorB; +} + +Rgbww80Color Rgbww80Color::Dim(uint16_t ratio) const +{ + // specifically avoids float math + return Rgbww80Color(_elementDim(R, ratio), + _elementDim(G, ratio), + _elementDim(B, ratio), + _elementDim(WW, ratio), + _elementDim(CW, ratio)); +} + +Rgbww80Color Rgbww80Color::Brighten(uint16_t ratio) const +{ + // specifically avoids float math + return Rgbww80Color(_elementBrighten(R, ratio), + _elementBrighten(G, ratio), + _elementBrighten(B, ratio), + _elementBrighten(WW, ratio), + _elementBrighten(CW, ratio)); +} + +void Rgbww80Color::Darken(uint16_t delta) +{ + if (R > delta) + { + R -= delta; + } + else + { + R = 0; + } + + if (G > delta) + { + G -= delta; + } + else + { + G = 0; + } + + if (B > delta) + { + B -= delta; + } + else + { + B = 0; + } + + if (WW > delta) + { + WW -= delta; + } + else + { + WW = 0; + } + + if (CW > delta) + { + CW -= delta; + } + else + { + CW = 0; + } +} + +void Rgbww80Color::Lighten(uint16_t delta) +{ + if (IsColorLess()) + { + if (WW < Max - delta) + { + WW += delta; + } + else + { + WW = Max; + } + + if (CW < Max - delta) + { + CW += delta; + } + else + { + CW = Max; + } + } + else + { + if (R < Max - delta) + { + R += delta; + } + else + { + R = Max; + } + + if (G < Max - delta) + { + G += delta; + } + else + { + G = Max; + } + + if (B < Max - delta) + { + B += delta; + } + else + { + B = Max; + } + } +} + +Rgbww80Color Rgbww80Color::LinearBlend(const Rgbww80Color& left, const Rgbww80Color& right, float progress) +{ + return Rgbww80Color( left.R + ((static_cast(right.R) - left.R) * progress), + left.G + ((static_cast(right.G) - left.G) * progress), + left.B + ((static_cast(right.B) - left.B) * progress), + left.WW + ((static_cast(right.WW) - left.WW) * progress), + left.CW + ((static_cast(right.CW) - left.CW) * progress)); +} + +Rgbww80Color Rgbww80Color::LinearBlend(const Rgbww80Color& left, const Rgbww80Color& right, uint8_t progress) +{ + return Rgbww80Color(left.R + (((static_cast(right.R) - left.R) * static_cast(progress) + 1) >> 8), + left.G + (((static_cast(right.G) - left.G) * static_cast(progress) + 1) >> 8), + left.B + (((static_cast(right.B) - left.B) * static_cast(progress) + 1) >> 8), + left.WW + (((static_cast(right.WW) - left.WW) * static_cast(progress) + 1) >> 8), + left.CW + (((static_cast(right.CW) - left.CW) * static_cast(progress) + 1) >> 8)); +} + +Rgbww80Color Rgbww80Color::BilinearBlend(const Rgbww80Color& c00, + const Rgbww80Color& c01, + const Rgbww80Color& c10, + const Rgbww80Color& c11, + float x, + float y) +{ + float v00 = (1.0f - x) * (1.0f - y); + float v10 = x * (1.0f - y); + float v01 = (1.0f - x) * y; + float v11 = x * y; + + return Rgbww80Color( + c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11, + c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11, + c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11, + c00.WW * v00 + c10.WW * v10 + c01.WW * v01 + c11.WW * v11, + c00.CW * v00 + c10.CW * v10 + c01.CW * v01 + c11.CW * v11); +} \ No newline at end of file diff --git a/src/internal/colors/Rgbww80Color.h b/src/internal/colors/Rgbww80Color.h new file mode 100644 index 00000000..df3fcde1 --- /dev/null +++ b/src/internal/colors/Rgbww80Color.h @@ -0,0 +1,364 @@ +/*------------------------------------------------------------------------- +Rgbww80Color provides a color object that can be directly consumed by NeoPixelBus + +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 + +struct RgbColor; +struct HslColor; +struct HsbColor; + +// ------------------------------------------------------------------------ +// Rgbww80Color represents a color object that is represented by Red, Green, Blue +// component values and two extra White components. +// While the white components are labeled as WW (warm) and CW (cool), they can be +// considered as the "warmer" and "cooler" whites of your LEDs; so that if yours +// have Nuetral and Cool, you could consider the WW as your nuetral. +// It contains helpful color routines to manipulate the color. +// ------------------------------------------------------------------------ +struct Rgbww80Color : RgbColorBase +{ + typedef NeoRgbwwCurrentSettings SettingsObject; + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color using R, G, B, WW, CW values (0-65535) + // ------------------------------------------------------------------------ + Rgbww80Color(uint16_t r, uint16_t g, uint16_t b, uint16_t warmW = 0, uint16_t coolW = 0) : + R(r), G(g), B(b), WW(warmW), CW(coolW) + { + }; + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color using a single brightness value (0-65535) + // This works well for creating gray tone colors + // (0) = black, (65535) = white, (128) = gray + // ------------------------------------------------------------------------ + Rgbww80Color(uint16_t brightness) : + R(0), G(0), B(0), WW(brightness), CW(brightness) + { + }; + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color using RgbColor + // ------------------------------------------------------------------------ + Rgbww80Color(const RgbColor& color) + { + *this = Rgb48Color(color); + }; + + // ------------------------------------------------------------------------ + // Construct a Rgbw80Color using Rgb48Color + // ------------------------------------------------------------------------ + Rgbww80Color(const Rgb48Color& color) : + R(color.R), + G(color.G), + B(color.B), + WW(0), + CW(0) + { + }; + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color using RgbwColor + // ------------------------------------------------------------------------ + Rgbww80Color(const RgbwColor& color); + + // ------------------------------------------------------------------------ + // Construct a Rgbw64Color using Rgb48Color + // ------------------------------------------------------------------------ + Rgbww80Color(const Rgbw64Color& color); + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color using HtmlColor + // ------------------------------------------------------------------------ + Rgbww80Color(const HtmlColor& color) + { + *this = RgbwColor(color); + } + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color using HslColor + // ------------------------------------------------------------------------ + Rgbww80Color(const HslColor& color) + { + *this = Rgb48Color(color); + } + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color using HsbColor + // ------------------------------------------------------------------------ + Rgbww80Color(const HsbColor& color) + { + *this = Rgb48Color(color); + } + + // ------------------------------------------------------------------------ + // Construct a Rgbww80Color that will have its values set in latter operations + // CAUTION: The R,G,B, WW, CW members are not initialized and may not be consistent + // ------------------------------------------------------------------------ + Rgbww80Color() + { + }; + + // ------------------------------------------------------------------------ + // Comparison operators + // ------------------------------------------------------------------------ + bool operator==(const Rgbww80Color& other) const + { + return (R == other.R && G == other.G && B == other.B && WW == other.WW && CW == other.CW); + }; + + bool operator!=(const Rgbww80Color& other) const + { + return !(*this == other); + }; + + // ------------------------------------------------------------------------ + // CompareTo method + // compares against another color with the given epsilon (delta allowed) + // returns the greatest difference of a set of elements, + // 0 = equal within epsilon delta + // negative - this is less than other + // positive - this is greater than other + // ------------------------------------------------------------------------ + int32_t CompareTo(const Rgbww80Color& other, uint16_t epsilon = 256) + { + return _Compare(*this, other, epsilon); + } + + // ------------------------------------------------------------------------ + // Compare method + // compares two colors with the given epsilon (delta allowed) + // returns the greatest difference of a set of elements, + // 0 = equal within epsilon delta + // negative - left is less than right + // positive - left is greater than right + // ------------------------------------------------------------------------ + static int32_t Compare(const Rgbww80Color& left, const Rgbww80Color& right, uint16_t epsilon = 256) + { + return _Compare(left, right, epsilon); + } + + // ------------------------------------------------------------------------ + // operator [] - readonly + // access elements in order by index rather than R,G,B,WW,CW + // see static Count for the number of elements + // ------------------------------------------------------------------------ + uint16_t operator[](size_t idx) const + { + switch (idx) + { + case 0: + return R; + case 1: + return G; + case 2: + return B; + case 3: + return WW; + default: + return CW; + } + } + + // ------------------------------------------------------------------------ + // operator [] - read write + // access elements in order by index rather than R,G,B,WW,CW + // see static Count for the number of elements + // ------------------------------------------------------------------------ + uint16_t& operator[](size_t idx) + { + switch (idx) + { + case 0: + return R; + case 1: + return G; + case 2: + return B; + case 3: + return WW; + default: + return CW; + } + } + + // ------------------------------------------------------------------------ + // Returns if the color is grey, all values are equal other than whites + // ------------------------------------------------------------------------ + bool IsMonotone() const + { + return (R == B && R == G); + }; + + // ------------------------------------------------------------------------ + // Returns if the color components are all zero, the white components maybe + // anything + // ------------------------------------------------------------------------ + bool IsColorLess() const + { + return (R == 0 && B == 0 && G == 0); + }; + + // ------------------------------------------------------------------------ + // CalculateBrightness will calculate the overall brightness + // NOTE: This is a simple linear brightness + // ------------------------------------------------------------------------ + uint16_t CalculateBrightness() const; + + // ------------------------------------------------------------------------ + // Dim will return a new color that is blended to black with the given ratio + // ratio - (0-65535) where 65535 will return the original color and 0 will return black + // + // NOTE: This is a simple linear blend + // ------------------------------------------------------------------------ + Rgbww80Color Dim(uint16_t ratio) const; + + // ------------------------------------------------------------------------ + // Dim will return a new color that is blended to black with the given ratio + // ratio - (0-255) where 255 will return the original color and 0 will return black + // + // NOTE: This is a simple linear blend + // ------------------------------------------------------------------------ + Rgbww80Color Dim(uint8_t ratio) const + { + uint16_t expanded = ratio << 8; + return Dim(expanded); + } + + // ------------------------------------------------------------------------ + // Brighten will return a new color that is blended to white with the given ratio + // ratio - (0-65535) where 65535 will return the original color and 0 will return white + // + // NOTE: This is a simple linear blend + // ------------------------------------------------------------------------ + Rgbww80Color Brighten(uint16_t ratio) const; + + // ------------------------------------------------------------------------ + // Brighten will return a new color that is blended to white with the given ratio + // ratio - (0-255) where 255 will return the original color and 0 will return white + // + // NOTE: This is a simple linear blend + // ------------------------------------------------------------------------ + Rgbww80Color Brighten(uint8_t ratio) const + { + uint16_t expanded = ratio << 8; + return Brighten(expanded); + } + + // ------------------------------------------------------------------------ + // Darken will adjust the color by the given delta toward black + // NOTE: This is a simple linear change + // delta - (0-65535) the amount to dim the color + // ------------------------------------------------------------------------ + void Darken(uint16_t delta); + + // ------------------------------------------------------------------------ + // Lighten will adjust the color by the given delta toward white + // NOTE: This is a simple linear change + // delta - (0-65535) the amount to lighten the color + // ------------------------------------------------------------------------ + void Lighten(uint16_t delta); + + // ------------------------------------------------------------------------ + // LinearBlend between two colors by the amount defined by progress variable + // left - the color to start the blend at + // right - the color to end the blend at + // progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right + // and a value between will blend the color weighted linearly between them + // ------------------------------------------------------------------------ + static Rgbww80Color LinearBlend(const Rgbww80Color& left, const Rgbww80Color& right, float progress); + // progress - (0 - 255) value where 0 will return left and 255 will return right + // and a value between will blend the color weighted linearly between them + // ------------------------------------------------------------------------ + static Rgbww80Color LinearBlend(const Rgbww80Color& left, const Rgbww80Color& right, uint8_t progress); + + // ------------------------------------------------------------------------ + // BilinearBlend between four colors by the amount defined by 2d variable + // c00 - upper left quadrant color + // c01 - upper right quadrant color + // c10 - lower left quadrant color + // c11 - lower right quadrant color + // x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space + // y - unit value (0.0 - 1.0) that defines the blend progress in vertical space + // ------------------------------------------------------------------------ + static Rgbww80Color BilinearBlend(const Rgbww80Color& c00, + const Rgbww80Color& c01, + const Rgbww80Color& c10, + const Rgbww80Color& c11, + float x, + float y); + + uint16_t CalcTotalTenthMilliAmpere(const SettingsObject& settings) + { + auto total = 0; + + total += R * settings.RedTenthMilliAmpere / Max; + total += G * settings.GreenTenthMilliAmpere / Max; + total += B * settings.BlueTenthMilliAmpere / Max; + total += WW * settings.WarmWhiteTenthMilliAmpere / Max; + total += CW * settings.CoolWhiteTenthMilliAmpere / Max; + + return total; + } + + // ------------------------------------------------------------------------ + // Red, Green, Blue, Warm White, Cool White color members (0-65535) where + // (0,0,0,0,0) is black and + // (65535,65535,65535, 0, 0) is a white + // (0,0,0,65535,0) is warm white and + // (0,0,0,0,65535) is cool white and + // Note (65535,65535,65535,65535,65535) is extreme bright white + // ------------------------------------------------------------------------ + uint16_t R; + uint16_t G; + uint16_t B; + uint16_t WW; + uint16_t CW; + + const static uint16_t Max = 65535; + const static size_t Count = 5; // five elements in [] + +private: + inline static uint16_t _elementDim(uint16_t value, uint16_t ratio) + { + return (static_cast(value) * (static_cast(ratio) + 1)) >> 16; + } + + inline static uint16_t _elementBrighten(uint16_t value, uint16_t ratio) + { + uint32_t element = ((static_cast(value) + 1) << 16) / (static_cast(ratio) + 1); + + if (element > Max) + { + element = Max; + } + else + { + element -= 1; + } + return element; + } +}; + diff --git a/src/internal/colors/RgbwwColor.cpp b/src/internal/colors/RgbwwColor.cpp index 9751bc26..09e8f8da 100644 --- a/src/internal/colors/RgbwwColor.cpp +++ b/src/internal/colors/RgbwwColor.cpp @@ -141,51 +141,51 @@ void RgbwwColor::Lighten(uint8_t delta) { if (IsColorLess()) { - if (WW < 255 - delta) + if (WW < Max - delta) { WW += delta; } else { - WW = 255; + WW = Max; } - if (CW < 255 - delta) + if (CW < Max - delta) { CW += delta; } else { - CW = 255; + CW = Max; } } else { - if (R < 255 - delta) + if (R < Max - delta) { R += delta; } else { - R = 255; + R = Max; } - if (G < 255 - delta) + if (G < Max - delta) { G += delta; } else { - G = 255; + G = Max; } - if (B < 255 - delta) + if (B < Max - delta) { B += delta; } else { - B = 255; + B = Max; } } } diff --git a/src/internal/colors/RgbwwColor.h b/src/internal/colors/RgbwwColor.h index 8833e783..ac9b1b77 100644 --- a/src/internal/colors/RgbwwColor.h +++ b/src/internal/colors/RgbwwColor.h @@ -299,7 +299,7 @@ struct RgbwwColor : RgbColorBase uint8_t CW; const static uint8_t Max = 255; - const static size_t Count = 5; // four elements in [] + const static size_t Count = 5; // five elements in [] private: inline static uint8_t _elementDim(uint8_t value, uint8_t ratio) diff --git a/src/internal/features/Neo5WordFeature.h b/src/internal/features/Neo5WordFeature.h new file mode 100644 index 00000000..713ecfa3 --- /dev/null +++ b/src/internal/features/Neo5WordFeature.h @@ -0,0 +1,87 @@ +/*------------------------------------------------------------------------- +Neo5WordFeature provides feature base class to describe color order for + 5 Word features + +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 + +template +class Neo5WordFeature : + public NeoWordElements<10, Rgbww80Color, uint16_t> +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + // due to endianness the byte order must be copied to output + *p++ = color[V_IC_1] >> 8; + *p++ = color[V_IC_1] & 0xff; + *p++ = color[V_IC_2] >> 8; + *p++ = color[V_IC_2] & 0xff; + *p++ = color[V_IC_3] >> 8; + *p++ = color[V_IC_3] & 0xff; + *p++ = color[V_IC_4] >> 8; + *p++ = color[V_IC_4] & 0xff; + *p++ = color[V_IC_5] >> 8; + *p = color[V_IC_5] & 0xff; + } + + static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress(pPixels, indexPixel); + + // due to endianness the byte order must be copied to output + color[V_IC_1] = (static_cast(*p++) << 8); + color[V_IC_1] |= *p++; + color[V_IC_2] = (static_cast(*p++) << 8); + color[V_IC_2] |= *p++; + color[V_IC_3] = (static_cast(*p++) << 8); + color[V_IC_3] |= *p++; + color[V_IC_4] = (static_cast(*p++) << 8); + color[V_IC_4] |= *p++; + color[V_IC_5] = (static_cast(*p++) << 8); + color[V_IC_5] |= *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint16_t* p = reinterpret_cast(getPixelAddress(reinterpret_cast(pPixels), indexPixel)); + + // PROGMEM unit of storage expected to be the same size as color element + // so no endianness issues to worry about + color[V_IC_1] = pgm_read_word(p++); + color[V_IC_2] = pgm_read_word(p++); + color[V_IC_3] = pgm_read_word(p++); + color[V_IC_4] = pgm_read_word(p++); + color[V_IC_5] = pgm_read_word(p); + + return color; + } + + }; \ No newline at end of file diff --git a/src/internal/features/NeoSm168x3Features.h b/src/internal/features/NeoSm168x3Features.h new file mode 100644 index 00000000..503cc75f --- /dev/null +++ b/src/internal/features/NeoSm168x3Features.h @@ -0,0 +1,161 @@ +/*------------------------------------------------------------------------- +NeoSm168x3Features provides feature classes to describe color order and +color depth for NeoPixelBus template class specific to the SM168x3 chips/leds + +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 +/* +3 channel RGB +SM16803P 1.8~60mA << need spec sheet to get accurate implementation +SM16813PB 1.8~19mA +SM16823E 60~350mA +*/ + +class NeoSm168x3SettingsBase : public NeoRgbCurrentSettings +{ +public: + NeoSm168x3SettingsBase(uint8_t redGain, + uint8_t greenGain, + uint8_t blueGain, + uint16_t redCurrent, + uint16_t greenCurrent, + uint16_t blueCurrent) : + NeoRgbCurrentSettings(redCurrent, greenCurrent, blueCurrent), + RedGain(redGain & 0x0f), + GreenGain(greenGain & 0x0f), + BlueGain(blueGain & 0x0f) {} + + // ------------------------------------------------------------------------ + // operator [] - readonly + // access elements in order by index rather than member name + // ------------------------------------------------------------------------ + uint8_t operator[](size_t idx) const + { + switch (idx) + { + case 0: + return RedGain; + case 1: + return GreenGain; + default: + return BlueGain; + } + } + + const uint8_t RedGain : 4; + const uint8_t GreenGain : 4; + const uint8_t BlueGain : 4; +}; + +template +class NeoSm16803pbSettings : public NeoSm168x3SettingsBase +{ +public: + NeoSm16803pbSettings(uint8_t redGain, uint8_t greenGain, uint8_t blueGain) : + NeoSm168x3SettingsBase(redGain, + greenGain, + blueGain, + CurrentLookup[redGain], + CurrentLookup[greenGain], + CurrentLookup[blueGain]) + { + } + + void Encode(uint8_t* encoded) const + { + // 0RGB 4 bits each + *encoded++ = operator[](V_IC_1); + *encoded = operator[](V_IC_2) << 4 | operator[](V_IC_3); + } + +protected: + static constexpr uint8_t CurrentLookup[16] = { + 18, 30, 41, 53, 64, 76, 87, 99, + 110, 133, 145, 156, 168, 179, 190}; +}; + +template +class NeoSm16823eSettings : public NeoSm168x3SettingsBase +{ +public: + NeoSm16823eSettings(uint8_t redGain, uint8_t greenGain, uint8_t blueGain, uint16_t resisterOhms) : + NeoSm168x3SettingsBase(redGain, + greenGain, + blueGain, + calcCurrent(resisterOhms, redGain), + calcCurrent(resisterOhms, greenGain), + calcCurrent(resisterOhms, blueGain)), + extROhms(resisterOhms) + { + } + + void Encode(uint8_t* encoded) const + { + // RGB0 4 bits each + *encoded++ = operator[](V_IC_1) << 4 | operator[](V_IC_2); + *encoded = operator[](V_IC_3) << 4; + } + +protected: + const uint16_t extROhms; + + static uint16_t calcCurrent(const uint16_t ohms, const uint8_t gain) + { + uint16_t mA = (967 * (240 + (gain * 32)) / ohms); // from spec sheet, gain 0-15 instead + return mA * 10; // return tenths of mA + } +}; + +// CAUTION: Make sure ColorIndex order for Neo3ByteFeature matches T_SETTINGS +template class NeoRgbSm168x3Elements : + public Neo3ByteFeature +{ +public: + typedef T_SETTINGS SettingsObject; + static const size_t SettingsSize = 2; + + static void applySettings([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData, [[maybe_unused]] const SettingsObject& settings) + { + // settings are at the end of the data stream + uint8_t* pDest = pData + sizeData - SettingsSize; + + settings.Encode(pDest); + } + + static uint8_t* pixels([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData) + { + return pData; + } + + static const uint8_t* pixels([[maybe_unused]] const uint8_t* pData, [[maybe_unused]] size_t sizeData) + { + return pData; + } +}; + +typedef NeoRgbSm168x3Elements> NeoRgbSm16803pbFeature; +typedef NeoRgbSm168x3Elements> NeoRgbSm16823eFeature; + + + diff --git a/src/internal/features/NeoSm168xxFeatures.h b/src/internal/features/NeoSm168x4Features.h similarity index 58% rename from src/internal/features/NeoSm168xxFeatures.h rename to src/internal/features/NeoSm168x4Features.h index 03663d97..07c371cd 100644 --- a/src/internal/features/NeoSm168xxFeatures.h +++ b/src/internal/features/NeoSm168x4Features.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- -NeoSm168xxFeatures provides feature classes to describe color order and -color depth for NeoPixelBus template class specific to the SM168xx chips/leds +NeoSm168x4Features provides feature classes to describe color order and +color depth for NeoPixelBus template class specific to the SM168x4 chips/leds Written by Michael C. Miller. @@ -26,111 +26,12 @@ License along with NeoPixel. If not, see -------------------------------------------------------------------------*/ #pragma once /* -3 channel RGB -SM16803P 1.8~60mA << need spec sheet to get accurate implementation -SM16813PB 1.8~19mA -SM16823E 60~350mA 4 channel RGBW SM16804PB 1.5~60mA << need spec sheet to get accurate implementation SM16804EB 1.8~19mA SM16824E 60~350mA */ -class NeoSm168x3SettingsBase : public NeoRgbCurrentSettings -{ -public: - NeoSm168x3SettingsBase(uint8_t redGain, - uint8_t greenGain, - uint8_t blueGain, - uint16_t redCurrent, - uint16_t greenCurrent, - uint16_t blueCurrent) : - NeoRgbCurrentSettings(redCurrent, greenCurrent, blueCurrent), - RedGain(redGain & 0x0f), - GreenGain(greenGain & 0x0f), - BlueGain(blueGain & 0x0f) {} - - // ------------------------------------------------------------------------ - // operator [] - readonly - // access elements in order by index rather than member name - // ------------------------------------------------------------------------ - uint8_t operator[](size_t idx) const - { - switch (idx) - { - case 0: - return RedGain; - case 1: - return GreenGain; - default: - return BlueGain; - } - } - - const uint8_t RedGain : 4; - const uint8_t GreenGain : 4; - const uint8_t BlueGain : 4; -}; - -template -class NeoSm16803pbSettings : public NeoSm168x3SettingsBase -{ -public: - NeoSm16803pbSettings(uint8_t redGain, uint8_t greenGain, uint8_t blueGain) : - NeoSm168x3SettingsBase(redGain, - greenGain, - blueGain, - CurrentLookup[redGain], - CurrentLookup[greenGain], - CurrentLookup[blueGain]) - { - } - - void Encode(uint8_t* encoded) const - { - // 0RGB 4 bits each - *encoded++ = operator[](V_IC_1); - *encoded = operator[](V_IC_2) << 4 | operator[](V_IC_3); - } - -protected: - static constexpr uint8_t CurrentLookup[16] = { - 18, 30, 41, 53, 64, 76, 87, 99, - 110, 133, 145, 156, 168, 179, 190}; -}; - -template -class NeoSm16823eSettings : public NeoSm168x3SettingsBase -{ -public: - NeoSm16823eSettings(uint8_t redGain, uint8_t greenGain, uint8_t blueGain, uint16_t resisterOhms) : - NeoSm168x3SettingsBase(redGain, - greenGain, - blueGain, - calcCurrent(resisterOhms, redGain), - calcCurrent(resisterOhms, greenGain), - calcCurrent(resisterOhms, blueGain)), - extROhms(resisterOhms) - { - } - - void Encode(uint8_t* encoded) const - { - // RGB0 4 bits each - *encoded++ = operator[](V_IC_1) << 4 | operator[](V_IC_2); - *encoded = operator[](V_IC_3) << 4; - } - -protected: - const uint16_t extROhms; - - static uint16_t calcCurrent(const uint16_t ohms, const uint8_t gain) - { - uint16_t mA = (967 * (240 + (gain * 32)) / ohms); // from spec sheet, gain 0-15 instead - return mA * 10; // return tenths of mA - } -}; - // RGBW versions class NeoSm168x4SettingsBase : public NeoRgbwCurrentSettings @@ -267,35 +168,6 @@ class NeoRgbwSm168x4Elements : } }; -// CAUTION: Make sure ColorIndex order for Neo3ByteFeature matches T_SETTINGS -template class NeoRgbSm168x3Elements : - public Neo3ByteFeature -{ -public: - typedef T_SETTINGS SettingsObject; - static const size_t SettingsSize = 2; - - static void applySettings([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData, [[maybe_unused]] const SettingsObject& settings) - { - // settings are at the end of the data stream - uint8_t* pDest = pData + sizeData - SettingsSize; - - settings.Encode(pDest); - } - - static uint8_t* pixels([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData) - { - return pData; - } - - static const uint8_t* pixels([[maybe_unused]] const uint8_t* pData, [[maybe_unused]] size_t sizeData) - { - return pData; - } -}; - -typedef NeoRgbSm168x3Elements> NeoRgbSm16803pbFeature; -typedef NeoRgbSm168x3Elements> NeoRgbSm16823eFeature; typedef NeoRgbwSm168x4Elements> NeoRgbwSm16804ebFeature; typedef NeoRgbwSm168x4Elements> NeoRgbwSm16824eFeature; diff --git a/src/internal/features/NeoSm168x5Features.h b/src/internal/features/NeoSm168x5Features.h new file mode 100644 index 00000000..687c75c2 --- /dev/null +++ b/src/internal/features/NeoSm168x5Features.h @@ -0,0 +1,161 @@ +/*------------------------------------------------------------------------- +NeoSm168x5Features provides feature classes to describe color order and +color depth for NeoPixelBus template class specific to the SM168x5 chips/leds + +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 +/* +5 channel RGBWY +SM16825E 10.2~310.0mA +*/ + +class NeoSm168x5SettingsBase : public NeoRgbwwCurrentSettings +{ +public: + NeoSm168x5SettingsBase(uint8_t redGain, + uint8_t greenGain, + uint8_t blueGain, + uint8_t whiteGain, + uint8_t otherGain, + uint16_t redCurrent, + uint16_t greenCurrent, + uint16_t blueCurrent, + uint16_t whiteCurrent, + uint16_t otherCurrent) : + NeoRgbwwCurrentSettings(redCurrent, greenCurrent, blueCurrent, whiteCurrent, otherCurrent), + RedGain(redGain & 0x1f), + GreenGain(greenGain & 0x1f), + BlueGain(blueGain & 0x1f), + WhiteGain(whiteGain & 0x1f), + OtherGain(otherGain & 0x1f) {} + + // ------------------------------------------------------------------------ + // operator [] - readonly + // access elements in order by index rather than member name + // ------------------------------------------------------------------------ + uint8_t operator[](size_t idx) const + { + switch (idx) + { + case 0: + return RedGain; + case 1: + return GreenGain; + case 2: + return BlueGain; + case 3: + return WhiteGain; + default: + return OtherGain; + } + } + + const uint8_t RedGain : 5; + const uint8_t GreenGain : 5; + const uint8_t BlueGain : 5; + const uint8_t WhiteGain : 5; + const uint8_t OtherGain : 5; +}; + + + +template +class NeoSm16825eSettings : public NeoSm168x5SettingsBase +{ +public: + NeoSm16825eSettings(uint8_t redGain, uint8_t greenGain, uint8_t blueGain, uint8_t whiteGain, uint8_t otherGain ) : + NeoSm168x5SettingsBase(redGain, + greenGain, + blueGain, + whiteGain, + otherGain, + CurrentLookup[redGain], + CurrentLookup[greenGain], + CurrentLookup[blueGain], + CurrentLookup[whiteGain], + CurrentLookup[otherGain]) + { + } + + void Encode(uint8_t* encoded) const + { + // RGBWY 5 bits each + *encoded++ = operator[](V_IC_1) << 3 | operator[](V_IC_2) >> 2; // 0b11111222 + *encoded++ = operator[](V_IC_2) << 6 | operator[](V_IC_3) << 1 | operator[](V_IC_4) >> 4; // 0b22333334 + *encoded++ = operator[](V_IC_4) << 4 | operator[](V_IC_5) >> 1; // 0b44445555 + *encoded = operator[](V_IC_5) << 7 | 0b00011111; // 0b50011111 00 (action, not standby) 11111 (reserved) + } + +protected: + static constexpr uint16_t CurrentLookup[32] = { + 102, 203, 304, 405, 506, 607, 708, 809, + 910, 1011, 1112, 1213, 1307, 1406, 1505, 1602, + 1700, 1790, 1885, 1980, 2078, 2168, 2264, 2358, + 2450, 2544, 2636, 2728, 2820, 2910, 3000, 3100}; // in tenth mA + + /* not to spec, switched to table + constexpr uint16_t MinCmA = 1020; // 100th of a mA + constexpr uint16_t MaxCmA = 31000; + constexpr uint16_t DeltaCmA = MaxCmA - MinCmA; + constexpr uint16_t IncCmA = DeltaCmA / 31; + + static uint16_t calcCurrent(const uint8_t gain) + { + uint16_t CmA = MinCmA + (gain * IncCmA); + return CmA / 10; // return tenths of mA + } + */ +}; + +// CAUTION: Make sure ColorIndex order for Neo5ByteFeature matches T_SETTINGS +template +class NeoRgbwcSm168x5Elements : + public Neo5WordFeature +{ +public: + typedef NeoSm16825eSettings SettingsObject; + static const size_t SettingsSize = 4; + + static void applySettings([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData, [[maybe_unused]] const SettingsObject& settings) + { + // settings are at the end of the data stream + uint8_t* pDest = pData + sizeData - SettingsSize; + + settings.Encode(pDest); + } + + static uint8_t* pixels([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData) + { + return pData; + } + + static const uint8_t* pixels([[maybe_unused]] const uint8_t* pData, [[maybe_unused]] size_t sizeData) + { + return pData; + } +}; + +typedef NeoRgbwcSm168x5Elements NeoRgbwcSm16825eFeature; +typedef NeoRgbwcSm168x5Elements NeoRgbcwSm16825eFeature; +