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);
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);
setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
@ -1570,7 +1570,7 @@ uint16_t WS2812FX::mode_juggle(void){
byte dothue = 0;
for ( byte i = 0; i < 8; i++) {
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);
setPixelColor(index, fastled_col.red, fastled_col.green, fastled_col.blue);
dothue += 32;
@ -1696,7 +1696,7 @@ uint16_t WS2812FX::mode_colorwaves(void)
bri8 += (255 - brightdepth);
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);
setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
@ -1836,7 +1836,7 @@ uint16_t WS2812FX::mode_colortwinkle()
CRGB fastled_col, prev;
fract8 fadeUpAmount = 8 + (SEGMENT.speed/4), fadeDownAmount = 5 + (SEGMENT.speed/7);
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;
if(_locked[i]) {
CRGB incrementalColor = fastled_col;
@ -1848,7 +1848,7 @@ uint16_t WS2812FX::mode_colortwinkle()
}
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;
setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
@ -2050,3 +2050,130 @@ uint16_t WS2812FX::mode_ripple()
}
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_SELECTED ((SEGMENT.options & SELECTED) == SELECTED )
#define MODE_COUNT 80
#define MODE_COUNT 81
#define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1
@ -162,6 +162,7 @@
#define FX_MODE_METEOR_SMOOTH 77
#define FX_MODE_RAILWAY 78
#define FX_MODE_RIPPLE 79
#define FX_MODE_TWINKLEFOX 80
class WS2812FX {
@ -216,6 +217,7 @@ class WS2812FX {
} segment_runtime;
WS2812FX() {
//assign each member of the _mode[] array to its respective function reference
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
_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_RAILWAY] = &WS2812FX::mode_railway;
_mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple;
_mode[FX_MODE_TWINKLEFOX] = &WS2812FX::mode_twinklefox;
_brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black);
@ -335,6 +338,7 @@ class WS2812FX {
trigger(void),
setSegment(uint8_t n, uint16_t start, uint16_t stop),
resetSegments(),
setPixelColor(uint16_t n, CRGB fastled),
setPixelColor(uint16_t n, uint32_t c),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
show(void);
@ -361,6 +365,10 @@ class WS2812FX {
gamma8(uint8_t),
get_random_wheel_index(uint8_t);
uint16_t
ablMilliampsMax,
currentMilliamps;
uint32_t
color_wheel(uint8_t),
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255),
@ -378,21 +386,6 @@ class WS2812FX {
WS2812FX::Segment*
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
uint16_t
mode_static(void),
@ -475,12 +468,14 @@ class WS2812FX {
mode_meteor(void),
mode_meteor_smooth(void),
mode_railway(void),
mode_ripple(void);
mode_ripple(void),
mode_twinklefox(void);
private:
NeoPixelWrapper *bus;
CRGB fastled_from_col(uint32_t);
uint32_t crgb_to_col(CRGB fastled);
CRGB col_to_crgb(uint32_t);
CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette;
@ -505,6 +500,20 @@ class WS2812FX {
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 _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",
"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",
"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",
"Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64",
"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

View File

@ -89,6 +89,10 @@ bool WS2812FX::modeUsesLock(uint8_t m)
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) {
uint8_t w = (c >> 24) & 0xFF;
uint8_t r = (c >> 16) & 0xFF;
@ -616,7 +620,7 @@ void WS2812FX::blur(uint8_t blur_amount)
CRGB carryover = CRGB::Black;
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;
part.nscale8(seep);
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;
fastled_col.red = (color >> 16 & 0xFF);
@ -720,11 +730,11 @@ void WS2812FX::handle_palette(void)
_lastPaletteChange = millis();
} break;}
case 2: {//primary color only
CRGB prim = fastled_from_col(SEGCOLOR(0));
CRGB prim = col_to_crgb(SEGCOLOR(0));
targetPalette = CRGBPalette16(prim); break;}
case 3: {//based on primary
//considering performance implications
CRGB prim = fastled_from_col(SEGCOLOR(0));
CRGB prim = col_to_crgb(SEGCOLOR(0));
CHSV prim_hsv = rgb2hsv_approximate(prim);
targetPalette = CRGBPalette16(
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
break;}
case 4: {//primary + secondary
CRGB prim = fastled_from_col(SEGCOLOR(0));
CRGB sec = fastled_from_col(SEGCOLOR(1));
CRGB prim = col_to_crgb(SEGCOLOR(0));
CRGB sec = col_to_crgb(SEGCOLOR(1));
targetPalette = CRGBPalette16(sec,prim); break;}
case 5: {//based on primary + secondary
CRGB prim = fastled_from_col(SEGCOLOR(0));
CRGB sec = fastled_from_col(SEGCOLOR(1));
CRGB prim = col_to_crgb(SEGCOLOR(0));
CRGB sec = col_to_crgb(SEGCOLOR(1));
targetPalette = CRGBPalette16(sec,prim,CRGB::White); break;}
case 6: //Party colors
targetPalette = PartyColors_p; break;

View File

@ -535,6 +535,16 @@ DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
229, 223, 45, 72, //pink
244, 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.
@ -581,7 +591,8 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
Blue_Cyan_Yellow_gp, //43-30 Yelblu
Orange_Teal_gp, //44-31 Orange & Teal
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)
#define VERSION 1908251
#define VERSION 1908301
char versionString[] = "0.8.5-dev";