Added TwinkleFOX effect

Added Orangery palette
This commit is contained in:
cschwinne 2019-08-30 15:39:34 +02:00
parent 44a8ae457d
commit 188fe5dc52
5 changed files with 192 additions and 35 deletions

View File

@ -1552,7 +1552,7 @@ uint16_t WS2812FX::mode_pride_2015(void)
bri8 += (255 - brightdepth); bri8 += (255 - brightdepth);
CRGB newcolor = CHSV( hue8, sat8, bri8); CRGB newcolor = CHSV( hue8, sat8, bri8);
fastled_col = fastled_from_col(getPixelColor(i)); fastled_col = col_to_crgb(getPixelColor(i));
nblend( fastled_col, newcolor, 64); nblend( fastled_col, newcolor, 64);
setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
@ -1570,7 +1570,7 @@ uint16_t WS2812FX::mode_juggle(void){
byte dothue = 0; byte dothue = 0;
for ( byte i = 0; i < 8; i++) { for ( byte i = 0; i < 8; i++) {
uint16_t index = SEGMENT.start + beatsin16(i + 7, 0, SEGLEN -1); uint16_t index = SEGMENT.start + beatsin16(i + 7, 0, SEGLEN -1);
fastled_col = fastled_from_col(getPixelColor(index)); fastled_col = col_to_crgb(getPixelColor(index));
fastled_col |= (SEGMENT.palette==0)?CHSV(dothue, 220, 255):ColorFromPalette(currentPalette, dothue, 255); fastled_col |= (SEGMENT.palette==0)?CHSV(dothue, 220, 255):ColorFromPalette(currentPalette, dothue, 255);
setPixelColor(index, fastled_col.red, fastled_col.green, fastled_col.blue); setPixelColor(index, fastled_col.red, fastled_col.green, fastled_col.blue);
dothue += 32; dothue += 32;
@ -1696,7 +1696,7 @@ uint16_t WS2812FX::mode_colorwaves(void)
bri8 += (255 - brightdepth); bri8 += (255 - brightdepth);
CRGB newcolor = ColorFromPalette(currentPalette, hue8, bri8); CRGB newcolor = ColorFromPalette(currentPalette, hue8, bri8);
fastled_col = fastled_from_col(getPixelColor(i)); fastled_col = col_to_crgb(getPixelColor(i));
nblend(fastled_col, newcolor, 128); nblend(fastled_col, newcolor, 128);
setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
@ -1836,7 +1836,7 @@ uint16_t WS2812FX::mode_colortwinkle()
CRGB fastled_col, prev; CRGB fastled_col, prev;
fract8 fadeUpAmount = 8 + (SEGMENT.speed/4), fadeDownAmount = 5 + (SEGMENT.speed/7); fract8 fadeUpAmount = 8 + (SEGMENT.speed/4), fadeDownAmount = 5 + (SEGMENT.speed/7);
for( uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { for( uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) {
fastled_col = fastled_from_col(getPixelColor(i)); fastled_col = col_to_crgb(getPixelColor(i));
prev = fastled_col; prev = fastled_col;
if(_locked[i]) { if(_locked[i]) {
CRGB incrementalColor = fastled_col; CRGB incrementalColor = fastled_col;
@ -1848,7 +1848,7 @@ uint16_t WS2812FX::mode_colortwinkle()
} }
setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
if (fastled_from_col(getPixelColor(i)) == prev) //fix "stuck" pixels if (col_to_crgb(getPixelColor(i)) == prev) //fix "stuck" pixels
{ {
fastled_col += fastled_col; fastled_col += fastled_col;
setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
@ -2050,3 +2050,130 @@ uint16_t WS2812FX::mode_ripple()
} }
return 20; return 20;
} }
// TwinkleFOX by Mark Kriegsman: https://gist.github.com/kriegsman/756ea6dcae8e30845b5a
//
// TwinkleFOX: Twinkling 'holiday' lights that fade in and out.
// Colors are chosen from a palette. Read more about this effect using the link above!
// If COOL_LIKE_INCANDESCENT is set to 1, colors will
// fade out slighted 'reddened', similar to how
// incandescent bulbs change color as they get dim down.
#define COOL_LIKE_INCANDESCENT 1
CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt)
{
// Overall twinkle speed (changed)
uint16_t ticks = ms / (32 - (SEGMENT.speed >> 3));
uint8_t fastcycle8 = ticks;
uint16_t slowcycle16 = (ticks >> 8) + salt;
slowcycle16 += sin8(slowcycle16);
slowcycle16 = (slowcycle16 * 2053) + 1384;
uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8);
// Overall twinkle density.
// 0 (NONE lit) to 8 (ALL lit at once).
// Default is 5.
uint8_t twinkleDensity = (SEGMENT.intensity >> 5) +1;
uint8_t bright = 0;
if (((slowcycle8 & 0x0E)/2) < twinkleDensity) {
uint8_t ph = fastcycle8;
// This is like 'triwave8', which produces a
// symmetrical up-and-down triangle sawtooth waveform, except that this
// function produces a triangle wave with a faster attack and a slower decay
if (ph < 86) {
bright = ph * 3;
} else {
ph -= 86;
bright = 255 - (ph + (ph/2));
}
}
uint8_t hue = slowcycle8 - salt;
CRGB c;
if (bright > 0) {
c = ColorFromPalette(currentPalette, hue, bright, NOBLEND);
if(COOL_LIKE_INCANDESCENT == 1) {
// This code takes a pixel, and if its in the 'fading down'
// part of the cycle, it adjusts the color a little bit like the
// way that incandescent bulbs fade toward 'red' as they dim.
if (fastcycle8 >= 128)
{
uint8_t cooling = (fastcycle8 - 128) >> 4;
c.g = qsub8(c.g, cooling);
c.b = qsub8(c.b, cooling * 2);
}
}
} else {
c = CRGB::Black;
}
return c;
}
// This function loops over each pixel, calculates the
// adjusted 'clock' that this pixel should use, and calls
// "CalculateOneTwinkle" on each pixel. It then displays
// either the twinkle color of the background color,
// whichever is brighter.
uint16_t WS2812FX::mode_twinklefox()
{
// "PRNG16" is the pseudorandom number generator
// It MUST be reset to the same starting value each time
// this function is called, so that the sequence of 'random'
// numbers that it generates is (paradoxically) stable.
uint16_t PRNG16 = 11337;
uint32_t clock32 = millis();
// Set up the background color, "bg".
// if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of
// the current palette are identical, then a deeply faded version of
// that color is used for the background color
CRGB bg;
bg = col_to_crgb(SEGCOLOR(1));
uint8_t bglight = bg.getAverageLight();
if (bglight > 64) {
bg.nscale8_video(16); // very bright, so scale to 1/16th
} else if (bglight > 16) {
bg.nscale8_video(64); // not that bright, so scale to 1/4th
} else {
bg.nscale8_video(86); // dim, scale to 1/3rd.
}
uint8_t backgroundBrightness = bg.getAverageLight();
for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) {
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number
uint16_t myclockoffset16= PRNG16; // use that number as clock offset
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number
// use that number as clock speed adjustment factor (in 8ths, from 8/8ths to 23/8ths)
uint8_t myspeedmultiplierQ5_3 = ((((PRNG16 & 0xFF)>>4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08;
uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16;
uint8_t myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel
// We now have the adjusted 'clock' for this pixel, now we call
// the function that computes what color the pixel should be based
// on the "brightness = f( time )" idea.
CRGB c = twinklefox_one_twinkle(myclock30, myunique8);
uint8_t cbright = c.getAverageLight();
int16_t deltabright = cbright - backgroundBrightness;
if (deltabright >= 32 || (!bg)) {
// If the new pixel is significantly brighter than the background color,
// use the new color.
setPixelColor(i, c);
} else if (deltabright > 0) {
// If the new pixel is just slightly brighter than the background color,
// mix a blend of the new color and the background color
setPixelColor(i, color_blend(crgb_to_col(bg), crgb_to_col(c), deltabright * 8));
} else {
// if the new pixel is not at all brighter than the background color,
// just use the background color.
setPixelColor(i, bg);
}
}
return 20;
}

View File

@ -79,7 +79,7 @@
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
#define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED )
#define MODE_COUNT 80 #define MODE_COUNT 81
#define FX_MODE_STATIC 0 #define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1 #define FX_MODE_BLINK 1
@ -162,6 +162,7 @@
#define FX_MODE_METEOR_SMOOTH 77 #define FX_MODE_METEOR_SMOOTH 77
#define FX_MODE_RAILWAY 78 #define FX_MODE_RAILWAY 78
#define FX_MODE_RIPPLE 79 #define FX_MODE_RIPPLE 79
#define FX_MODE_TWINKLEFOX 80
class WS2812FX { class WS2812FX {
@ -216,6 +217,7 @@ class WS2812FX {
} segment_runtime; } segment_runtime;
WS2812FX() { WS2812FX() {
//assign each member of the _mode[] array to its respective function reference
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static; _mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
_mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe; _mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe;
@ -296,6 +298,7 @@ class WS2812FX {
_mode[FX_MODE_METEOR_SMOOTH] = &WS2812FX::mode_meteor_smooth; _mode[FX_MODE_METEOR_SMOOTH] = &WS2812FX::mode_meteor_smooth;
_mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway; _mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway;
_mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple; _mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple;
_mode[FX_MODE_TWINKLEFOX] = &WS2812FX::mode_twinklefox;
_brightness = DEFAULT_BRIGHTNESS; _brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black); currentPalette = CRGBPalette16(CRGB::Black);
@ -335,6 +338,7 @@ class WS2812FX {
trigger(void), trigger(void),
setSegment(uint8_t n, uint16_t start, uint16_t stop), setSegment(uint8_t n, uint16_t start, uint16_t stop),
resetSegments(), resetSegments(),
setPixelColor(uint16_t n, CRGB fastled),
setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint32_t c),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
show(void); show(void);
@ -361,6 +365,10 @@ class WS2812FX {
gamma8(uint8_t), gamma8(uint8_t),
get_random_wheel_index(uint8_t); get_random_wheel_index(uint8_t);
uint16_t
ablMilliampsMax,
currentMilliamps;
uint32_t uint32_t
color_wheel(uint8_t), color_wheel(uint8_t),
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255), color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255),
@ -378,21 +386,6 @@ class WS2812FX {
WS2812FX::Segment* WS2812FX::Segment*
getSegments(void); getSegments(void);
// mode helper functions
uint16_t
ablMilliampsMax,
currentMilliamps,
blink(uint32_t, uint32_t, bool strobe, bool),
color_wipe(uint32_t, uint32_t, bool , bool),
scan(bool),
theater_chase(uint32_t, uint32_t, bool),
running_base(bool),
dissolve(uint32_t),
chase(uint32_t, uint32_t, uint32_t, bool),
gradient_base(bool),
running(uint32_t, uint32_t),
tricolor_chase(uint32_t, uint32_t);
// builtin modes // builtin modes
uint16_t uint16_t
mode_static(void), mode_static(void),
@ -475,12 +468,14 @@ class WS2812FX {
mode_meteor(void), mode_meteor(void),
mode_meteor_smooth(void), mode_meteor_smooth(void),
mode_railway(void), mode_railway(void),
mode_ripple(void); mode_ripple(void),
mode_twinklefox(void);
private: private:
NeoPixelWrapper *bus; NeoPixelWrapper *bus;
CRGB fastled_from_col(uint32_t); uint32_t crgb_to_col(CRGB fastled);
CRGB col_to_crgb(uint32_t);
CRGBPalette16 currentPalette; CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette; CRGBPalette16 targetPalette;
@ -505,6 +500,20 @@ class WS2812FX {
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
// mode helper functions
uint16_t
blink(uint32_t, uint32_t, bool strobe, bool),
color_wipe(uint32_t, uint32_t, bool , bool),
scan(bool),
theater_chase(uint32_t, uint32_t, bool),
running_base(bool),
dissolve(uint32_t),
chase(uint32_t, uint32_t, uint32_t, bool),
gradient_base(bool),
running(uint32_t, uint32_t),
tricolor_chase(uint32_t, uint32_t);
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt);
uint32_t _lastPaletteChange = 0; uint32_t _lastPaletteChange = 0;
uint32_t _lastShow = 0; uint32_t _lastShow = 0;
@ -528,7 +537,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([
"Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","In Out","In In", "Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","In Out","In In",
"Out Out","Out In","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Out Out","Out In","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet",
"Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","BPM","Fill Noise","Noise 1", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","BPM","Fill Noise","Noise 1",
"Noise 2","Noise 3","Noise 4","Colortwinkle","Lake","Meteor","Smooth Meteor","Railway","Ripple" "Noise 2","Noise 3","Noise 4","Colortwinkle","Lake","Meteor","Smooth Meteor","Railway","Ripple","Twinklefox"
])====="; ])=====";
@ -537,7 +546,7 @@ const char JSON_palette_names[] PROGMEM = R"=====([
"Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash", "Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash",
"Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64", "Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64",
"Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn", "Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn",
"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night" "Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery"
])====="; ])=====";
#endif #endif

View File

@ -89,6 +89,10 @@ bool WS2812FX::modeUsesLock(uint8_t m)
return false; return false;
} }
void WS2812FX::setPixelColor(uint16_t n, CRGB fastled) {
setPixelColor(n, fastled.red, fastled.green, fastled.blue, 0);
}
void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { void WS2812FX::setPixelColor(uint16_t n, uint32_t c) {
uint8_t w = (c >> 24) & 0xFF; uint8_t w = (c >> 24) & 0xFF;
uint8_t r = (c >> 16) & 0xFF; uint8_t r = (c >> 16) & 0xFF;
@ -616,7 +620,7 @@ void WS2812FX::blur(uint8_t blur_amount)
CRGB carryover = CRGB::Black; CRGB carryover = CRGB::Black;
for(uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) for(uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++)
{ {
CRGB cur = fastled_from_col(getPixelColor(i)); CRGB cur = col_to_crgb(getPixelColor(i));
CRGB part = cur; CRGB part = cur;
part.nscale8(seep); part.nscale8(seep);
cur.nscale8(keep); cur.nscale8(keep);
@ -668,7 +672,13 @@ uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) {
} }
CRGB WS2812FX::fastled_from_col(uint32_t color) uint32_t WS2812FX::crgb_to_col(CRGB fastled)
{
return (((uint32_t)fastled.red << 16) | ((uint32_t)fastled.green << 8) | fastled.blue);
}
CRGB WS2812FX::col_to_crgb(uint32_t color)
{ {
CRGB fastled_col; CRGB fastled_col;
fastled_col.red = (color >> 16 & 0xFF); fastled_col.red = (color >> 16 & 0xFF);
@ -720,11 +730,11 @@ void WS2812FX::handle_palette(void)
_lastPaletteChange = millis(); _lastPaletteChange = millis();
} break;} } break;}
case 2: {//primary color only case 2: {//primary color only
CRGB prim = fastled_from_col(SEGCOLOR(0)); CRGB prim = col_to_crgb(SEGCOLOR(0));
targetPalette = CRGBPalette16(prim); break;} targetPalette = CRGBPalette16(prim); break;}
case 3: {//based on primary case 3: {//based on primary
//considering performance implications //considering performance implications
CRGB prim = fastled_from_col(SEGCOLOR(0)); CRGB prim = col_to_crgb(SEGCOLOR(0));
CHSV prim_hsv = rgb2hsv_approximate(prim); CHSV prim_hsv = rgb2hsv_approximate(prim);
targetPalette = CRGBPalette16( targetPalette = CRGBPalette16(
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v), //color itself CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v), //color itself
@ -733,12 +743,12 @@ void WS2812FX::handle_palette(void)
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v)); //color itself CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v)); //color itself
break;} break;}
case 4: {//primary + secondary case 4: {//primary + secondary
CRGB prim = fastled_from_col(SEGCOLOR(0)); CRGB prim = col_to_crgb(SEGCOLOR(0));
CRGB sec = fastled_from_col(SEGCOLOR(1)); CRGB sec = col_to_crgb(SEGCOLOR(1));
targetPalette = CRGBPalette16(sec,prim); break;} targetPalette = CRGBPalette16(sec,prim); break;}
case 5: {//based on primary + secondary case 5: {//based on primary + secondary
CRGB prim = fastled_from_col(SEGCOLOR(0)); CRGB prim = col_to_crgb(SEGCOLOR(0));
CRGB sec = fastled_from_col(SEGCOLOR(1)); CRGB sec = col_to_crgb(SEGCOLOR(1));
targetPalette = CRGBPalette16(sec,prim,CRGB::White); break;} targetPalette = CRGBPalette16(sec,prim,CRGB::White); break;}
case 6: //Party colors case 6: //Party colors
targetPalette = PartyColors_p; break; targetPalette = PartyColors_p; break;

View File

@ -536,6 +536,16 @@ DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
244, 1, 5, 45, 244, 1, 5, 45,
255, 1, 5, 45}; 255, 1, 5, 45};
DEFINE_GRADIENT_PALETTE( Orangery_gp ) {
0, 255, 173, 23,
35, 255, 82, 0,
70, 196, 19, 10,
105, 255, 140, 45,
140, 255, 69, 0,
175, 158, 13, 11,
210, 241, 95, 17,
255, 213, 37, 4};
// Single array of defined cpt-city color palettes. // Single array of defined cpt-city color palettes.
// This will let us programmatically choose one based on // This will let us programmatically choose one based on
@ -581,7 +591,8 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
Blue_Cyan_Yellow_gp, //43-30 Yelblu Blue_Cyan_Yellow_gp, //43-30 Yelblu
Orange_Teal_gp, //44-31 Orange & Teal Orange_Teal_gp, //44-31 Orange & Teal
Tiamat_gp, //45-32 Tiamat Tiamat_gp, //45-32 Tiamat
April_Night_gp //46-33 April Night April_Night_gp, //46-33 April Night
Orangery_gp //47-34 Orangery
}; };

View File

@ -98,7 +98,7 @@
//version code in format yymmddb (b = daily build) //version code in format yymmddb (b = daily build)
#define VERSION 1908251 #define VERSION 1908301
char versionString[] = "0.8.5-dev"; char versionString[] = "0.8.5-dev";