872 lines
23 KiB
C
872 lines
23 KiB
C
#ifndef __INC_PIXELS_H
|
|
#define __INC_PIXELS_H
|
|
|
|
#include "FastLED.h"
|
|
|
|
#include <stdint.h>
|
|
#include "lib8tion.h"
|
|
#include "color.h"
|
|
|
|
FASTLED_NAMESPACE_BEGIN
|
|
|
|
struct CRGB;
|
|
struct CHSV;
|
|
|
|
///@defgroup Pixeltypes CHSV and CRGB type definitions
|
|
///@{
|
|
|
|
/// Forward declaration of hsv2rgb_rainbow here,
|
|
/// to avoid circular dependencies.
|
|
extern void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb);
|
|
|
|
/// Representation of an HSV pixel (hue, saturation, value (aka brightness)).
|
|
struct CHSV {
|
|
union {
|
|
struct {
|
|
union {
|
|
uint8_t hue;
|
|
uint8_t h; };
|
|
union {
|
|
uint8_t saturation;
|
|
uint8_t sat;
|
|
uint8_t s; };
|
|
union {
|
|
uint8_t value;
|
|
uint8_t val;
|
|
uint8_t v; };
|
|
};
|
|
uint8_t raw[3];
|
|
};
|
|
|
|
/// default values are UNITIALIZED
|
|
inline CHSV() __attribute__((always_inline))
|
|
{
|
|
}
|
|
|
|
/// allow construction from H, S, V
|
|
inline CHSV( uint8_t ih, uint8_t is, uint8_t iv) __attribute__((always_inline))
|
|
: h(ih), s(is), v(iv)
|
|
{
|
|
}
|
|
|
|
/// allow copy construction
|
|
inline CHSV(const CHSV& rhs) __attribute__((always_inline))
|
|
{
|
|
h = rhs.h;
|
|
s = rhs.s;
|
|
v = rhs.v;
|
|
}
|
|
|
|
inline CHSV& operator= (const CHSV& rhs) __attribute__((always_inline))
|
|
{
|
|
h = rhs.h;
|
|
s = rhs.s;
|
|
v = rhs.v;
|
|
return *this;
|
|
}
|
|
|
|
inline CHSV& setHSV(uint8_t ih, uint8_t is, uint8_t iv) __attribute__((always_inline))
|
|
{
|
|
h = ih;
|
|
s = is;
|
|
v = iv;
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
/// Pre-defined hue values for HSV objects
|
|
typedef enum {
|
|
HUE_RED = 0,
|
|
HUE_ORANGE = 32,
|
|
HUE_YELLOW = 64,
|
|
HUE_GREEN = 96,
|
|
HUE_AQUA = 128,
|
|
HUE_BLUE = 160,
|
|
HUE_PURPLE = 192,
|
|
HUE_PINK = 224
|
|
} HSVHue;
|
|
|
|
/// Representation of an RGB pixel (Red, Green, Blue)
|
|
struct CRGB {
|
|
union {
|
|
struct {
|
|
union {
|
|
uint8_t r;
|
|
uint8_t red;
|
|
};
|
|
union {
|
|
uint8_t g;
|
|
uint8_t green;
|
|
};
|
|
union {
|
|
uint8_t b;
|
|
uint8_t blue;
|
|
};
|
|
};
|
|
uint8_t raw[3];
|
|
};
|
|
|
|
/// Array access operator to index into the crgb object
|
|
inline uint8_t& operator[] (uint8_t x) __attribute__((always_inline))
|
|
{
|
|
return raw[x];
|
|
}
|
|
|
|
/// Array access operator to index into the crgb object
|
|
inline const uint8_t& operator[] (uint8_t x) const __attribute__((always_inline))
|
|
{
|
|
return raw[x];
|
|
}
|
|
|
|
// default values are UNINITIALIZED
|
|
inline CRGB() __attribute__((always_inline))
|
|
{
|
|
}
|
|
|
|
/// allow construction from R, G, B
|
|
inline CRGB( uint8_t ir, uint8_t ig, uint8_t ib) __attribute__((always_inline))
|
|
: r(ir), g(ig), b(ib)
|
|
{
|
|
}
|
|
|
|
/// allow construction from 32-bit (really 24-bit) bit 0xRRGGBB color code
|
|
inline CRGB( uint32_t colorcode) __attribute__((always_inline))
|
|
: r((colorcode >> 16) & 0xFF), g((colorcode >> 8) & 0xFF), b((colorcode >> 0) & 0xFF)
|
|
{
|
|
}
|
|
|
|
/// allow construction from a LEDColorCorrection enum
|
|
inline CRGB( LEDColorCorrection colorcode) __attribute__((always_inline))
|
|
: r((colorcode >> 16) & 0xFF), g((colorcode >> 8) & 0xFF), b((colorcode >> 0) & 0xFF)
|
|
{
|
|
|
|
}
|
|
|
|
/// allow construction from a ColorTemperature enum
|
|
inline CRGB( ColorTemperature colorcode) __attribute__((always_inline))
|
|
: r((colorcode >> 16) & 0xFF), g((colorcode >> 8) & 0xFF), b((colorcode >> 0) & 0xFF)
|
|
{
|
|
|
|
}
|
|
|
|
/// allow copy construction
|
|
inline CRGB(const CRGB& rhs) __attribute__((always_inline))
|
|
{
|
|
r = rhs.r;
|
|
g = rhs.g;
|
|
b = rhs.b;
|
|
}
|
|
|
|
/// allow construction from HSV color
|
|
inline CRGB(const CHSV& rhs) __attribute__((always_inline))
|
|
{
|
|
hsv2rgb_rainbow( rhs, *this);
|
|
}
|
|
|
|
/// allow assignment from one RGB struct to another
|
|
inline CRGB& operator= (const CRGB& rhs) __attribute__((always_inline))
|
|
{
|
|
r = rhs.r;
|
|
g = rhs.g;
|
|
b = rhs.b;
|
|
return *this;
|
|
}
|
|
|
|
/// allow assignment from 32-bit (really 24-bit) 0xRRGGBB color code
|
|
inline CRGB& operator= (const uint32_t colorcode) __attribute__((always_inline))
|
|
{
|
|
r = (colorcode >> 16) & 0xFF;
|
|
g = (colorcode >> 8) & 0xFF;
|
|
b = (colorcode >> 0) & 0xFF;
|
|
return *this;
|
|
}
|
|
|
|
/// allow assignment from R, G, and B
|
|
inline CRGB& setRGB (uint8_t nr, uint8_t ng, uint8_t nb) __attribute__((always_inline))
|
|
{
|
|
r = nr;
|
|
g = ng;
|
|
b = nb;
|
|
return *this;
|
|
}
|
|
|
|
/// allow assignment from H, S, and V
|
|
inline CRGB& setHSV (uint8_t hue, uint8_t sat, uint8_t val) __attribute__((always_inline))
|
|
{
|
|
hsv2rgb_rainbow( CHSV(hue, sat, val), *this);
|
|
return *this;
|
|
}
|
|
|
|
/// allow assignment from just a Hue, saturation and value automatically at max.
|
|
inline CRGB& setHue (uint8_t hue) __attribute__((always_inline))
|
|
{
|
|
hsv2rgb_rainbow( CHSV(hue, 255, 255), *this);
|
|
return *this;
|
|
}
|
|
|
|
/// allow assignment from HSV color
|
|
inline CRGB& operator= (const CHSV& rhs) __attribute__((always_inline))
|
|
{
|
|
hsv2rgb_rainbow( rhs, *this);
|
|
return *this;
|
|
}
|
|
|
|
/// allow assignment from 32-bit (really 24-bit) 0xRRGGBB color code
|
|
inline CRGB& setColorCode (uint32_t colorcode) __attribute__((always_inline))
|
|
{
|
|
r = (colorcode >> 16) & 0xFF;
|
|
g = (colorcode >> 8) & 0xFF;
|
|
b = (colorcode >> 0) & 0xFF;
|
|
return *this;
|
|
}
|
|
|
|
|
|
/// add one RGB to another, saturating at 0xFF for each channel
|
|
inline CRGB& operator+= (const CRGB& rhs )
|
|
{
|
|
r = qadd8( r, rhs.r);
|
|
g = qadd8( g, rhs.g);
|
|
b = qadd8( b, rhs.b);
|
|
return *this;
|
|
}
|
|
|
|
/// add a contstant to each channel, saturating at 0xFF
|
|
/// this is NOT an operator+= overload because the compiler
|
|
/// can't usefully decide when it's being passed a 32-bit
|
|
/// constant (e.g. CRGB::Red) and an 8-bit one (CRGB::Blue)
|
|
inline CRGB& addToRGB (uint8_t d )
|
|
{
|
|
r = qadd8( r, d);
|
|
g = qadd8( g, d);
|
|
b = qadd8( b, d);
|
|
return *this;
|
|
}
|
|
|
|
/// subtract one RGB from another, saturating at 0x00 for each channel
|
|
inline CRGB& operator-= (const CRGB& rhs )
|
|
{
|
|
r = qsub8( r, rhs.r);
|
|
g = qsub8( g, rhs.g);
|
|
b = qsub8( b, rhs.b);
|
|
return *this;
|
|
}
|
|
|
|
/// subtract a constant from each channel, saturating at 0x00
|
|
/// this is NOT an operator+= overload because the compiler
|
|
/// can't usefully decide when it's being passed a 32-bit
|
|
/// constant (e.g. CRGB::Red) and an 8-bit one (CRGB::Blue)
|
|
inline CRGB& subtractFromRGB(uint8_t d )
|
|
{
|
|
r = qsub8( r, d);
|
|
g = qsub8( g, d);
|
|
b = qsub8( b, d);
|
|
return *this;
|
|
}
|
|
|
|
/// subtract a constant of '1' from each channel, saturating at 0x00
|
|
inline CRGB& operator-- () __attribute__((always_inline))
|
|
{
|
|
subtractFromRGB(1);
|
|
return *this;
|
|
}
|
|
|
|
/// subtract a constant of '1' from each channel, saturating at 0x00
|
|
inline CRGB operator-- (int ) __attribute__((always_inline))
|
|
{
|
|
CRGB retval(*this);
|
|
--(*this);
|
|
return retval;
|
|
}
|
|
|
|
/// add a constant of '1' from each channel, saturating at 0xFF
|
|
inline CRGB& operator++ () __attribute__((always_inline))
|
|
{
|
|
addToRGB(1);
|
|
return *this;
|
|
}
|
|
|
|
/// add a constant of '1' from each channel, saturating at 0xFF
|
|
inline CRGB operator++ (int ) __attribute__((always_inline))
|
|
{
|
|
CRGB retval(*this);
|
|
++(*this);
|
|
return retval;
|
|
}
|
|
|
|
/// divide each of the channels by a constant
|
|
inline CRGB& operator/= (uint8_t d )
|
|
{
|
|
r /= d;
|
|
g /= d;
|
|
b /= d;
|
|
return *this;
|
|
}
|
|
|
|
/// right shift each of the channels by a constant
|
|
inline CRGB& operator>>= (uint8_t d)
|
|
{
|
|
r >>= d;
|
|
g >>= d;
|
|
b >>= d;
|
|
return *this;
|
|
}
|
|
|
|
/// multiply each of the channels by a constant,
|
|
/// saturating each channel at 0xFF
|
|
inline CRGB& operator*= (uint8_t d )
|
|
{
|
|
r = qmul8( r, d);
|
|
g = qmul8( g, d);
|
|
b = qmul8( b, d);
|
|
return *this;
|
|
}
|
|
|
|
/// scale down a RGB to N 256ths of it's current brightness, using
|
|
/// 'video' dimming rules, which means that unless the scale factor is ZERO
|
|
/// each channel is guaranteed NOT to dim down to zero. If it's already
|
|
/// nonzero, it'll stay nonzero, even if that means the hue shifts a little
|
|
/// at low brightness levels.
|
|
inline CRGB& nscale8_video (uint8_t scaledown )
|
|
{
|
|
nscale8x3_video( r, g, b, scaledown);
|
|
return *this;
|
|
}
|
|
|
|
/// %= is a synonym for nscale8_video. Think of it is scaling down
|
|
/// by "a percentage"
|
|
inline CRGB& operator%= (uint8_t scaledown )
|
|
{
|
|
nscale8x3_video( r, g, b, scaledown);
|
|
return *this;
|
|
}
|
|
|
|
/// fadeLightBy is a synonym for nscale8_video( ..., 255-fadefactor)
|
|
inline CRGB& fadeLightBy (uint8_t fadefactor )
|
|
{
|
|
nscale8x3_video( r, g, b, 255 - fadefactor);
|
|
return *this;
|
|
}
|
|
|
|
/// scale down a RGB to N 256ths of it's current brightness, using
|
|
/// 'plain math' dimming rules, which means that if the low light levels
|
|
/// may dim all the way to 100% black.
|
|
inline CRGB& nscale8 (uint8_t scaledown )
|
|
{
|
|
nscale8x3( r, g, b, scaledown);
|
|
return *this;
|
|
}
|
|
|
|
/// scale down a RGB to N 256ths of it's current brightness, using
|
|
/// 'plain math' dimming rules, which means that if the low light levels
|
|
/// may dim all the way to 100% black.
|
|
inline CRGB& nscale8 (const CRGB & scaledown )
|
|
{
|
|
r = ::scale8(r, scaledown.r);
|
|
g = ::scale8(g, scaledown.g);
|
|
b = ::scale8(b, scaledown.b);
|
|
return *this;
|
|
}
|
|
|
|
/// return a CRGB object that is a scaled down version of this object
|
|
inline CRGB scale8 (const CRGB & scaledown ) const
|
|
{
|
|
CRGB out;
|
|
out.r = ::scale8(r, scaledown.r);
|
|
out.g = ::scale8(g, scaledown.g);
|
|
out.b = ::scale8(b, scaledown.b);
|
|
return out;
|
|
}
|
|
|
|
/// fadeToBlackBy is a synonym for nscale8( ..., 255-fadefactor)
|
|
inline CRGB& fadeToBlackBy (uint8_t fadefactor )
|
|
{
|
|
nscale8x3( r, g, b, 255 - fadefactor);
|
|
return *this;
|
|
}
|
|
|
|
/// "or" operator brings each channel up to the higher of the two values
|
|
inline CRGB& operator|= (const CRGB& rhs )
|
|
{
|
|
if( rhs.r > r) r = rhs.r;
|
|
if( rhs.g > g) g = rhs.g;
|
|
if( rhs.b > b) b = rhs.b;
|
|
return *this;
|
|
}
|
|
|
|
/// "or" operator brings each channel up to the higher of the two values
|
|
inline CRGB& operator|= (uint8_t d )
|
|
{
|
|
if( d > r) r = d;
|
|
if( d > g) g = d;
|
|
if( d > b) b = d;
|
|
return *this;
|
|
}
|
|
|
|
/// "and" operator brings each channel down to the lower of the two values
|
|
inline CRGB& operator&= (const CRGB& rhs )
|
|
{
|
|
if( rhs.r < r) r = rhs.r;
|
|
if( rhs.g < g) g = rhs.g;
|
|
if( rhs.b < b) b = rhs.b;
|
|
return *this;
|
|
}
|
|
|
|
/// "and" operator brings each channel down to the lower of the two values
|
|
inline CRGB& operator&= (uint8_t d )
|
|
{
|
|
if( d < r) r = d;
|
|
if( d < g) g = d;
|
|
if( d < b) b = d;
|
|
return *this;
|
|
}
|
|
|
|
/// this allows testing a CRGB for zero-ness
|
|
inline operator bool() const __attribute__((always_inline))
|
|
{
|
|
return r || g || b;
|
|
}
|
|
|
|
/// invert each channel
|
|
inline CRGB operator- ()
|
|
{
|
|
CRGB retval;
|
|
retval.r = 255 - r;
|
|
retval.g = 255 - g;
|
|
retval.b = 255 - b;
|
|
return retval;
|
|
}
|
|
|
|
#if (defined SmartMatrix_h || defined SmartMatrix3_h)
|
|
operator rgb24() const {
|
|
rgb24 ret;
|
|
ret.red = r;
|
|
ret.green = g;
|
|
ret.blue = b;
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/// Get the 'luma' of a CRGB object - aka roughly how much light the
|
|
/// CRGB pixel is putting out (from 0 to 255).
|
|
inline uint8_t getLuma ( ) const {
|
|
//Y' = 0.2126 R' + 0.7152 G' + 0.0722 B'
|
|
// 54 183 18 (!)
|
|
|
|
uint8_t luma = scale8_LEAVING_R1_DIRTY( r, 54) + \
|
|
scale8_LEAVING_R1_DIRTY( g, 183) + \
|
|
scale8_LEAVING_R1_DIRTY( b, 18);
|
|
cleanup_R1();
|
|
return luma;
|
|
}
|
|
|
|
/// Get the average of the R, G, and B values
|
|
inline uint8_t getAverageLight( ) const {
|
|
#if FASTLED_SCALE8_FIXED == 1
|
|
const uint8_t eightyfive = 85;
|
|
#else
|
|
const uint8_t eightyfive = 86;
|
|
#endif
|
|
uint8_t avg = scale8_LEAVING_R1_DIRTY( r, eightyfive) + \
|
|
scale8_LEAVING_R1_DIRTY( g, eightyfive) + \
|
|
scale8_LEAVING_R1_DIRTY( b, eightyfive);
|
|
cleanup_R1();
|
|
return avg;
|
|
}
|
|
|
|
/// maximize the brightness of this CRGB object
|
|
inline void maximizeBrightness( uint8_t limit = 255 ) {
|
|
uint8_t max = red;
|
|
if( green > max) max = green;
|
|
if( blue > max) max = blue;
|
|
|
|
// stop div/0 when color is black
|
|
if(max > 0) {
|
|
uint16_t factor = ((uint16_t)(limit) * 256) / max;
|
|
red = (red * factor) / 256;
|
|
green = (green * factor) / 256;
|
|
blue = (blue * factor) / 256;
|
|
}
|
|
}
|
|
|
|
/// return a new CRGB object after performing a linear interpolation between this object and the passed in object
|
|
inline CRGB lerp8( const CRGB& other, fract8 frac) const
|
|
{
|
|
CRGB ret;
|
|
|
|
ret.r = lerp8by8(r,other.r,frac);
|
|
ret.g = lerp8by8(g,other.g,frac);
|
|
ret.b = lerp8by8(b,other.b,frac);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/// return a new CRGB object after performing a linear interpolation between this object and the passed in object
|
|
inline CRGB lerp16( const CRGB& other, fract16 frac) const
|
|
{
|
|
CRGB ret;
|
|
|
|
ret.r = lerp16by16(r<<8,other.r<<8,frac)>>8;
|
|
ret.g = lerp16by16(g<<8,other.g<<8,frac)>>8;
|
|
ret.b = lerp16by16(b<<8,other.b<<8,frac)>>8;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/// getParity returns 0 or 1, depending on the
|
|
/// lowest bit of the sum of the color components.
|
|
inline uint8_t getParity()
|
|
{
|
|
uint8_t sum = r + g + b;
|
|
return (sum & 0x01);
|
|
}
|
|
|
|
/// setParity adjusts the color in the smallest
|
|
/// way possible so that the parity of the color
|
|
/// is now the desired value. This allows you to
|
|
/// 'hide' one bit of information in the color.
|
|
///
|
|
/// Ideally, we find one color channel which already
|
|
/// has data in it, and modify just that channel by one.
|
|
/// We don't want to light up a channel that's black
|
|
/// if we can avoid it, and if the pixel is 'grayscale',
|
|
/// (meaning that R==G==B), we modify all three channels
|
|
/// at once, to preserve the neutral hue.
|
|
///
|
|
/// There's no such thing as a free lunch; in many cases
|
|
/// this 'hidden bit' may actually be visible, but this
|
|
/// code makes reasonable efforts to hide it as much
|
|
/// as is reasonably possible.
|
|
///
|
|
/// Also, an effort is made to have make it such that
|
|
/// repeatedly setting the parity to different values
|
|
/// will not cause the color to 'drift'. Toggling
|
|
/// the parity twice should generally result in the
|
|
/// original color again.
|
|
///
|
|
inline void setParity( uint8_t parity)
|
|
{
|
|
uint8_t curparity = getParity();
|
|
|
|
if( parity == curparity) return;
|
|
|
|
if( parity ) {
|
|
// going 'up'
|
|
if( (b > 0) && (b < 255)) {
|
|
if( r == g && g == b) {
|
|
r++;
|
|
g++;
|
|
}
|
|
b++;
|
|
} else if( (r > 0) && (r < 255)) {
|
|
r++;
|
|
} else if( (g > 0) && (g < 255)) {
|
|
g++;
|
|
} else {
|
|
if( r == g && g == b) {
|
|
r ^= 0x01;
|
|
g ^= 0x01;
|
|
}
|
|
b ^= 0x01;
|
|
}
|
|
} else {
|
|
// going 'down'
|
|
if( b > 1) {
|
|
if( r == g && g == b) {
|
|
r--;
|
|
g--;
|
|
}
|
|
b--;
|
|
} else if( g > 1) {
|
|
g--;
|
|
} else if( r > 1) {
|
|
r--;
|
|
} else {
|
|
if( r == g && g == b) {
|
|
r ^= 0x01;
|
|
g ^= 0x01;
|
|
}
|
|
b ^= 0x01;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Predefined RGB colors
|
|
typedef enum {
|
|
AliceBlue=0xF0F8FF,
|
|
Amethyst=0x9966CC,
|
|
AntiqueWhite=0xFAEBD7,
|
|
Aqua=0x00FFFF,
|
|
Aquamarine=0x7FFFD4,
|
|
Azure=0xF0FFFF,
|
|
Beige=0xF5F5DC,
|
|
Bisque=0xFFE4C4,
|
|
Black=0x000000,
|
|
BlanchedAlmond=0xFFEBCD,
|
|
Blue=0x0000FF,
|
|
BlueViolet=0x8A2BE2,
|
|
Brown=0xA52A2A,
|
|
BurlyWood=0xDEB887,
|
|
CadetBlue=0x5F9EA0,
|
|
Chartreuse=0x7FFF00,
|
|
Chocolate=0xD2691E,
|
|
Coral=0xFF7F50,
|
|
CornflowerBlue=0x6495ED,
|
|
Cornsilk=0xFFF8DC,
|
|
Crimson=0xDC143C,
|
|
Cyan=0x00FFFF,
|
|
DarkBlue=0x00008B,
|
|
DarkCyan=0x008B8B,
|
|
DarkGoldenrod=0xB8860B,
|
|
DarkGray=0xA9A9A9,
|
|
DarkGrey=0xA9A9A9,
|
|
DarkGreen=0x006400,
|
|
DarkKhaki=0xBDB76B,
|
|
DarkMagenta=0x8B008B,
|
|
DarkOliveGreen=0x556B2F,
|
|
DarkOrange=0xFF8C00,
|
|
DarkOrchid=0x9932CC,
|
|
DarkRed=0x8B0000,
|
|
DarkSalmon=0xE9967A,
|
|
DarkSeaGreen=0x8FBC8F,
|
|
DarkSlateBlue=0x483D8B,
|
|
DarkSlateGray=0x2F4F4F,
|
|
DarkSlateGrey=0x2F4F4F,
|
|
DarkTurquoise=0x00CED1,
|
|
DarkViolet=0x9400D3,
|
|
DeepPink=0xFF1493,
|
|
DeepSkyBlue=0x00BFFF,
|
|
DimGray=0x696969,
|
|
DimGrey=0x696969,
|
|
DodgerBlue=0x1E90FF,
|
|
FireBrick=0xB22222,
|
|
FloralWhite=0xFFFAF0,
|
|
ForestGreen=0x228B22,
|
|
Fuchsia=0xFF00FF,
|
|
Gainsboro=0xDCDCDC,
|
|
GhostWhite=0xF8F8FF,
|
|
Gold=0xFFD700,
|
|
Goldenrod=0xDAA520,
|
|
Gray=0x808080,
|
|
Grey=0x808080,
|
|
Green=0x008000,
|
|
GreenYellow=0xADFF2F,
|
|
Honeydew=0xF0FFF0,
|
|
HotPink=0xFF69B4,
|
|
IndianRed=0xCD5C5C,
|
|
Indigo=0x4B0082,
|
|
Ivory=0xFFFFF0,
|
|
Khaki=0xF0E68C,
|
|
Lavender=0xE6E6FA,
|
|
LavenderBlush=0xFFF0F5,
|
|
LawnGreen=0x7CFC00,
|
|
LemonChiffon=0xFFFACD,
|
|
LightBlue=0xADD8E6,
|
|
LightCoral=0xF08080,
|
|
LightCyan=0xE0FFFF,
|
|
LightGoldenrodYellow=0xFAFAD2,
|
|
LightGreen=0x90EE90,
|
|
LightGrey=0xD3D3D3,
|
|
LightPink=0xFFB6C1,
|
|
LightSalmon=0xFFA07A,
|
|
LightSeaGreen=0x20B2AA,
|
|
LightSkyBlue=0x87CEFA,
|
|
LightSlateGray=0x778899,
|
|
LightSlateGrey=0x778899,
|
|
LightSteelBlue=0xB0C4DE,
|
|
LightYellow=0xFFFFE0,
|
|
Lime=0x00FF00,
|
|
LimeGreen=0x32CD32,
|
|
Linen=0xFAF0E6,
|
|
Magenta=0xFF00FF,
|
|
Maroon=0x800000,
|
|
MediumAquamarine=0x66CDAA,
|
|
MediumBlue=0x0000CD,
|
|
MediumOrchid=0xBA55D3,
|
|
MediumPurple=0x9370DB,
|
|
MediumSeaGreen=0x3CB371,
|
|
MediumSlateBlue=0x7B68EE,
|
|
MediumSpringGreen=0x00FA9A,
|
|
MediumTurquoise=0x48D1CC,
|
|
MediumVioletRed=0xC71585,
|
|
MidnightBlue=0x191970,
|
|
MintCream=0xF5FFFA,
|
|
MistyRose=0xFFE4E1,
|
|
Moccasin=0xFFE4B5,
|
|
NavajoWhite=0xFFDEAD,
|
|
Navy=0x000080,
|
|
OldLace=0xFDF5E6,
|
|
Olive=0x808000,
|
|
OliveDrab=0x6B8E23,
|
|
Orange=0xFFA500,
|
|
OrangeRed=0xFF4500,
|
|
Orchid=0xDA70D6,
|
|
PaleGoldenrod=0xEEE8AA,
|
|
PaleGreen=0x98FB98,
|
|
PaleTurquoise=0xAFEEEE,
|
|
PaleVioletRed=0xDB7093,
|
|
PapayaWhip=0xFFEFD5,
|
|
PeachPuff=0xFFDAB9,
|
|
Peru=0xCD853F,
|
|
Pink=0xFFC0CB,
|
|
Plaid=0xCC5533,
|
|
Plum=0xDDA0DD,
|
|
PowderBlue=0xB0E0E6,
|
|
Purple=0x800080,
|
|
Red=0xFF0000,
|
|
RosyBrown=0xBC8F8F,
|
|
RoyalBlue=0x4169E1,
|
|
SaddleBrown=0x8B4513,
|
|
Salmon=0xFA8072,
|
|
SandyBrown=0xF4A460,
|
|
SeaGreen=0x2E8B57,
|
|
Seashell=0xFFF5EE,
|
|
Sienna=0xA0522D,
|
|
Silver=0xC0C0C0,
|
|
SkyBlue=0x87CEEB,
|
|
SlateBlue=0x6A5ACD,
|
|
SlateGray=0x708090,
|
|
SlateGrey=0x708090,
|
|
Snow=0xFFFAFA,
|
|
SpringGreen=0x00FF7F,
|
|
SteelBlue=0x4682B4,
|
|
Tan=0xD2B48C,
|
|
Teal=0x008080,
|
|
Thistle=0xD8BFD8,
|
|
Tomato=0xFF6347,
|
|
Turquoise=0x40E0D0,
|
|
Violet=0xEE82EE,
|
|
Wheat=0xF5DEB3,
|
|
White=0xFFFFFF,
|
|
WhiteSmoke=0xF5F5F5,
|
|
Yellow=0xFFFF00,
|
|
YellowGreen=0x9ACD32,
|
|
|
|
// LED RGB color that roughly approximates
|
|
// the color of incandescent fairy lights,
|
|
// assuming that you're using FastLED
|
|
// color correction on your LEDs (recommended).
|
|
FairyLight=0xFFE42D,
|
|
// If you are using no color correction, use this
|
|
FairyLightNCC=0xFF9D2A
|
|
|
|
} HTMLColorCode;
|
|
};
|
|
|
|
|
|
inline __attribute__((always_inline)) bool operator== (const CRGB& lhs, const CRGB& rhs)
|
|
{
|
|
return (lhs.r == rhs.r) && (lhs.g == rhs.g) && (lhs.b == rhs.b);
|
|
}
|
|
|
|
inline __attribute__((always_inline)) bool operator!= (const CRGB& lhs, const CRGB& rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
inline __attribute__((always_inline)) bool operator< (const CRGB& lhs, const CRGB& rhs)
|
|
{
|
|
uint16_t sl, sr;
|
|
sl = lhs.r + lhs.g + lhs.b;
|
|
sr = rhs.r + rhs.g + rhs.b;
|
|
return sl < sr;
|
|
}
|
|
|
|
inline __attribute__((always_inline)) bool operator> (const CRGB& lhs, const CRGB& rhs)
|
|
{
|
|
uint16_t sl, sr;
|
|
sl = lhs.r + lhs.g + lhs.b;
|
|
sr = rhs.r + rhs.g + rhs.b;
|
|
return sl > sr;
|
|
}
|
|
|
|
inline __attribute__((always_inline)) bool operator>= (const CRGB& lhs, const CRGB& rhs)
|
|
{
|
|
uint16_t sl, sr;
|
|
sl = lhs.r + lhs.g + lhs.b;
|
|
sr = rhs.r + rhs.g + rhs.b;
|
|
return sl >= sr;
|
|
}
|
|
|
|
inline __attribute__((always_inline)) bool operator<= (const CRGB& lhs, const CRGB& rhs)
|
|
{
|
|
uint16_t sl, sr;
|
|
sl = lhs.r + lhs.g + lhs.b;
|
|
sr = rhs.r + rhs.g + rhs.b;
|
|
return sl <= sr;
|
|
}
|
|
|
|
|
|
__attribute__((always_inline))
|
|
inline CRGB operator+( const CRGB& p1, const CRGB& p2)
|
|
{
|
|
return CRGB( qadd8( p1.r, p2.r),
|
|
qadd8( p1.g, p2.g),
|
|
qadd8( p1.b, p2.b));
|
|
}
|
|
|
|
__attribute__((always_inline))
|
|
inline CRGB operator-( const CRGB& p1, const CRGB& p2)
|
|
{
|
|
return CRGB( qsub8( p1.r, p2.r),
|
|
qsub8( p1.g, p2.g),
|
|
qsub8( p1.b, p2.b));
|
|
}
|
|
|
|
__attribute__((always_inline))
|
|
inline CRGB operator*( const CRGB& p1, uint8_t d)
|
|
{
|
|
return CRGB( qmul8( p1.r, d),
|
|
qmul8( p1.g, d),
|
|
qmul8( p1.b, d));
|
|
}
|
|
|
|
__attribute__((always_inline))
|
|
inline CRGB operator/( const CRGB& p1, uint8_t d)
|
|
{
|
|
return CRGB( p1.r/d, p1.g/d, p1.b/d);
|
|
}
|
|
|
|
|
|
__attribute__((always_inline))
|
|
inline CRGB operator&( const CRGB& p1, const CRGB& p2)
|
|
{
|
|
return CRGB( p1.r < p2.r ? p1.r : p2.r,
|
|
p1.g < p2.g ? p1.g : p2.g,
|
|
p1.b < p2.b ? p1.b : p2.b);
|
|
}
|
|
|
|
__attribute__((always_inline))
|
|
inline CRGB operator|( const CRGB& p1, const CRGB& p2)
|
|
{
|
|
return CRGB( p1.r > p2.r ? p1.r : p2.r,
|
|
p1.g > p2.g ? p1.g : p2.g,
|
|
p1.b > p2.b ? p1.b : p2.b);
|
|
}
|
|
|
|
__attribute__((always_inline))
|
|
inline CRGB operator%( const CRGB& p1, uint8_t d)
|
|
{
|
|
CRGB retval( p1);
|
|
retval.nscale8_video( d);
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/// RGB orderings, used when instantiating controllers to determine what
|
|
/// order the controller should send RGB data out in, RGB being the default
|
|
/// ordering.
|
|
enum EOrder {
|
|
RGB=0012,
|
|
RBG=0021,
|
|
GRB=0102,
|
|
GBR=0120,
|
|
BRG=0201,
|
|
BGR=0210
|
|
};
|
|
|
|
FASTLED_NAMESPACE_END
|
|
///@}
|
|
|
|
#endif
|