Added Halloween Eyes effect

Added Twinklecat
This commit is contained in:
cschwinne 2019-10-02 01:17:26 +02:00
parent 4390aee1e0
commit 4b4b93ac04
4 changed files with 125 additions and 30 deletions

View File

@ -45,21 +45,35 @@ uint16_t WS2812FX::mode_static(void) {
* if(strobe == true) then create a strobe effect * if(strobe == true) then create a strobe effect
*/ */
uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) { uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) {
uint32_t color = ((SEGENV.call & 1) == 0) ? color1 : color2; uint16_t stateTime = SEGENV.aux1;
uint32_t cycleTime = (255 - SEGMENT.speed)*20;
uint32_t onTime = 0;
uint32_t offTime = cycleTime;
if (!strobe) {
onTime = (cycleTime * SEGMENT.intensity) >> 8;
offTime = cycleTime - onTime;
}
stateTime = ((SEGENV.aux0 & 1) == 0) ? onTime : offTime;
stateTime += 20;
if (now - SEGENV.step > stateTime)
{
SEGENV.aux0++;
SEGENV.aux1 = stateTime;
SEGENV.step = now;
}
uint32_t color = ((SEGENV.aux0 & 1) == 0) ? color1 : color2;
if (color == color1 && do_palette) if (color == color1 && do_palette)
{ {
for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) {
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
} }
} else { } else fill(color);
fill(color);
}
if((SEGENV.call & 1) == 0) { return 20;
return strobe ? 20 : (100 + ((1986 * (uint32_t)(255 - SEGMENT.speed)) / 255))*(float)(SEGMENT.intensity/128.0);
} else {
return strobe ? 50 + ((1986 * (uint32_t)(255 - SEGMENT.speed)) / 255) : (100 + ((1986 * (uint32_t)(255 - SEGMENT.speed)) / 255))*(float)(2.0-(SEGMENT.intensity/128.0));
}
} }
@ -2044,7 +2058,7 @@ uint16_t WS2812FX::mode_ripple()
uint16_t origin = SEGMENT.start + random16(SEGLEN); uint16_t origin = SEGMENT.start + random16(SEGLEN);
_locked[storeI+1] = origin >> 8; _locked[storeI+1] = origin >> 8;
_locked[storeI+2] = origin & 0xFF; _locked[storeI+2] = origin & 0xFF;
_locked[storeI+3] = random8(); _locked[storeI+3] = random8(); //color
} }
} }
} }
@ -2062,7 +2076,7 @@ uint16_t WS2812FX::mode_ripple()
// incandescent bulbs change color as they get dim down. // incandescent bulbs change color as they get dim down.
#define COOL_LIKE_INCANDESCENT 1 #define COOL_LIKE_INCANDESCENT 1
CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt) CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat)
{ {
// Overall twinkle speed (changed) // Overall twinkle speed (changed)
uint16_t ticks = ms / (32 - (SEGMENT.speed >> 3)); uint16_t ticks = ms / (32 - (SEGMENT.speed >> 3));
@ -2083,6 +2097,10 @@ CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt)
// This is like 'triwave8', which produces a // This is like 'triwave8', which produces a
// symmetrical up-and-down triangle sawtooth waveform, except that this // symmetrical up-and-down triangle sawtooth waveform, except that this
// function produces a triangle wave with a faster attack and a slower decay // function produces a triangle wave with a faster attack and a slower decay
if (cat) //twinklecat, variant where the leds instantly turn on
{
bright = 255 - ph;
} else { //vanilla twinklefox
if (ph < 86) { if (ph < 86) {
bright = ph * 3; bright = ph * 3;
} else { } else {
@ -2090,6 +2108,7 @@ CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt)
bright = 255 - (ph + (ph/2)); bright = 255 - (ph + (ph/2));
} }
} }
}
uint8_t hue = slowcycle8 - salt; uint8_t hue = slowcycle8 - salt;
CRGB c; CRGB c;
@ -2117,7 +2136,7 @@ CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt)
// "CalculateOneTwinkle" on each pixel. It then displays // "CalculateOneTwinkle" on each pixel. It then displays
// either the twinkle color of the background color, // either the twinkle color of the background color,
// whichever is brighter. // whichever is brighter.
uint16_t WS2812FX::mode_twinklefox() void WS2812FX::twinklefox_base(bool cat)
{ {
// "PRNG16" is the pseudorandom number generator // "PRNG16" is the pseudorandom number generator
// It MUST be reset to the same starting value each time // It MUST be reset to the same starting value each time
@ -2125,8 +2144,6 @@ uint16_t WS2812FX::mode_twinklefox()
// numbers that it generates is (paradoxically) stable. // numbers that it generates is (paradoxically) stable.
uint16_t PRNG16 = 11337; uint16_t PRNG16 = 11337;
uint32_t clock32 = millis();
// Set up the background color, "bg". // Set up the background color, "bg".
// if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of // if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of
// the current palette are identical, then a deeply faded version of // the current palette are identical, then a deeply faded version of
@ -2151,13 +2168,13 @@ uint16_t WS2812FX::mode_twinklefox()
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number 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) // 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; uint8_t myspeedmultiplierQ5_3 = ((((PRNG16 & 0xFF)>>4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08;
uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16; uint32_t myclock30 = (uint32_t)((now * myspeedmultiplierQ5_3) >> 3) + myclockoffset16;
uint8_t myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel uint8_t myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel
// We now have the adjusted 'clock' for this pixel, now we call // We now have the adjusted 'clock' for this pixel, now we call
// the function that computes what color the pixel should be based // the function that computes what color the pixel should be based
// on the "brightness = f( time )" idea. // on the "brightness = f( time )" idea.
CRGB c = twinklefox_one_twinkle(myclock30, myunique8); CRGB c = twinklefox_one_twinkle(myclock30, myunique8, cat);
uint8_t cbright = c.getAverageLight(); uint8_t cbright = c.getAverageLight();
int16_t deltabright = cbright - backgroundBrightness; int16_t deltabright = cbright - backgroundBrightness;
@ -2175,5 +2192,74 @@ uint16_t WS2812FX::mode_twinklefox()
setPixelColor(i, bg); setPixelColor(i, bg);
} }
} }
}
uint16_t WS2812FX::mode_twinklefox()
{
twinklefox_base(false);
return 20;
}
uint16_t WS2812FX::mode_twinklecat()
{
twinklefox_base(true);
return 20;
}
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
#define HALLOWEEN_EYE_SPACE 3
#define HALLOWEEN_EYE_WIDTH 1
uint16_t WS2812FX::mode_halloween_eyes()
{
uint16_t eyeLength = (2*HALLOWEEN_EYE_WIDTH) + HALLOWEEN_EYE_SPACE;
if (eyeLength > SEGLEN) return mode_static(); //bail if segment too short
fill(SEGCOLOR(1)); //fill background
uint8_t state = SEGENV.aux1 >> 8;
uint16_t stateTime = SEGENV.call;
if (stateTime == 0) stateTime = 2000;
if (state == 0) { //spawn eyes
SEGENV.aux0 = random(SEGMENT.start, SEGMENT.stop - eyeLength); //start pos
SEGENV.aux1 = random8(); //color
state = 1;
}
if (state < 2) { //fade eyes
uint16_t startPos = SEGENV.aux0;
uint16_t start2ndEye = startPos + HALLOWEEN_EYE_WIDTH + HALLOWEEN_EYE_SPACE;
uint32_t fadestage = (now - SEGENV.step)*255 / stateTime;
if (fadestage > 255) fadestage = 255;
uint32_t c = color_blend(color_from_palette(SEGENV.aux1 & 0xFF, false, false, 0), SEGCOLOR(1), fadestage);
for (uint16_t i = 0; i < HALLOWEEN_EYE_WIDTH; i++)
{
setPixelColor(startPos + i, c);
setPixelColor(start2ndEye + i, c);
}
}
if (now - SEGENV.step > stateTime)
{
state++;
if (state > 2) state = 0;
if (state < 2)
{
stateTime = 100 + (255 - SEGMENT.intensity)*10; //eye fade time
} else {
uint16_t eyeOffTimeBase = (255 - SEGMENT.speed)*10;
stateTime = eyeOffTimeBase + random(eyeOffTimeBase);
}
SEGENV.step = now;
SEGENV.call = stateTime;
}
SEGENV.aux1 = (SEGENV.aux1 & 0xFF) + (state << 8); //save state
return 20; 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 81 #define MODE_COUNT 83
#define FX_MODE_STATIC 0 #define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1 #define FX_MODE_BLINK 1
@ -163,6 +163,8 @@
#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 #define FX_MODE_TWINKLEFOX 80
#define FX_MODE_TWINKLECAT 81
#define FX_MODE_HALLOWEEN_EYES 82
class WS2812FX { class WS2812FX {
@ -299,6 +301,8 @@ class WS2812FX {
_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; _mode[FX_MODE_TWINKLEFOX] = &WS2812FX::mode_twinklefox;
_mode[FX_MODE_TWINKLECAT] = &WS2812FX::mode_twinklecat;
_mode[FX_MODE_HALLOWEEN_EYES] = &WS2812FX::mode_halloween_eyes;
_brightness = DEFAULT_BRIGHTNESS; _brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black); currentPalette = CRGBPalette16(CRGB::Black);
@ -469,7 +473,9 @@ class WS2812FX {
mode_meteor_smooth(void), mode_meteor_smooth(void),
mode_railway(void), mode_railway(void),
mode_ripple(void), mode_ripple(void),
mode_twinklefox(void); mode_twinklefox(void),
mode_twinklecat(void),
mode_halloween_eyes(void);
private: private:
NeoPixelWrapper *bus; NeoPixelWrapper *bus;
@ -479,6 +485,7 @@ class WS2812FX {
CRGBPalette16 currentPalette; CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette; CRGBPalette16 targetPalette;
uint32_t now;
uint16_t _length; uint16_t _length;
uint16_t _rand16seed; uint16_t _rand16seed;
uint8_t _brightness; uint8_t _brightness;
@ -486,6 +493,7 @@ class WS2812FX {
void handle_palette(void); void handle_palette(void);
void fill(uint32_t); void fill(uint32_t);
bool modeUsesLock(uint8_t); bool modeUsesLock(uint8_t);
void twinklefox_base(bool);
bool bool
_modeUsesLock, _modeUsesLock,
@ -513,7 +521,7 @@ class WS2812FX {
running(uint32_t, uint32_t), running(uint32_t, uint32_t),
tricolor_chase(uint32_t, uint32_t); tricolor_chase(uint32_t, uint32_t);
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt); CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
uint32_t _lastPaletteChange = 0; uint32_t _lastPaletteChange = 0;
uint32_t _lastShow = 0; uint32_t _lastShow = 0;
@ -536,8 +544,9 @@ const char JSON_mode_names[] PROGMEM = R"=====([
"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream", "Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream",
"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 2","Noise 3","Noise 4","Colortwinkle","Lake","Meteor","Smooth Meteor","Railway","Ripple","Twinklefox" "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple",
"Twinklefox","Twinklecat","Halloween Eyes"
])====="; ])=====";

View File

@ -55,7 +55,7 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
} }
void WS2812FX::service() { void WS2812FX::service() {
unsigned long now = millis(); // Be aware, millis() rolls over every 49 days now = millis(); // Be aware, millis() rolls over every 49 days
if (now - _lastShow < MIN_SHOW_DELAY) return; if (now - _lastShow < MIN_SHOW_DELAY) return;
bool doShow = false; bool doShow = false;
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++) for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
@ -69,7 +69,7 @@ void WS2812FX::service() {
handle_palette(); handle_palette();
uint16_t delay = (this->*_mode[SEGMENT.mode])(); uint16_t delay = (this->*_mode[SEGMENT.mode])();
SEGENV.next_time = now + delay; SEGENV.next_time = now + delay;
SEGENV.call++; if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
} }
} }
} }

View File

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