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
*/
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)
{
for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) {
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
}
} else {
fill(color);
}
} else fill(color);
if((SEGENV.call & 1) == 0) {
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));
}
return 20;
}
@ -2044,7 +2058,7 @@ uint16_t WS2812FX::mode_ripple()
uint16_t origin = SEGMENT.start + random16(SEGLEN);
_locked[storeI+1] = origin >> 8;
_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.
#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)
uint16_t ticks = ms / (32 - (SEGMENT.speed >> 3));
@ -2083,11 +2097,16 @@ CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt)
// 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));
if (cat) //twinklecat, variant where the leds instantly turn on
{
bright = 255 - ph;
} else { //vanilla twinklefox
if (ph < 86) {
bright = ph * 3;
} else {
ph -= 86;
bright = 255 - (ph + (ph/2));
}
}
}
@ -2117,7 +2136,7 @@ CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt)
// "CalculateOneTwinkle" on each pixel. It then displays
// either the twinkle color of the background color,
// whichever is brighter.
uint16_t WS2812FX::mode_twinklefox()
void WS2812FX::twinklefox_base(bool cat)
{
// "PRNG16" is the pseudorandom number generator
// 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.
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
@ -2151,13 +2168,13 @@ uint16_t WS2812FX::mode_twinklefox()
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;
uint32_t myclock30 = (uint32_t)((now * 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);
CRGB c = twinklefox_one_twinkle(myclock30, myunique8, cat);
uint8_t cbright = c.getAverageLight();
int16_t deltabright = cbright - backgroundBrightness;
@ -2175,5 +2192,74 @@ uint16_t WS2812FX::mode_twinklefox()
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;
}

View File

@ -79,7 +79,7 @@
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
#define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED )
#define MODE_COUNT 81
#define MODE_COUNT 83
#define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1
@ -163,6 +163,8 @@
#define FX_MODE_RAILWAY 78
#define FX_MODE_RIPPLE 79
#define FX_MODE_TWINKLEFOX 80
#define FX_MODE_TWINKLECAT 81
#define FX_MODE_HALLOWEEN_EYES 82
class WS2812FX {
@ -299,6 +301,8 @@ class WS2812FX {
_mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway;
_mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple;
_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;
currentPalette = CRGBPalette16(CRGB::Black);
@ -469,7 +473,9 @@ class WS2812FX {
mode_meteor_smooth(void),
mode_railway(void),
mode_ripple(void),
mode_twinklefox(void);
mode_twinklefox(void),
mode_twinklecat(void),
mode_halloween_eyes(void);
private:
NeoPixelWrapper *bus;
@ -478,7 +484,8 @@ class WS2812FX {
CRGB col_to_crgb(uint32_t);
CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette;
uint32_t now;
uint16_t _length;
uint16_t _rand16seed;
uint8_t _brightness;
@ -486,6 +493,7 @@ class WS2812FX {
void handle_palette(void);
void fill(uint32_t);
bool modeUsesLock(uint8_t);
void twinklefox_base(bool);
bool
_modeUsesLock,
@ -513,7 +521,7 @@ class WS2812FX {
running(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 _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",
"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","Twinklefox"
"Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","BPM","Fill Noise",
"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() {
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;
bool doShow = false;
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
@ -69,7 +69,7 @@ void WS2812FX::service() {
handle_palette();
uint16_t delay = (this->*_mode[SEGMENT.mode])();
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)
#define VERSION 1909194
#define VERSION 1910012
char versionString[] = "0.8.5";