diff --git a/src/internal/NeoColorFeatures.h b/src/internal/NeoColorFeatures.h
index b33a170..cd88e6d 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 dd26204..9d4bdd4 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 ea2bac0..9267fd9 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 0000000..9914ae4
--- /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 0000000..df3fcde
--- /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 9751bc2..09e8f8d 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 8833e78..ac9b1b7 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 0000000..713ecfa
--- /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 0000000..503cc75
--- /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 03663d9..07c371c 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 @@ public:
}
};
-// 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 0000000..687c75c
--- /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;
+