diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index b97ae8e5..5912966a 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -1,8 +1,12 @@ //this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103 +#ifndef NpbWrapper_h +#define NpbWrapper_h //#define WORKAROUND_ESP32_BITBANG //see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support +#define LEDPIN 2 //strip pin. Only effective for ESP32, ESP8266 must use gpio2 + //uncomment this if red and green are swapped //#define SWAPRG @@ -13,9 +17,12 @@ #else #define PIXELMETHOD NeoEsp32RmtWS2813_V3Method #endif -#else +#else //esp8266 +//you may change to DMA method on pin GPIO3 here #define PIXELMETHOD NeoEsp8266Uart800KbpsMethod +//#define PIXELMETHOD NeoEsp8266Dma800KbpsMethod #endif + //handle swapping Red and Green automatically #ifdef SWAPRG #define PIXELFEATURE3 NeoRgbFeature @@ -52,7 +59,7 @@ public: cleanup(); } - void Begin(NeoPixelType type, uint16_t countPixels, uint8_t pin) + void Begin(NeoPixelType type, uint16_t countPixels) { cleanup(); _type = type; @@ -60,12 +67,12 @@ public: switch (_type) { case NeoPixelType_Grb: - _pGrb = new NeoPixelBrightnessBus(countPixels, pin); + _pGrb = new NeoPixelBrightnessBus(countPixels, LEDPIN); _pGrb->Begin(); break; case NeoPixelType_Grbw: - _pGrbw = new NeoPixelBrightnessBus(countPixels, pin); + _pGrbw = new NeoPixelBrightnessBus(countPixels, LEDPIN); _pGrbw->Begin(); break; } @@ -110,7 +117,7 @@ public: void SetPixelColor(uint16_t indexPixel, RgbwColor color) { switch (_type) { - case NeoPixelType_Grb: _pGrbw->SetPixelColor(indexPixel, color); break; + case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); break; case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break; } } @@ -174,3 +181,4 @@ private: } } }; +#endif diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp index 9b2e0e74..505f0ba8 100644 --- a/wled00/WS2812FX.cpp +++ b/wled00/WS2812FX.cpp @@ -4,13 +4,13 @@ www.aldick.org FEATURES * A lot of blinken modes and counting - * WS2812FX can be used as drop-in replacement for Adafruit Neopixel Library + * WS2812FX can be used as drop-in replacement for Adafruit NeoPixel Library NOTES - * Uses the Adafruit Neopixel library. Get it here: + * Uses the Adafruit NeoPixel library. Get it here: https://github.com/adafruit/Adafruit_NeoPixel LICENSE The MIT License (MIT) - Copyright (c) 2016 Harm Aldick + Copyright (c) 2016 Harm Aldick Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights @@ -30,1876 +30,115 @@ 2016-05-28 Initial beta release 2016-06-03 Code cleanup, minor improvements, new modes 2016-06-04 2 new fx, fixed setColor (now also resets _mode_color) + 2017-02-02 added external trigger functionality (e.g. for sound-to-light) + 2017-02-02 removed "blackout" on mode, speed or color-change + 2017-09-26 implemented segment and reverse features + 2017-11-16 changed speed calc, reduced memory footprint + 2018-02-24 added hooks for user created custom effects + Modified for WLED */ -#include "Arduino.h" #include "WS2812FX.h" +#include "FastLED.h" -#define CALL_MODE(n) (this->*_mode[n])(); - -void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t pin,bool skipFirst) { - begin(supportWhite,countPixels,pin,skipFirst); - for (int i=0; i < _led_count; i++) _locked[i] = false; - WS2812FX::setBrightness(_brightness); +void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst) +{ + if (supportWhite == _rgbwMode && countPixels == _length && _locked != NULL) return; + RESET_RUNTIME; + _rgbwMode = supportWhite; + _skipFirstMode = skipFirst; + _length = countPixels; + if (_skipFirstMode) _length++; + uint8_t ty = 1; + if (supportWhite) ty =2; + bus->Begin((NeoPixelType)ty, _length); + if (_locked != NULL) delete _locked; + _locked = new byte[_length]; + _segments[0].start = 0; + _segments[0].stop = _length -1; + unlockAll(); + setBrightness(_brightness); show(); + _running = true; } void WS2812FX::service() { if(_running || _triggered) { - unsigned long now = millis(); - - if(now - _mode_last_call_time > _mode_delay || _triggered) { - CALL_MODE(_mode_index); - _counter_mode_call++; - _mode_last_call_time = now; - _triggered = false; - } - } -} - -void WS2812FX::trigger() { - _triggered = true; -} - -void WS2812FX::start() { - _counter_mode_call = 0; - _counter_mode_step = 0; - _mode_last_call_time = 0; - _running = true; - show(); -} - -void WS2812FX::stop() { - _running = false; - strip_off(); -} - -void WS2812FX::setMode(byte m) { - _counter_mode_call = 0; - _counter_mode_step = 0; - _mode_last_call_time = 0; - _mode_index = constrain(m, 0, MODE_COUNT-1); - _mode_color = _color; - _mode_var1 = 0; - setBrightness(_brightness); - strip_off_respectLock(); -} - -void WS2812FX::setSpeed(byte s) { - _mode_last_call_time = 0; - _speed = constrain(s, SPEED_MIN, SPEED_MAX); -} - -void WS2812FX::increaseSpeed(byte s) { - s = constrain(_speed + s, SPEED_MIN, SPEED_MAX); - setSpeed(s); -} - -void WS2812FX::decreaseSpeed(byte s) { - s = constrain(_speed - s, SPEED_MIN, SPEED_MAX); - setSpeed(s); -} - -void WS2812FX::setIntensity(byte in) { - _intensity=in; -} - -void WS2812FX::setColor(byte r, byte g, byte b) { - setColor(((uint32_t)r << 16) | ((uint32_t)g << 8) | b); -} - - -void WS2812FX::setColor(byte r, byte g, byte b, byte w) { - setColor(((uint32_t)w << 24)|((uint32_t)r << 16) | ((uint32_t)g << 8) | b); -} - -void WS2812FX::setSecondaryColor(byte r, byte g, byte b) { - setSecondaryColor(((uint32_t)r << 16) | ((uint32_t)g << 8) | b); -} - - -void WS2812FX::setSecondaryColor(byte r, byte g, byte b, byte w) { - setSecondaryColor(((uint32_t)w << 24)|((uint32_t)r << 16) | ((uint32_t)g << 8) | b); -} - -void WS2812FX::setColor(uint32_t c) { - _color = c; - _mode_color = _color; - setBrightness(_brightness); -} - -void WS2812FX::setSecondaryColor(uint32_t c) { - _color_sec = c; - if (_cronixieMode) _cronixieSecMultiplier = getSafePowerMultiplier(900, 100, c, _brightness); - setBrightness(_brightness); -} - -void WS2812FX::increaseBrightness(byte s) { - s = constrain(_brightness + s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - setBrightness(s); -} - -void WS2812FX::decreaseBrightness(byte s) { - s = constrain(_brightness - s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - setBrightness(s); -} - -bool WS2812FX::isRunning() { - return _running; -} - -byte WS2812FX::getMode(void) { - return _mode_index; -} - -byte WS2812FX::getSpeed(void) { - return _speed; -} - -byte WS2812FX::getBrightness(void) { - return _brightness; -} - -byte WS2812FX::getModeCount(void) { - return MODE_COUNT; -} - -uint32_t WS2812FX::getColor(void) { - return _color; -} - -/* ##################################################### -# -# Color and Blinken Functions -# -##################################################### */ - -/* - * Turns everything off. Doh. - */ -void WS2812FX::strip_off() { - clear(); - show(); -} - -void WS2812FX::strip_off_respectLock() { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, 0); - } - show(); -} - - -/* - * Put a value 0 to 255 in to get a color value. - * The colours are a transition r -> g -> b -> back to r - * Inspired by the Adafruit examples. - */ -uint32_t WS2812FX::color_wheel(byte pos) { - pos = 255 - pos; - if(pos < 85) { - return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3); - } else if(pos < 170) { - pos -= 85; - return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3); - } else { - pos -= 170; - return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0); - } -} - - -/* - * Returns a new, random wheel index with a minimum distance of 42 from pos. - */ -byte WS2812FX::get_random_wheel_index(byte pos) { - byte r = 0; - byte x = 0; - byte y = 0; - byte d = 0; - - while(d < 42) { - r = random(256); - x = abs(pos - r); - y = 255 - x; - d = minval(x, y); - } - - return r; -} - - -/* - * No blinking. Just plain old static light. - */ -void WS2812FX::mode_static(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - show(); - _mode_delay = (_fastStandard) ? 25 : 500; -} - - -/* - * Normal blinking. on/off duty time set by FX intensity. - */ -void WS2812FX::mode_blink(void) { - if(_counter_mode_call % 2 == 1) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - _mode_delay = (100 + ((1986 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX))*(float)(_intensity/128.0); - } else { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - _mode_delay = (100 + ((1986 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX))*(float)(2.0-(_intensity/128.0)); - } - show(); -} - - -/* - * Lights all LEDs after each other up. Then turns them in - * that order off (2nd color). Repeat. - */ -void WS2812FX::mode_color_wipe(void) { - if(_counter_mode_step < _led_count) { - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, _color); - } else { - if (!_locked[_counter_mode_step - _led_count]) - setPixelColor(_counter_mode_step - _led_count, _color_sec); - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % (_led_count * 2); - - _mode_delay = 5 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Turns all LEDs after each other to a random color. - * Then starts over with another color. - */ -void WS2812FX::mode_color_wipe_random(void) { - if(_counter_mode_step == 0) { - _mode_color = get_random_wheel_index(_mode_color); - } - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, color_wheel(_mode_color)); - show(); - - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - - _mode_delay = 5 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Lights all LEDs in one random color up. Then switches them - * to the next random color. - */ -void WS2812FX::mode_random_color(void) { - _mode_color = get_random_wheel_index(_mode_color); - - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(_mode_color)); - } - - show(); - _mode_delay = 100 + ((5000 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Lights some pastel colors - */ -void WS2812FX::mode_easter(void) { - //uint32_t cols[]{0x00F7ECC5,0x00F8D5C7,0x00F9E2E7,0x00BED9D4,0x00F7ECC5,0x00F8D5C7,0x00F9E2E7}; - uint32_t cols[]{0x00FF8040,0x00E5D241,0x0077FF77,0x0077F0F0,0x00FF8040,0x00E5D241,0x0077FF77}; - mode_colorful_internal(cols); -} - - -/* - * Lights multiple random leds in a random color (higher intensity, more updates) - */ -void WS2812FX::mode_dynamic(void) { - if(_counter_mode_call == 0) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(random(256))); - } - } - if (_intensity > 0) //multi dynamic - { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i] && random(256)<_intensity) - setPixelColor(i, color_wheel(random(256))); - } - } else { //single dynamic - int ran = random(_led_count); - if (!_locked[ran]) - setPixelColor(ran, color_wheel(random(256))); - } - show(); - _mode_delay = 100 + ((5000 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Does the "standby-breathing" of well known i-Devices. Fixed Speed. - * Use mode "fade" if you like to have something similar with a different speed. - */ -void WS2812FX::mode_breath(void) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // step - uint16_t breath_delay_steps[] = { 7, 9, 13, 15, 16, 17, 18, 930, 19, 18, 15, 13, 9, 7, 4, 5, 10 }; // magic numbers for breathing LED - byte breath_brightness_steps[] = { 150, 125, 100, 75, 50, 25, 16, 15, 16, 25, 50, 75, 100, 125, 150, 220, 255 }; // even more magic numbers! - - if(_counter_mode_call == 0) { - _mode_color = breath_brightness_steps[0] + 1; - } - - byte breath_brightness = _mode_color; // we use _mode_color to store the brightness - - if(_counter_mode_step < 8) { - breath_brightness--; - } else { - breath_brightness++; - } - - // update index of current delay when target brightness is reached, start over after the last step - if(breath_brightness == breath_brightness_steps[_counter_mode_step]) { - _counter_mode_step = (_counter_mode_step + 1) % (sizeof(breath_brightness_steps)/sizeof(byte)); - } - - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); // set all LEDs to selected color - } - int b = map(breath_brightness, 0, 255, 0, _brightness); // keep brightness below brightness set by user - bus->SetBrightness(b); // set new brightness to leds - show(); - - _mode_color = breath_brightness; // we use _mode_color to store the brightness - _mode_delay = breath_delay_steps[_counter_mode_step]; -} - - -/* - * Fades the LEDs on and (almost) off again. - */ -void WS2812FX::mode_fade(void) { - - int y = _counter_mode_step - 127; - y = 256 - (abs(y) * 2); - double z = (double)y/256; - byte w = ((_color >> 24) & 0xFF), ws = ((_color_sec >> 24) & 0xFF); - byte r = ((_color >> 16) & 0xFF), rs = ((_color_sec >> 16) & 0xFF); - byte g = ((_color >> 8) & 0xFF), gs = ((_color_sec >> 8) & 0xFF); - byte b = (_color & 0xFF), bs = (_color_sec & 0xFF); - w = w+((ws - w)*z); - r = r+((rs - r)*z); - g = g+((gs - g)*z); - b = b+((bs - b)*z); - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, r, g, b, w); - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % 256; - _mode_delay = 5 + ((15 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Runs a single pixel back and forth. - */ -void WS2812FX::mode_scan(void) { - if(_counter_mode_step > (_led_count*2) - 2) { - _counter_mode_step = 0; - } - _counter_mode_step++; - - int i = _counter_mode_step - (_led_count - 1); - i = abs(i); - - for(uint16_t x=0; x < _led_count; x++) { - if (!_locked[x]) - setPixelColor(x, _color_sec); - } - if (!_locked[i]) - setPixelColor(abs(i), _color); - show(); - - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Runs two pixel back and forth in opposite directions. - */ -void WS2812FX::mode_dual_scan(void) { - if(_counter_mode_step > (_led_count*2) - 2) { - _counter_mode_step = 0; - } - _counter_mode_step++; - - int i = _counter_mode_step - (_led_count - 1); - i = abs(i); - for(uint16_t x=0; x < _led_count; x++) { - if (!_locked[x]) - setPixelColor(x, _color_sec); - } - if (!_locked[i]) - setPixelColor(i, _color); - if (!_locked[_led_count - (i+1)]) - setPixelColor(_led_count - (i+1), _color); - show(); - - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Cycles all LEDs at once through a rainbow. - */ -void WS2812FX::mode_rainbow(void) { - uint32_t color = color_wheel(_counter_mode_step); - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color); - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % 256; - - _mode_delay = 1 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Cycles a rainbow over the entire string of LEDs. - */ -void WS2812FX::mode_rainbow_cycle(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(((i * 256 / ((uint16_t)(_led_count*(float)(_intensity/128.0))+1)) + _counter_mode_step) % 256)); - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % 256; - - _mode_delay = 1 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Theatre-style crawling lights. - * Inspired by the Adafruit examples. - */ -void WS2812FX::mode_theater_chase(void) { - byte j = _counter_mode_call % 6; - if(j % 2 == 0) { - for(uint16_t i=0; i < _led_count; i=i+3) { - if (!_locked[i+(j/2)]) - setPixelColor(i+(j/2), _color); - } - show(); - _mode_delay = 50 + ((500 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); - } else { - for(uint16_t i=0; i < _led_count; i=i+3) { - if (!_locked[i+(j/2)]) - setPixelColor(i+(j/2), _color_sec); - } - _mode_delay = 1; - } -} - - -/* - * Theatre-style crawling lights with rainbow effect. - * Inspired by the Adafruit examples. - */ -void WS2812FX::mode_theater_chase_rainbow(void) { - byte j = _counter_mode_call % 6; - if(j % 2 == 0) { - for(uint16_t i=0; i < _led_count; i=i+3) { - if (!_locked[i+(j/2)]) - setPixelColor(i+(j/2), color_wheel((i+_counter_mode_step) % 256)); - } - show(); - _mode_delay = 50 + ((500 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); - } else { - for(uint16_t i=0; i < _led_count; i=i+3) { - if (!_locked[i+(j/2)]) - setPixelColor(i+(j/2), _color_sec); - } - _mode_delay = 1; - } - _counter_mode_step = (_counter_mode_step + 1) % 256; -} - - -/* - * Running lights effect with smooth sine transition. - */ -void WS2812FX::mode_running_lights(void) { - byte w = ((_color >> 24) & 0xFF); - byte r = ((_color >> 16) & 0xFF); - byte g = ((_color >> 8) & 0xFF); - byte b = (_color & 0xFF); - - for(uint16_t i=0; i < _led_count; i++) { - int s = (sin(i+_counter_mode_call) * 127) + 128; - if (!_locked[i]) - setPixelColor(i, (((uint32_t)(r * s)) / 255), (((uint32_t)(g * s)) / 255), (((uint32_t)(b * s)) / 255), (((uint32_t)(w * s)) / 255)); - } - - show(); - - _mode_delay = 35 + ((350 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Blink several LEDs on, reset, repeat. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -void WS2812FX::mode_twinkle(void) { - if(_counter_mode_step == 0) { - for (int i = 0; i < _led_count; i++) - { - setPixelColor(i, _color_sec); - } - uint16_t min_leds = maxval(1, _led_count/5); // make sure, at least one LED is on - uint16_t max_leds = maxval(1, _led_count/2); // make sure, at least one LED is on - _counter_mode_step = random(min_leds, max_leds); - } - int ran = random(_led_count); - if (!_locked[ran]) - setPixelColor(ran, _mode_color); - show(); - - _counter_mode_step--; - _mode_delay = 50 + ((1986 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Blink several LEDs in random colors on, reset, repeat. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -void WS2812FX::mode_twinkle_random(void) { - _mode_color = color_wheel(random(256)); - mode_twinkle(); -} - - -/* - * Blink several LEDs on, fading out. - */ -void WS2812FX::mode_twinkle_fade(void) { - - for(uint16_t i=0; i < _led_count; i++) { - uint32_t px_rgb = getPixelColor(i); - - byte px_w = (px_rgb & 0xFF000000) >> 24; - byte px_r = (px_rgb & 0x00FF0000) >> 16; - byte px_g = (px_rgb & 0x0000FF00) >> 8; - byte px_b = (px_rgb & 0x000000FF) >> 0; - - // fade out (divide by 2) - px_w = px_w >> 1; - px_r = px_r >> 1; - px_g = px_g >> 1; - px_b = px_b >> 1; - if (!_locked[i]) - setPixelColor(i, px_r, px_g, px_b, px_w); - } - - if(random(256) < _intensity) { - int ran = random(_led_count); - if (!_locked[ran]) - setPixelColor(ran, _mode_color); - } - - show(); - - _mode_delay = 100 + ((100 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Blink several LEDs in random colors on, fading out. - */ -void WS2812FX::mode_twinkle_fade_random(void) { - _mode_color = color_wheel(random(256)); - mode_twinkle_fade(); -} - - -/* - * Blinks one LED at a time. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -void WS2812FX::mode_sparkle(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - int ran = random(_led_count); - if (!_locked[ran]) - setPixelColor(ran ,_color); - show(); - _mode_delay = 10 + ((200 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Lights all LEDs in the _color. Flashes single secondary color pixels randomly. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -void WS2812FX::mode_flash_sparkle(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - - if(random(256) <= _intensity) { - int ran = random(_led_count); - if (!_locked[ran]) - setPixelColor(ran , _color_sec); - _mode_delay = 20; - } else { - _mode_delay = 20 + ((200 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); - } - - show(); -} - - -/* - * Like flash sparkle. With more flash. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -void WS2812FX::mode_hyper_sparkle(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - - if(random(256) <= _intensity) { - for(uint16_t i=0; i < maxval(1, _led_count/3); i++) { - int ran = random(_led_count); - if (!_locked[ran]) - setPixelColor(ran , _color_sec); - } - _mode_delay = 20; - } else { - _mode_delay = 15 + ((120 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); - } - show(); -} - - -/* - * Classic Strobe effect. - */ -void WS2812FX::mode_strobe(void) { - if(_counter_mode_call % 2 == 0) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - _mode_delay = 20; - } else { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - _mode_delay = 50 + ((1986 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); - } - show(); -} - - -/* - * Strobe effect with different strobe count and pause, controlled by _speed. - */ -void WS2812FX::mode_multi_strobe(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - - if(_counter_mode_step < (2 * ((_speed / 10) + 1))) { - if(_counter_mode_step % 2 == 0) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - _mode_delay = 20; - } else { - _mode_delay = 50; - } - - } else { - _mode_delay = 100 + ((9 - (_speed % 10)) * 125); - } - - show(); - _counter_mode_step = (_counter_mode_step + 1) % ((2 * ((_speed / 10) + 1)) + 1); -} - - -/* - * Classic Strobe effect. Cycling through the rainbow. - */ -void WS2812FX::mode_strobe_rainbow(void) { - if(_counter_mode_call % 2 == 0) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(_counter_mode_call % 256)); - } - _mode_delay = 20; - } else { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - _mode_delay = 50 + ((1986 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); - } - show(); -} - - -/* - * Classic Blink effect. Cycling through the rainbow. - */ -void WS2812FX::mode_blink_rainbow(void) { - if(_counter_mode_call % 2 == 1) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(_counter_mode_call % 256)); - } - } else { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - } - show(); - _mode_delay = 100 + ((1986 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - - -/* - * Android loading circle - */ -void WS2812FX::mode_android(void) { - if (_counter_mode_call == 0) _mode_color = 0; //we use modecolor as bool - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - - uint16_t a = _counter_mode_step; - if (_mode_var1 > ((float)_intensity/255.0)*(float)_led_count) - { - _mode_color = 1; - } else - { - if (_mode_var1 < 2) _mode_color = 0; - } - - if (_mode_color == 0) - { - if (_counter_mode_call %3 == 1) {a++;} - else {_mode_var1++;} - } else - { - a++; - if (_counter_mode_call %3 != 1) _mode_var1--; - } - - if (a >= _led_count) a = 0; - - if (a +_mode_var1 <= _led_count) - { - for(int i = a; i < a+_mode_var1; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - } else - { - for(int i = a; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - for(int i = 0; i < _mode_var1 - (_led_count - a); i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - } - _counter_mode_step = a; - - show(); - _mode_delay = 3 + ((8 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * _color_sec running on _color. - */ -void WS2812FX::mode_chase_color(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - - uint16_t n = _counter_mode_step; - uint16_t m = (_counter_mode_step + 1) % _led_count; - if (!_locked[n]) - setPixelColor(n, _color); - if (!_locked[m]) - setPixelColor(m, _color); - show(); - - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * color_sec running followed by random color. - */ -void WS2812FX::mode_chase_random(void) { - if(_counter_mode_step == 0) { - if (!_locked[_led_count-1]) - setPixelColor(_led_count-1, color_wheel(_mode_color)); - _mode_color = get_random_wheel_index(_mode_color); - } - - for(uint16_t i=0; i < _counter_mode_step; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(_mode_color)); - } - - uint16_t n = _counter_mode_step; - uint16_t m = (_counter_mode_step + 1) % _led_count; - if (!_locked[n]) - setPixelColor(n, _color_sec); - if (!_locked[m]) - setPixelColor(m, _color_sec); - - show(); - - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * color_sec running on rainbow. - */ -void WS2812FX::mode_chase_rainbow(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(((i * 256 / _led_count) + (_counter_mode_call % 256)) % 256)); - } - - uint16_t n = _counter_mode_step; - uint16_t m = (_counter_mode_step + 1) % _led_count; - if (!_locked[n]) - setPixelColor(n, _color_sec); - if (!_locked[m]) - setPixelColor(m, _color_sec); - show(); - - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * _color_sec flashes running on _color. - */ -void WS2812FX::mode_chase_flash(void) { - const static byte flash_count = 4; - byte flash_step = _counter_mode_call % ((flash_count * 2) + 1); - - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color); - } - - if(flash_step < (flash_count * 2)) { - if(flash_step % 2 == 0) { - uint16_t n = _counter_mode_step; - uint16_t m = (_counter_mode_step + 1) % _led_count; - if (!_locked[n]) - setPixelColor(n, _color_sec); - if (!_locked[m]) - setPixelColor(m, _color_sec); - _mode_delay = 20; - } else { - _mode_delay = 30; - } - } else { - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); - } - - show(); -} - - -/* - * _color_sec flashes running, followed by random color. - */ -void WS2812FX::mode_chase_flash_random(void) { - const static byte flash_count = 4; - byte flash_step = _counter_mode_call % ((flash_count * 2) + 1); - - for(uint16_t i=0; i < _counter_mode_step; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(_mode_color)); - } - - if(flash_step < (flash_count * 2)) { - uint16_t n = _counter_mode_step; - uint16_t m = (_counter_mode_step + 1) % _led_count; - if(flash_step % 2 == 0) { - if (!_locked[n]) - setPixelColor(n, _color_sec); - if (!_locked[m]) - setPixelColor(m, _color_sec); - _mode_delay = 20; - } else { - if (!_locked[n]) - setPixelColor(n, color_wheel(_mode_color)); - if (!_locked[m]) - setPixelColor(m, 0, 0, 0); - _mode_delay = 30; - } - } else { - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - _mode_delay = 1 + ((10 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); - - if(_counter_mode_step == 0) { - _mode_color = get_random_wheel_index(_mode_color); - } - } - - show(); -} - - -/* - * Rainbow running on _color_sec. - */ -void WS2812FX::mode_chase_rainbow_white(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - - uint16_t n = _counter_mode_step; - uint16_t m = (_counter_mode_step + 1) % _led_count; - if (!_locked[n]) - setPixelColor(n, color_wheel(((n * 256 / _led_count) + (_counter_mode_call % 256)) % 256)); - if (!_locked[m]) - setPixelColor(m, color_wheel(((m * 256 / _led_count) + (_counter_mode_call % 256)) % 256)); - show(); - - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -/* - * Red - Amber - Green - Blue lights running - */ -void WS2812FX::mode_colorful(void) { - uint32_t cols[]{0x00FF0000,0x00EEBB00,0x0000EE00,0x000077CC,0x00FF0000,0x00EEBB00,0x0000EE00}; - mode_colorful_internal(cols); -} - -/* - * Common function for 4-color-running (Colorful, easter) - */ -void WS2812FX::mode_colorful_internal(uint32_t cols[]) { - int i = 0; - for (i; i < _led_count ; i+=4) - { - if(!_locked[i])setPixelColor(i, cols[_counter_mode_step]); - if(!_locked[i+1])setPixelColor(i+1, cols[_counter_mode_step+1]); - if(!_locked[i+2])setPixelColor(i+2, cols[_counter_mode_step+2]); - if(!_locked[i+3])setPixelColor(i+3, cols[_counter_mode_step+3]); - } - i+=4; - if(i < _led_count && !_locked[i]) - { - setPixelColor(i, cols[_counter_mode_step]); - - if(i+1 < _led_count && !_locked[i+1]) - { - setPixelColor(i+1, cols[_counter_mode_step+1]); - - if(i+2 < _led_count && !_locked[i+2]) - { - setPixelColor(i+2, cols[_counter_mode_step+2]); + unsigned long now = millis(); // Be aware, millis() rolls over every 49 days + bool doShow = false; + for(uint8_t i=0; i < _num_segments; i++) { + _segment_index = i; + if(now > SEGMENT_RUNTIME.next_time || _triggered) { + doShow = true; + uint16_t delay = (this->*_mode[SEGMENT.mode])(); + SEGMENT_RUNTIME.next_time = now + max(delay, 5); + SEGMENT_RUNTIME.counter_mode_call++; } } + if(doShow) { + show(); + } + _triggered = false; } - - show(); - if (_speed > SPEED_MIN) _counter_mode_step++; //static if lowest speed - if (_counter_mode_step >3) _counter_mode_step = 0; - _mode_delay = 50 + (15 * (uint32_t)(SPEED_MAX - _speed)); } +void WS2812FX::clear() +{ + bus->ClearTo(RgbColor(0)); +} -/* - * Emulates a traffic light. - */ -void WS2812FX::mode_traffic_light(void) { - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - for (int i = 0; i < _led_count-2 ; i+=3) +void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { + uint8_t w = (c >> 24) & 0xFF; + uint8_t r = (c >> 16) & 0xFF; + uint8_t g = (c >> 8) & 0xFF; + uint8_t b = c & 0xFF; + setPixelColor(n, r, g, b, w); +} + +void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) +{ + if (_reverseMode) i = _length - 1 -i; + if (_locked[i] && SEGMENT.mode != FX_MODE_FIRE_2012) return; + if (IS_REVERSE) i = SEGMENT.stop - (i - SEGMENT.start); //reverse just individual segment + if (!_cronixieMode) { - switch (_counter_mode_step) - { - case 0: if(!_locked[i])setPixelColor(i, 0x00FF0000); _mode_delay = 150 + (100 * (uint32_t)(SPEED_MAX - _speed));break; - case 1: if(!_locked[i])setPixelColor(i, 0x00FF0000); _mode_delay = 150 + (20 * (uint32_t)(SPEED_MAX - _speed)); if(!_locked[i+1])setPixelColor(i+1, 0x00EECC00); break; - case 2: if(!_locked[i+2])setPixelColor(i+2, 0x0000FF00); _mode_delay = 150 + (100 * (uint32_t)(SPEED_MAX - _speed));break; - case 3: if(!_locked[i+1])setPixelColor(i+1, 0x00EECC00); _mode_delay = 150 + (20 * (uint32_t)(SPEED_MAX - _speed));break; - } - } - show(); - _counter_mode_step++; - if (_counter_mode_step >3) _counter_mode_step = 0; -} - - -/* - * Random color intruduced alternating from start and end of strip. - */ -void WS2812FX::mode_color_sweep_random(void) { - if(_counter_mode_step == 0 || _counter_mode_step == _led_count) { - _mode_color = get_random_wheel_index(_mode_color); - } - - if(_counter_mode_step < _led_count) { - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, color_wheel(_mode_color)); + if (_skipFirstMode) {i++;if(i==1)bus->SetPixelColor(i, RgbwColor(0,0,0,0));} + bus->SetPixelColor(i, RgbwColor(r,g,b,w)); } else { - if (!_locked[(_led_count * 2) - _counter_mode_step - 1]) - setPixelColor((_led_count * 2) - _counter_mode_step - 1, color_wheel(_mode_color)); - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % (_led_count * 2); - _mode_delay = 5 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Alternating color/2nd pixels running. - */ -void WS2812FX::mode_running_color(void) { - for(uint16_t i=0; i < _led_count; i++) { - if((i + _counter_mode_step) % 4 < 2) { - if (!_locked[i]) - setPixelColor(i, _mode_color); - } else { - if (!_locked[i]) - setPixelColor(i, _color_sec); - } - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % 4; - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Alternating red/blue pixels running. (RED) - */ -void WS2812FX::mode_running_red_blue(void) { - for(uint16_t i=0; i < _led_count; i++) { - if((i + _counter_mode_step) % 4 < 2) { - if (!_locked[i]) - setPixelColor(i, 255, 0, 0); - } else { - if (!_locked[i]) - setPixelColor(i, 0, 0, 255); - } - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % 4; - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Random colored pixels running. - */ -void WS2812FX::mode_running_random(void) { - for(uint16_t i=_led_count-1; i > 0; i--) { - if (!_locked[i]) + if(i>6)return; + byte o = 10*i; + if (_cronixieBacklightEnabled && _cronixieDigits[i] <11) { - if (!_locked[i-1]) + byte rCorr = (int)(((double)((_segments[0].colors[1]>>16) & 0xFF))*_cronixieSecMultiplier); + byte gCorr = (int)(((double)((_segments[0].colors[1]>>8) & 0xFF))*_cronixieSecMultiplier); + byte bCorr = (int)(((double)((_segments[0].colors[1]) & 0xFF))*_cronixieSecMultiplier); + byte wCorr = (int)(((double)((_segments[0].colors[1]>>24) & 0xFF))*_cronixieSecMultiplier); + for (int j=o; j< o+19; j++) { - setPixelColor(i, getPixelColor(i-1)); - } else + bus->SetPixelColor((_skipFirstMode)?j+1:j,RgbwColor(rCorr,gCorr,bCorr,wCorr)); + } + } else + { + for (int j=o; j< o+19; j++) { - setPixelColor(i, color_wheel(_mode_color)); + bus->SetPixelColor((_skipFirstMode)?j+1:j,RgbwColor(0,0,0,0)); } } - } - - if(_counter_mode_step == 0) { - _mode_color = get_random_wheel_index(_mode_color); - if (!_locked[0]) - setPixelColor(0, color_wheel(_mode_color)); - } - - show(); - - _counter_mode_step = (_counter_mode_step + 1) % 2; - - _mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * K.I.T.T. - */ -void WS2812FX::mode_larson_scanner(void) { - - for(uint16_t i=0; i < _led_count; i++) { - uint32_t px_rgb = getPixelColor(i); - - byte px_r = (px_rgb & 0x00FF0000) >> 16; - byte px_g = (px_rgb & 0x0000FF00) >> 8; - byte px_b = (px_rgb & 0x000000FF) >> 0; - - // fade out (divide by 2) - px_r = px_r >> 1; - px_g = px_g >> 1; - px_b = px_b >> 1; - - if (!_locked[i]) - setPixelColor(i, px_r, px_g, px_b); - } - - uint16_t pos = 0; - - if(_counter_mode_step < _led_count) { - pos = _counter_mode_step; - } else { - pos = (_led_count * 2) - _counter_mode_step - 2; - } - - if (!_locked[pos]) - setPixelColor(pos, _color); - show(); - - _counter_mode_step = (_counter_mode_step + 1) % ((_led_count * 2) - 2); - _mode_delay = 10 + ((10 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Fireing comets from one end. - */ -void WS2812FX::mode_comet(void) { - - for(uint16_t i=0; i < _led_count; i++) { - uint32_t px_rgb = getPixelColor(i); - - byte px_r = (px_rgb & 0x00FF0000) >> 16; - byte px_g = (px_rgb & 0x0000FF00) >> 8; - byte px_b = (px_rgb & 0x000000FF) >> 0; - - // fade out (divide by 2) - px_r = px_r >> 1; - px_g = px_g >> 1; - px_b = px_b >> 1; - - if (!_locked[i]) - setPixelColor(i, px_r, px_g, px_b); - } - - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, _color); - show(); - - _counter_mode_step = (_counter_mode_step + 1) % _led_count; - _mode_delay = 10 + ((10 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - - -/* - * Firework sparks. - */ -void WS2812FX::mode_fireworks(void) { - uint32_t px_rgb = 0; - byte px_r = 0; - byte px_g = 0; - byte px_b = 0; - - for(uint16_t i=0; i < _led_count; i++) { - px_rgb = getPixelColor(i); - - px_r = (px_rgb & 0x00FF0000) >> 16; - px_g = (px_rgb & 0x0000FF00) >> 8; - px_b = (px_rgb & 0x000000FF) >> 0; - - // fade out (divide by 2) - px_r = px_r >> 1; - px_g = px_g >> 1; - px_b = px_b >> 1; - - if (!_locked[i]) - setPixelColor(i, px_r, px_g, px_b); - } - - // first LED has only one neighbour - px_r = (((getPixelColor(1) & 0x00FF0000) >> 16) >> 1) + ((getPixelColor(0) & 0x00FF0000) >> 16); - px_g = (((getPixelColor(1) & 0x0000FF00) >> 8) >> 1) + ((getPixelColor(0) & 0x0000FF00) >> 8); - px_b = (((getPixelColor(1) & 0x000000FF) >> 0) >> 1) + ((getPixelColor(0) & 0x000000FF) >> 0); - if (!_locked[0]) - setPixelColor(0, px_r, px_g, px_b); - - // set brightness(i) = ((brightness(i-1)/2 + brightness(i+1)) / 2) + brightness(i) - for(uint16_t i=1; i < _led_count-1; i++) { - px_r = (( - (((getPixelColor(i-1) & 0x00FF0000) >> 16) >> 1) + - (((getPixelColor(i+1) & 0x00FF0000) >> 16) >> 0) ) >> 1) + - (((getPixelColor(i ) & 0x00FF0000) >> 16) >> 0); - - px_g = (( - (((getPixelColor(i-1) & 0x0000FF00) >> 8) >> 1) + - (((getPixelColor(i+1) & 0x0000FF00) >> 8) >> 0) ) >> 1) + - (((getPixelColor(i ) & 0x0000FF00) >> 8) >> 0); - - px_b = (( - (((getPixelColor(i-1) & 0x000000FF) >> 0) >> 1) + - (((getPixelColor(i+1) & 0x000000FF) >> 0) >> 0) ) >> 1) + - (((getPixelColor(i ) & 0x000000FF) >> 0) >> 0); - - if (!_locked[i]) - setPixelColor(i, px_r, px_g, px_b); - } - - // last LED has only one neighbour - px_r = (((getPixelColor(_led_count-2) & 0x00FF0000) >> 16) >> 2) + ((getPixelColor(_led_count-1) & 0x00FF0000) >> 16); - px_g = (((getPixelColor(_led_count-2) & 0x0000FF00) >> 8) >> 2) + ((getPixelColor(_led_count-1) & 0x0000FF00) >> 8); - px_b = (((getPixelColor(_led_count-2) & 0x000000FF) >> 0) >> 2) + ((getPixelColor(_led_count-1) & 0x000000FF) >> 0); - if (!_locked[_led_count-1]) - setPixelColor(_led_count-1, px_r, px_g, px_b); - - for(uint16_t i=0; i> 24; - byte p_r = (_color & 0x00FF0000) >> 16; - byte p_g = (_color & 0x0000FF00) >> 8; - byte p_b = (_color & 0x000000FF) >> 0; - byte flicker_val = maxval(p_r,maxval(p_g, maxval(p_b, p_w)))/(((256-_intensity)/16)+1); - for(uint16_t i=0; i < _led_count; i++) + switch(_cronixieDigits[i]) { - int flicker = random(0,flicker_val); - int r1 = p_r-flicker; - int g1 = p_g-flicker; - int b1 = p_b-flicker; - int w1 = p_w-flicker; - if(g1<0) g1=0; - if(r1<0) r1=0; - if(b1<0) b1=0; - if(w1<0) w1=0; - if (!_locked[i]) - setPixelColor(i,r1,g1,b1,w1); - } - show(); - _mode_delay = 10 + ((400 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - -/* - * Gradient run - */ -void WS2812FX::mode_gradient(void) { - byte p_w = (_color & 0xFF000000) >> 24; - byte p_r = (_color & 0x00FF0000) >> 16; - byte p_g = (_color & 0x0000FF00) >> 8; - byte p_b = (_color & 0x000000FF) >> 0; - byte p_w2 = (_color_sec & 0xFF000000) >> 24; - byte p_r2 = (_color_sec & 0x00FF0000) >> 16; - byte p_g2 = (_color_sec & 0x0000FF00) >> 8; - byte p_b2 = (_color_sec & 0x000000FF) >> 0; - byte nw,nr,ng,nb; - float per,val; //0.0 = sec 1.0 = pri - float brd = _intensity/2; if (brd <1.0) brd = 1.0; - int pp = _counter_mode_step; - int p1 = pp-_led_count; - int p2 = pp+_led_count; - - for(uint16_t i=0; i < _led_count; i++) - { - if (!_locked[i]) - { - val = minval(abs(pp-i),minval(abs(p1-i),abs(p2-i))); - per = val/brd; - if (per >1.0) per = 1.0; - nw = p_w+((p_w2 - p_w)*per); - nr = p_r+((p_r2 - p_r)*per); - ng = p_g+((p_g2 - p_g)*per); - nb = p_b+((p_b2 - p_b)*per); - setPixelColor(i,nr,ng,nb,nw); - } - } - - show(); - _counter_mode_step++; - if (_counter_mode_step >= _led_count) _counter_mode_step = 0; - if (_speed == 0) _counter_mode_step = _led_count >> 1; - _mode_delay = 7 + ((25 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -/* - * Gradient run with hard transition - */ -void WS2812FX::mode_loading(void) { - byte p_w = (_color & 0xFF000000) >> 24; - byte p_r = (_color & 0x00FF0000) >> 16; - byte p_g = (_color & 0x0000FF00) >> 8; - byte p_b = (_color & 0x000000FF) >> 0; - byte p_w2 = (_color_sec & 0xFF000000) >> 24; - byte p_r2 = (_color_sec & 0x00FF0000) >> 16; - byte p_g2 = (_color_sec & 0x0000FF00) >> 8; - byte p_b2 = (_color_sec & 0x000000FF) >> 0; - byte nw,nr,ng,nb; - float per,val; //0.0 = sec 1.0 = pri - float brd = _intensity; if (brd <1.0) brd = 1.0; - int pp = _counter_mode_step; - int p1 = pp+_led_count; - - for(uint16_t i=0; i < _led_count; i++) - { - if (!_locked[i]) - { - pp = _counter_mode_step; - if (i > pp) pp+=_led_count; - val = abs(pp-i); - per = val/brd; - if (per >1.0) per = 1.0; - nw = p_w+((p_w2 - p_w)*per); - nr = p_r+((p_r2 - p_r)*per); - ng = p_g+((p_g2 - p_g)*per); - nb = p_b+((p_b2 - p_b)*per); - setPixelColor(i,nr,ng,nb,nw); - } - } - - show(); - _counter_mode_step++; - if (_counter_mode_step >= _led_count) _counter_mode_step = 0; - if (_speed == 0) _counter_mode_step = _led_count -1; - _mode_delay = 7 + ((25 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -/* - * Lights all LEDs after each other up starting from the outer edges and - * finishing in the middle. Then turns them in reverse order off. Repeat. - */ -void WS2812FX::mode_dual_color_wipe_in_out(void) { - int end = _led_count - _counter_mode_step - 1; - bool odd = (_led_count % 2); - int mid = odd ? ((_led_count / 2) + 1) : (_led_count / 2); - if (_counter_mode_step < mid) { - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, _color); - if (!_locked[end]) - setPixelColor(end, _color); - } - else { - if (odd) { - // If odd, we need to 'double count' the center LED (once to turn it on, - // once to turn it off). So trail one behind after the middle LED. - if (!_locked[_counter_mode_step -1]) - setPixelColor(_counter_mode_step - 1, _color_sec); - if (!_locked[end+1]) - setPixelColor(end + 1, _color_sec); - } else { - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, _color_sec); - if (!_locked[end]) - setPixelColor(end, _color_sec); + case 0: bus->SetPixelColor((_skipFirstMode)?o+6:o+5,RgbwColor(r,g,b,w)); break; + case 1: bus->SetPixelColor((_skipFirstMode)?o+1:o+0,RgbwColor(r,g,b,w)); break; + case 2: bus->SetPixelColor((_skipFirstMode)?o+7:o+6,RgbwColor(r,g,b,w)); break; + case 3: bus->SetPixelColor((_skipFirstMode)?o+2:o+1,RgbwColor(r,g,b,w)); break; + case 4: bus->SetPixelColor((_skipFirstMode)?o+8:o+7,RgbwColor(r,g,b,w)); break; + case 5: bus->SetPixelColor((_skipFirstMode)?o+3:o+2,RgbwColor(r,g,b,w)); break; + case 6: bus->SetPixelColor((_skipFirstMode)?o+9:o+8,RgbwColor(r,g,b,w)); break; + case 7: bus->SetPixelColor((_skipFirstMode)?o+4:o+3,RgbwColor(r,g,b,w)); break; + case 8: bus->SetPixelColor((_skipFirstMode)?o+10:o+9,RgbwColor(r,g,b,w)); break; + case 9: bus->SetPixelColor((_skipFirstMode)?o+5:o+4,RgbwColor(r,g,b,w)); break; + default: break; } } - - _counter_mode_step++; - if (odd) { - if (_counter_mode_step > _led_count) { - _counter_mode_step = 0; - } - } else { - if (_counter_mode_step >= _led_count) { - _counter_mode_step = 0; - } - } - - show(); - - _mode_delay = 5 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -/* - * Lights all LEDs after each other up starting from the outer edges and - * finishing in the middle. Then turns them in that order off. Repeat. - */ -void WS2812FX::mode_dual_color_wipe_in_in(void) { - bool odd = (_led_count % 2); - int mid = _led_count / 2; - if (odd) { - if (_counter_mode_step <= mid) { - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, _color); - if (!_locked[_led_count - _counter_mode_step - 1]) - setPixelColor(_led_count - _counter_mode_step - 1, _color); - } else { - int i = _counter_mode_step - mid; - if (!_locked[i-1]) - setPixelColor(i - 1, _color_sec); - if (!_locked[_led_count - i]) - setPixelColor(_led_count - i, _color_sec); - } - } else { - if (_counter_mode_step < mid) { - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, _color); - if (!_locked[_led_count - _counter_mode_step - 1]) - setPixelColor(_led_count - _counter_mode_step - 1, _color); - } else { - int i = _counter_mode_step - mid; - if (!_locked[i]) - setPixelColor(i, _color_sec); - if (!_locked[_led_count - i -1]) - setPixelColor(_led_count - i - 1, _color_sec); - } - } - - _counter_mode_step++; - if (odd) { - if (_counter_mode_step > _led_count) { - _counter_mode_step = 0; - } - } else { - if (_counter_mode_step >= _led_count) { - _counter_mode_step = 0; - } - } - - show(); - - _mode_delay = 5 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -/* - * Lights all LEDs after each other up starting from the middle and - * finishing at the edges. Then turns them in that order off. Repeat. - */ -void WS2812FX::mode_dual_color_wipe_out_out(void) { - int end = _led_count - _counter_mode_step - 1; - bool odd = (_led_count % 2); - int mid = _led_count / 2; - - if (odd) { - if (_counter_mode_step <= mid) { - if (!_locked[mid + _counter_mode_step]) - setPixelColor(mid + _counter_mode_step, _color); - if (!_locked[mid - _counter_mode_step]) - setPixelColor(mid - _counter_mode_step, _color); - } else { - if (!_locked[_counter_mode_step -1]) - setPixelColor(_counter_mode_step - 1, _color_sec); - if (!_locked[end +1]) - setPixelColor(end + 1, _color_sec); - } - } else { - if (_counter_mode_step < mid) { - if (!_locked[mid - _counter_mode_step -1]) - setPixelColor(mid - _counter_mode_step - 1, _color); - if (!_locked[mid + _counter_mode_step]) - setPixelColor(mid + _counter_mode_step, _color); - } else { - if (!_locked[_counter_mode_step]) - setPixelColor(_counter_mode_step, 0); - if (!_locked[end]) - setPixelColor(end, _color_sec); - } - } - - _counter_mode_step++; - if (odd) { - if (_counter_mode_step > _led_count) { - _counter_mode_step = 0; - } - } else { - if (_counter_mode_step >= _led_count) { - _counter_mode_step = 0; - } - } - - show(); - - _mode_delay = 5 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -/* - * Lights all LEDs after each other up starting from the middle and - * finishing at the edges. Then turns them in reverse order off. Repeat. - */ -void WS2812FX::mode_dual_color_wipe_out_in(void) { - bool odd = (_led_count % 2); - int mid = _led_count / 2; - - if (odd) { - if (_counter_mode_step <= mid) { - if (!_locked[mid + _counter_mode_step]) - setPixelColor(mid + _counter_mode_step, _color); - if (!_locked[mid - _counter_mode_step]) - setPixelColor(mid - _counter_mode_step, _color); - } else { - int i = _counter_mode_step - mid; - if (!_locked[i -1]) - setPixelColor(i - 1, _color_sec); - if (!_locked[_led_count - i]) - setPixelColor(_led_count - i, _color_sec); - } - } else { - if (_counter_mode_step < mid) { - if (!_locked[mid - _counter_mode_step -1]) - setPixelColor(mid - _counter_mode_step - 1, _color); - if (!_locked[mid + _counter_mode_step]) - setPixelColor(mid + _counter_mode_step, _color); - } else { - int i = _counter_mode_step - mid; - if (!_locked[i]) - setPixelColor(i, _color_sec); - if (!_locked[_led_count - i -1]) - setPixelColor(_led_count - i - 1, _color_sec); - } - } - - _counter_mode_step++; - if (odd) { - if (_counter_mode_step > _led_count) { - _counter_mode_step = 0; - } - } else { - if (_counter_mode_step >= _led_count) { - _counter_mode_step = 0; - } - } - - show(); - - _mode_delay = 5 + ((50 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -/* - * Alternating pri/sec/black pixels running. - */ -void WS2812FX::mode_circus_combustus(void) { - for(uint16_t i=0; i < _led_count; i++) { - if((i + _counter_mode_step) % 6 < 2) { - if (!_locked[i]) - setPixelColor(i, _color); - } else if((i + _color) % 6 < 4){ - if (!_locked[i]) - setPixelColor(i, _color_sec); - } else { - if (!_locked[i]) - setPixelColor(i, 0, 0, 0); - } - } - show(); - - _counter_mode_step = (_counter_mode_step + 1) % 6; - _mode_delay = 100 + ((100 * (uint32_t)(SPEED_MAX - _speed)) / _led_count); -} - -void WS2812FX::mode_cc_core() -{ - for (int k = _cc_i1; k <= _cc_i2; k = k + _cc_num1 + _cc_num2) - { - for (int i = 0; i < _cc_num1; i++) - { - int num = 0; - num = ((k + i + _counter_ccStep) % _cc_i2) +_cc_i1; - if (_cc_fs) setPixelColor(num, _color); - if (_cc_fe) setPixelColor(_cc_i2 - num, _color); - } - } - show(); - _counter_ccStep = (_counter_ccStep + _ccStep) % (_cc_i2 - _cc_i1); - _mode_delay = 10 + ((250 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); -} - -void WS2812FX::mode_cc_standard() -{ - for(uint16_t i=0; i < _led_count; i++) - { - setPixelColor(i, (_cc_i1 <= i && i <= _cc_i2) ? _color_sec : _color); - } - mode_cc_core(); -} - -void WS2812FX::mode_cc_rainbow() -{ - uint32_t color = color_wheel(_counter_mode_step); - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color); - } - mode_cc_core(); - _counter_mode_step = (_counter_mode_step + 1) % 256; -} - -void WS2812FX::mode_cc_cycle() -{ - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(((i * 256 / _led_count) + _counter_mode_step) % 256)); - } - mode_cc_core(); - _counter_mode_step = (_counter_mode_step + 1) % 256; -} - -void WS2812FX::mode_cc_blink() -{ - for(uint16_t i=0; i < _led_count; i++) - { - setPixelColor(i, (_cc_i1 <= i && i <= _cc_i2) ? _color_sec : _color); - } - if (_counter_mode_step) - { - mode_cc_core(); - _counter_mode_step = 0; - } else { - show(); - _counter_mode_step = 1; - _mode_delay = 10 + ((250 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); - } -} - -void WS2812FX::mode_cc_random() -{ - for(uint16_t i=0; i < _led_count; i++) { - if (!_locked[i]) - setPixelColor(i, color_wheel(random(256))); - } - mode_cc_core(); -} - - -//WLED specific methods - -void WS2812FX::setIndividual(int i) -{ - if (i >= 0 && i < _led_count) - { - setPixelColor(i, _color); - //show(); - _locked[i] = true; - } -} - -void WS2812FX::setIndividual(int i, uint32_t col) -{ - if (i >= 0 && i < _led_count) - { - setPixelColor(i, col); - //show(); - _locked[i] = true; - } -} - -void WS2812FX::setRange(int i, int i2) -{ - if (i2 >= i) - { - for (int x = i; x <= i2; x++) - { - if (x >= 0 && x < _led_count) - { - setPixelColor(x, _color); - _locked[x] = true; - } - } - } else - { - for (int x = i2; x < _led_count; x++) - { - if (x >= 0 && x < _led_count) - { - setPixelColor(x, _color); - _locked[x] = true; - } - } - for (int x = 0; x <= i; x++) - { - if (x >= 0 && x < _led_count) - { - setPixelColor(x, _color); - _locked[x] = true; - } - } - } - //show(); -} - -void WS2812FX::setRange(int i, int i2, uint32_t col) -{ - if (i2 >= i) - { - for (int x = i; x <= i2; x++) - { - if (x >= 0 && x < _led_count) - { - setPixelColor(x, col); - _locked[x] = true; - } - } - } else - { - for (int x = i2; x < _led_count; x++) - { - if (x >= 0 && x < _led_count) - { - setPixelColor(x, col); - _locked[x] = true; - } - } - for (int x = 0; x <= i; x++) - { - if (x >= 0 && x < _led_count) - { - setPixelColor(x, col); - _locked[x] = true; - } - } - } - //show(); -} - -void WS2812FX::lock(int i) -{ - if (i >= 0 && i < _led_count) - _locked[i] = true; -} - -void WS2812FX::lockRange(int i, int i2) -{ - for (int x = i; x < i2; x++) - { - if (x >= 0 && x < _led_count) - _locked[x] = true; - } -} - -void WS2812FX::lockAll() -{ - for (int x = 0; x < _led_count; x++) - _locked[x] = true; -} - -void WS2812FX::unlock(int i) -{ - if (i >= 0 && i < _led_count) - _locked[i] = false; -} - -void WS2812FX::unlockRange(int i, int i2) -{ - for (int x = i; x < i2; x++) - { - if (x >= 0 && x < _led_count) - _locked[x] = false; - } -} - -void WS2812FX::unlockAll() -{ - for (int x = 0; x < _led_count; x++) - _locked[x] = false; -} - -void WS2812FX::setFastUpdateMode(bool y) -{ - _fastStandard = y; - if (_mode_index == 0) _mode_delay = 20; } void WS2812FX::setReverseMode(bool b) @@ -1910,6 +149,7 @@ void WS2812FX::setReverseMode(bool b) void WS2812FX::driverModeCronixie(bool b) { _cronixieMode = b; + if (b) _segments[0].stop = 5; } void WS2812FX::setCronixieBacklight(bool b) @@ -1925,12 +165,242 @@ void WS2812FX::setCronixieDigits(byte d[]) } } +void WS2812FX::show(void) { + bus->Show(); +} + +void WS2812FX::trigger() { + _triggered = true; +} + +void WS2812FX::setMode(uint8_t m) { + RESET_RUNTIME; + bool ua = _segments[0].mode == FX_MODE_FIRE_2012 && m != FX_MODE_FIRE_2012; + _segments[0].mode = constrain(m, 0, MODE_COUNT - 1); + if (ua) unlockAll(); + setBrightness(_brightness); +} + +//TODO transitions + +void WS2812FX::setSpeed(uint8_t s) { + _segments[0].speed = s; +} + +void WS2812FX::setIntensity(uint8_t in) { + _segments[0].intensity = in; +} + +void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { + setColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b); +} + +void WS2812FX::setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { + setSecondaryColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b); +} + +void WS2812FX::setColor(uint32_t c) { + _segments[0].colors[0] = c; + _triggered = true; +} + +void WS2812FX::setSecondaryColor(uint32_t c) { + _segments[0].colors[1] = c; + if (_cronixieMode) _cronixieSecMultiplier = getSafePowerMultiplier(900, 100, c, _brightness); + _triggered = true; +} + +void WS2812FX::setBrightness(uint8_t b) { + _brightness = b; + bus->SetBrightness(_brightness); + show(); +} + +uint8_t WS2812FX::getMode(void) { + return _segments[0].mode; +} + +uint8_t WS2812FX::getSpeed(void) { + return _segments[0].speed; +} + +uint8_t WS2812FX::getBrightness(void) { + return _brightness; +} + +uint8_t WS2812FX::getNumSegments(void) { + return _num_segments; +} + +void WS2812FX::setNumSegments(uint8_t n) { + _num_segments = n; +} + +uint32_t WS2812FX::getColor(void) { + return _segments[0].colors[0]; +} + +uint32_t WS2812FX::getPixelColor(uint16_t i) +{ + if (_reverseMode) i = _length- 1 -i; + if (_skipFirstMode) i++; + if (_cronixieMode) + { + if(i>6)return 0; + byte o = 10*i; + switch(_cronixieDigits[i]) + { + case 0: i=o+5; break; + case 1: i=o+0; break; + case 2: i=o+6; break; + case 3: i=o+1; break; + case 4: i=o+7; break; + case 5: i=o+2; break; + case 6: i=o+8; break; + case 7: i=o+3; break; + case 8: i=o+9; break; + case 9: i=o+4; break; + default: return 0; + } + } + RgbwColor lColor = bus->GetPixelColorRgbw(i); + return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B; +} + +WS2812FX::Segment WS2812FX::getSegment(void) { + return SEGMENT; +} + +WS2812FX::Segment_runtime WS2812FX::getSegmentRuntime(void) { + return SEGMENT_RUNTIME; +} + +WS2812FX::Segment* WS2812FX::getSegments(void) { + return _segments; +} + +void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint8_t speed, uint8_t intensity, bool reverse) { + uint32_t colors[] = {color, 0, 0}; + setSegment(n, start, stop, mode, colors, speed, intensity, reverse); +} + +void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, bool reverse) { + setSegment(n, start, stop, mode, colors, speed, intensity, (uint8_t)(reverse ? REVERSE : NO_OPTIONS)); +} + +void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, uint8_t options) { + if(n < (sizeof(_segments) / sizeof(_segments[0]))) { + if(n + 1 > _num_segments) _num_segments = n + 1; + _segments[n].start = start; + _segments[n].stop = stop; + _segments[n].mode = mode; + _segments[n].speed = speed; + _segments[n].intensity = intensity; + _segments[n].options = options; + + for(uint8_t i=0; i= 0 && i < _length) + { + _locked[i] = false; + setPixelColor(i, col); + _locked[i] = true; + } +} + +void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) +{ + if (i2 >= i) + { + for (uint16_t x = i; x <= i2; x++) setIndividual(x,col); + } else + { + for (uint16_t x = i2; x <= i; x++) setIndividual(x,col); + } +} + +void WS2812FX::lock(uint16_t i) +{ + if (SEGMENT.mode == FX_MODE_FIRE_2012) return; + if (i >= 0 && i < _length) _locked[i] = true; +} + +void WS2812FX::lockRange(uint16_t i, uint16_t i2) +{ + if (SEGMENT.mode == FX_MODE_FIRE_2012) return; + for (uint16_t x = i; x <= i2; x++) + { + if (i >= 0 && i < _length) _locked[i] = true; + } +} + +void WS2812FX::unlock(uint16_t i) +{ + if (SEGMENT.mode == FX_MODE_FIRE_2012) return; + if (i >= 0 && i < _length) _locked[i] = false; +} + +void WS2812FX::unlockRange(uint16_t i, uint16_t i2) +{ + if (SEGMENT.mode == FX_MODE_FIRE_2012) return; + for (uint16_t x = i; x < i2; x++) + { + if (x >= 0 && x < _length) _locked[x] = false; + } +} + +void WS2812FX::unlockAll() +{ + for (int i=0; i < _length; i++) _locked[i] = false; +} + +/* + * color blend function + */ +uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint8_t blend) { + if(blend == 0) return color1; + if(blend == 255) return color2; + + int w1 = (color1 >> 24) & 0xff; + int r1 = (color1 >> 16) & 0xff; + int g1 = (color1 >> 8) & 0xff; + int b1 = color1 & 0xff; + + int w2 = (color2 >> 24) & 0xff; + int r2 = (color2 >> 16) & 0xff; + int g2 = (color2 >> 8) & 0xff; + int b2 = color2 & 0xff; + + uint32_t w3 = ((w2 * blend) + (w1 * (255 - blend))) / 256; + uint32_t r3 = ((r2 * blend) + (r1 * (255 - blend))) / 256; + uint32_t g3 = ((g2 * blend) + (g1 * (255 - blend))) / 256; + uint32_t b3 = ((b2 * blend) + (b1 * (255 - blend))) / 256; + + return ((w3 << 24) | (r3 << 16) | (g3 << 8) | (b3)); +} + + double WS2812FX::getPowerEstimate(uint16_t leds, uint32_t c, byte b) { double _mARequired = 100; //ESP power double _mul = (double)b/255; double _sum = ((c & 0xFF000000) >> 24) + ((c & 0x00FF0000) >> 16) + ((c & 0x0000FF00) >> 8) + ((c & 0x000000FF) >> 0); - _sum /= (_rgbwMode)? 1024:768; + _sum /= (_rgbwMode)?1024:768; double _mAPerLed = 50*(_mul*_sum); _mARequired += leds*_mAPerLed; return _mARequired; @@ -1951,215 +421,1723 @@ double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uin return 1.0; } -void WS2812FX::setCCIndex1(byte i1) -{ - if (i1 < _led_count-1) _cc_i1 = i1; - if (_cc_i2 <= i1) _cc_i2 = i1+1; - _counter_ccStep = 0; + +/* ##################################################### +# +# Color and Blinken Functions +# +##################################################### */ + +/* + * Turns everything off. Doh. + */ +void WS2812FX::strip_off() { + clear(); + show(); } -void WS2812FX::setCCIndex2(uint16_t i2) -{ - if (i2 > _cc_i1) _cc_i2 = i2; - if (_cc_i2 >= _led_count) _cc_i2 = _led_count-1; - _counter_ccStep = 0; + +/* + * Put a value 0 to 255 in to get a color value. + * The colours are a transition r -> g -> b -> back to r + * Inspired by the Adafruit examples. + */ +uint32_t WS2812FX::color_wheel(uint8_t pos) { + pos = 255 - pos; + if(pos < 85) { + return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3); + } else if(pos < 170) { + pos -= 85; + return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3); + } else { + pos -= 170; + return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0); + } } -void WS2812FX::setCCStart(byte is) -{ - _cc_is = (is < _cc_i1 || is > _cc_i2) ? _cc_i1 : is; - _counter_ccStep = 0; + +/* + * Returns a new, random wheel index with a minimum distance of 42 from pos. + */ +uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) { + uint8_t r = 0; + uint8_t x = 0; + uint8_t y = 0; + uint8_t d = 0; + + while(d < 42) { + r = random8(); + x = abs(pos - r); + y = 255 - x; + d = min(x, y); + } + + return r; } -void WS2812FX::setCCNum1(byte np) -{ - _cc_num1 = np; - _counter_ccStep = 0; + +/* + * No blinking. Just plain old static light. + */ +uint16_t WS2812FX::mode_static(void) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + return 500; } -void WS2812FX::setCCNum2(byte ns) -{ - _cc_num2 = ns; - _counter_ccStep = 0; + +/* + * Blink/strobe function + * Alternate between color1 and color2 + * if(strobe == true) then create a strobe effect + */ +uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe) { + uint32_t color = ((SEGMENT_RUNTIME.counter_mode_call & 1) == 0) ? color1 : color2; + if(IS_REVERSE) color = (color == color1) ? color2 : color1; + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, color); + } + + if((SEGMENT_RUNTIME.counter_mode_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)); + } } -void WS2812FX::setCCStep(byte stp) -{ - _ccStep = stp; - _counter_ccStep = 0; + +/* + * Normal blinking. 50% on/off time. + */ +uint16_t WS2812FX::mode_blink(void) { + return blink(SEGMENT.colors[0], SEGMENT.colors[1], false); } -void WS2812FX::setCCFS(bool fs) -{ - _cc_fs = fs; - _cc_fe = (fs) ? _cc_fe : true; - _counter_ccStep = 0; + +/* + * Classic Blink effect. Cycling through the rainbow. + */ +uint16_t WS2812FX::mode_blink_rainbow(void) { + return blink(color_wheel(SEGMENT_RUNTIME.counter_mode_call & 0xFF), SEGMENT.colors[1], false); } -void WS2812FX::setCCFE(bool fe) -{ - _cc_fe = fe; - _cc_fs = (fe) ? _cc_fs : true; - _counter_ccStep = 0; + +/* + * Classic Strobe effect. + */ +uint16_t WS2812FX::mode_strobe(void) { + return blink(SEGMENT.colors[0], SEGMENT.colors[1], true); } -void WS2812FX::setCustomChase(byte i1, uint16_t i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe) -{ - setCCIndex1(i1); - setCCIndex2(i2); - setCCStart(is); - _cc_num1 = np; - _cc_num2 = ns; - _ccStep = stp; - setCCFS(fs); - setCCFE(fe); + +/* + * Classic Strobe effect. Cycling through the rainbow. + */ +uint16_t WS2812FX::mode_strobe_rainbow(void) { + return blink(color_wheel(SEGMENT_RUNTIME.counter_mode_call & 0xFF), SEGMENT.colors[1], true); } -//Added for quick NeoPixelBus compatibility with Adafruit syntax -void WS2812FX::setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w) -{ - if (_rgbwMode) + +/* + * Color wipe function + * LEDs are turned on (color1) in sequence, then turned off (color2) in sequence. + * if (bool rev == true) then LEDs are turned off in reverse order + */ +uint16_t WS2812FX::color_wipe(uint32_t color1, uint32_t color2, bool rev) { + if(SEGMENT_RUNTIME.counter_mode_step < SEGMENT_LENGTH) { + uint32_t led_offset = SEGMENT_RUNTIME.counter_mode_step; + setPixelColor(SEGMENT.start + led_offset, color1); + } else { + uint32_t led_offset = SEGMENT_RUNTIME.counter_mode_step - SEGMENT_LENGTH; + if(rev) { + setPixelColor(SEGMENT.stop - led_offset, color2); + } else { + setPixelColor(SEGMENT.start + led_offset, color2); + } + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % (SEGMENT_LENGTH * 2); + return SPEED_FORMULA_L; +} + + +/* + * Lights all LEDs one after another. + */ +uint16_t WS2812FX::mode_color_wipe(void) { + return color_wipe(SEGMENT.colors[0], SEGMENT.colors[1], false); +} + +/* + * Lights all LEDs one after another. Turns off opposite + */ +uint16_t WS2812FX::mode_color_sweep(void) { + return color_wipe(SEGMENT.colors[0], SEGMENT.colors[1], true); +} + + +/* + * Turns all LEDs after each other to a random color. + * Then starts over with another color. + */ +uint16_t WS2812FX::mode_color_wipe_random(void) { + if(SEGMENT_RUNTIME.counter_mode_step % SEGMENT_LENGTH == 0) { // aux_param will store our random color wheel index + SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + } + uint32_t color = color_wheel(SEGMENT_RUNTIME.aux_param); + return color_wipe(color, color, false); +} + + +/* + * Random color introduced alternating from start and end of strip. + */ +uint16_t WS2812FX::mode_color_sweep_random(void) { + if(SEGMENT_RUNTIME.counter_mode_step % SEGMENT_LENGTH == 0) { // aux_param will store our random color wheel index + SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + } + uint32_t color = color_wheel(SEGMENT_RUNTIME.aux_param); + return color_wipe(color, color, true); +} + + +/* + * Lights all LEDs in one random color up. Then switches them + * to the next random color. + */ +uint16_t WS2812FX::mode_random_color(void) { + SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); // aux_param will store our random color wheel index + uint32_t color = color_wheel(SEGMENT_RUNTIME.aux_param); + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, color); + } + return 50 + (20 * (uint32_t)(255 - SEGMENT.speed)); +} + + +/* + * Lights every LED in a random color. Changes all LED at the same time + * to new random colors. + */ +uint16_t WS2812FX::mode_dynamic(void) { + if(SEGMENT.intensity > 127 || SEGMENT_RUNTIME.counter_mode_call == 0) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, color_wheel(random8())); + } + } + setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), color_wheel(random8())); + return 50 + (15 * (uint32_t)(255 - SEGMENT.speed)); +} + + +/* + * Does the "standby-breathing" of well known i-Devices. Fixed Speed. + * Use mode "fade" if you like to have something similar with a different speed. + */ +uint16_t WS2812FX::mode_breath(void) { + int lum = SEGMENT_RUNTIME.counter_mode_step; + if(lum > 255) lum = 511 - lum; // lum = 15 -> 255 -> 15 + + uint16_t delay; + if(lum == 15) delay = 970; // 970 pause before each breath + else if(lum <= 25) delay = 38; // 19 + else if(lum <= 50) delay = 36; // 18 + else if(lum <= 75) delay = 28; // 14 + else if(lum <= 100) delay = 20; // 10 + else if(lum <= 125) delay = 14; // 7 + else if(lum <= 150) delay = 11; // 5 + else delay = 10; // 4 + + uint32_t color = SEGMENT.colors[0]; + uint8_t w = (color >> 24 & 0xFF) * lum / 256; + uint8_t r = (color >> 16 & 0xFF) * lum / 256; + uint8_t g = (color >> 8 & 0xFF) * lum / 256; + uint8_t b = (color & 0xFF) * lum / 256; + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, r, g, b, w); + } + + SEGMENT_RUNTIME.counter_mode_step += 2; + if(SEGMENT_RUNTIME.counter_mode_step > (512-15)) SEGMENT_RUNTIME.counter_mode_step = 15; + return delay; +} + + +/* + * Fades the LEDs between two colors + */ +uint16_t WS2812FX::mode_fade(void) { + int lum = SEGMENT_RUNTIME.counter_mode_step; + if(lum > 255) lum = 511 - lum; // lum = 0 -> 255 -> 0 + + uint32_t color = color_blend(SEGMENT.colors[0], SEGMENT.colors[1], lum); + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, color); + } + + SEGMENT_RUNTIME.counter_mode_step += 4; + if(SEGMENT_RUNTIME.counter_mode_step > 511) SEGMENT_RUNTIME.counter_mode_step = 0; + return 5 + ((15 * (uint32_t)(255 - SEGMENT.speed)) / 255); +} + + +//TODO add intensity (more than 1 pixel lit) +/* + * Runs a single pixel back and forth. + */ +uint16_t WS2812FX::mode_scan(void) { + if(SEGMENT_RUNTIME.counter_mode_step > (SEGMENT_LENGTH * 2) - 3) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[1]); + } + + int led_offset = SEGMENT_RUNTIME.counter_mode_step - (SEGMENT_LENGTH - 1); + led_offset = abs(led_offset); + setPixelColor(SEGMENT.start + led_offset, SEGMENT.colors[0]); + + SEGMENT_RUNTIME.counter_mode_step++; + return SPEED_FORMULA_L; +} + + +/* + * Runs two pixel back and forth in opposite directions. + */ +uint16_t WS2812FX::mode_dual_scan(void) { + if(SEGMENT_RUNTIME.counter_mode_step > (SEGMENT_LENGTH * 2) - 3) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, BLACK); + } + + int led_offset = SEGMENT_RUNTIME.counter_mode_step - (SEGMENT_LENGTH - 1); + led_offset = abs(led_offset); + + setPixelColor(SEGMENT.start + led_offset, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + SEGMENT_LENGTH - led_offset - 1, SEGMENT.colors[0]); + + SEGMENT_RUNTIME.counter_mode_step++; + return SPEED_FORMULA_L; +} + + +/* + * Cycles all LEDs at once through a rainbow. + */ +uint16_t WS2812FX::mode_rainbow(void) { + uint32_t color = color_wheel(SEGMENT_RUNTIME.counter_mode_step); + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, color); + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) & 0xFF; + return 1 + (((uint32_t)(255 - SEGMENT.speed)) / 5); +} + + +/* + * Cycles a rainbow over the entire string of LEDs. + */ +uint16_t WS2812FX::mode_rainbow_cycle(void) { + for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { + uint32_t color = color_wheel(((i * 256 / ((uint16_t)(SEGMENT_LENGTH*(float)(SEGMENT.intensity/128.0))+1)) + SEGMENT_RUNTIME.counter_mode_step) & 0xFF); + setPixelColor(SEGMENT.start + i, color); + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) & 0xFF; + return 1 + (((uint32_t)(255 - SEGMENT.speed)) / 5); +} + + +/* + * theater chase function + */ +uint16_t WS2812FX::theater_chase(uint32_t color1, uint32_t color2) { + SEGMENT_RUNTIME.counter_mode_call = SEGMENT_RUNTIME.counter_mode_call % 3; + for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { + if((i % 3) == SEGMENT_RUNTIME.counter_mode_call) { + setPixelColor(SEGMENT.start + i, color1); + } else { + setPixelColor(SEGMENT.start + i, color2); + } + } + return 50 + (2 * (uint32_t)(255 - SEGMENT.speed)); +} + + +/* + * Theatre-style crawling lights. + * Inspired by the Adafruit examples. + */ +uint16_t WS2812FX::mode_theater_chase(void) { + return theater_chase(SEGMENT.colors[0], SEGMENT.colors[1]); +} + + +/* + * Theatre-style crawling lights with rainbow effect. + * Inspired by the Adafruit examples. + */ +uint16_t WS2812FX::mode_theater_chase_rainbow(void) { + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) & 0xFF; + return theater_chase(color_wheel(SEGMENT_RUNTIME.counter_mode_step), SEGMENT.colors[1]); +} + + +/* + * Running lights effect with smooth sine transition. + */ +uint16_t WS2812FX::mode_running_lights(void) { + uint8_t w = ((SEGMENT.colors[0] >> 24) & 0xFF); + uint8_t r = ((SEGMENT.colors[0] >> 16) & 0xFF); + uint8_t g = ((SEGMENT.colors[0] >> 8) & 0xFF); + uint8_t b = (SEGMENT.colors[0] & 0xFF); + + for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { + int s = (sin(i+SEGMENT_RUNTIME.counter_mode_call) * 127) + 128; + setPixelColor(SEGMENT.start + i, (((uint32_t)(r * s)) / 255), (((uint32_t)(g * s)) / 255), (((uint32_t)(b * s)) / 255), (((uint32_t)(w * s)) / 255)); + } + + return 10 + (uint16_t)(255 - SEGMENT.speed); +} + + +/* + * twinkle function + */ +uint16_t WS2812FX::twinkle(uint32_t color) { + if(SEGMENT_RUNTIME.counter_mode_step == 0) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[1]); + } + uint16_t min_leds = max(1, SEGMENT_LENGTH / 5); // make sure, at least one LED is on + uint16_t max_leds = max(1, SEGMENT_LENGTH / 2); // make sure, at least one LED is on + SEGMENT_RUNTIME.counter_mode_step = random(min_leds, max_leds); + } + + setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), color); + + SEGMENT_RUNTIME.counter_mode_step--; + return 50 + (8 * (uint16_t)(255 - SEGMENT.speed)); +} + +/* + * Blink several LEDs on, reset, repeat. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +uint16_t WS2812FX::mode_twinkle(void) { + return twinkle(SEGMENT.colors[0]); +} + +/* + * Blink several LEDs in random colors on, reset, repeat. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +uint16_t WS2812FX::mode_twinkle_random(void) { + return twinkle(color_wheel(random8())); +} + + +/* + * fade out function + * fades out the current segment by dividing each pixel's intensity by 2 + */ +void WS2812FX::fade_out(uint8_t rate) { + static const float rateMap[] = {1.1, 1.20, 1.5, 2.0, 4.0, 8.0, 16.0, 64.0}; + if (rate > 7) rate = 7; + float mappedRate = rateMap[rate]; + + uint32_t color = SEGMENT.colors[1]; // target color + int w2 = (color >> 24) & 0xff; + int r2 = (color >> 16) & 0xff; + int g2 = (color >> 8) & 0xff; + int b2 = color & 0xff; + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + color = getPixelColor(i); + if(rate == 0) { // old fade-to-black algorithm + setPixelColor(i, (color >> 1) & 0x7F7F7F7F); + } else { // new fade-to-color algorithm + int w1 = (color >> 24) & 0xff; + int r1 = (color >> 16) & 0xff; + int g1 = (color >> 8) & 0xff; + int b1 = color & 0xff; + + int wdelta = (w2 - w1) / mappedRate; + int rdelta = (r2 - r1) / mappedRate; + int gdelta = (g2 - g1) / mappedRate; + int bdelta = (b2 - b1) / mappedRate; + + // if fade isn't complete, make sure delta is at least 1 (fixes rounding issues) + wdelta += (w2 == w1) ? 0 : (w2 > w1) ? 1 : -1; + rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1; + gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1; + bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1; + + setPixelColor(i, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); + } + } +} + + +/* + * twinkle_fade function + */ +uint16_t WS2812FX::twinkle_fade(uint32_t color) { + fade_out((255-SEGMENT.intensity) / 32); + + if(random8(3) == 0) { + setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), color); + } + return 100 + ((uint32_t)(255 - SEGMENT.speed)) / 3; +} + + +/* + * Blink several LEDs on, fading out. + */ +uint16_t WS2812FX::mode_twinkle_fade(void) { + return twinkle_fade(SEGMENT.colors[0]); +} + + +/* + * Blink several LEDs in random colors on, fading out. + */ +uint16_t WS2812FX::mode_twinkle_fade_random(void) { + return twinkle_fade(color_wheel(random8())); +} + + +/* + * Blinks one LED at a time. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +uint16_t WS2812FX::mode_sparkle(void) { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[1]); + SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH); // aux_param stores the random led index + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[0]); + return 10 + (uint16_t)(255 - SEGMENT.speed); +} + + +/* + * Lights all LEDs in the color. Flashes single white pixels randomly. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +uint16_t WS2812FX::mode_flash_sparkle(void) { + if(SEGMENT_RUNTIME.counter_mode_call == 0) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + } + + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[0]); + + if(random8(5) == 0) { + SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH); // aux_param stores the random led index + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[1]); + return 20; + } + return 20 + (uint16_t)(255-SEGMENT.speed); +} + + +/* + * Like flash sparkle. With more flash. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +uint16_t WS2812FX::mode_hyper_sparkle(void) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + + if(random8(5) < 2) { + for(uint16_t i=0; i < max(1, SEGMENT_LENGTH/3); i++) { + setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), SEGMENT.colors[1]); + } + return 20; + } + return 20 + (uint16_t)(255-SEGMENT.speed); +} + + +/* + * Strobe effect with different strobe count and pause, controlled by speed. + */ +uint16_t WS2812FX::mode_multi_strobe(void) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[1]); + } + + uint16_t delay = 50 + 20*(uint16_t)(255-SEGMENT.speed); + uint16_t count = 2 * ((SEGMENT.speed / 10) + 1); + if(SEGMENT_RUNTIME.counter_mode_step < count) { + if((SEGMENT_RUNTIME.counter_mode_step & 1) == 0) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + delay = 20; + } else { + delay = 50; + } + } + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % (count + 1); + return delay; +} + +/* + * Android loading circle + */ +uint16_t WS2812FX::mode_android(void) { + if (SEGMENT_RUNTIME.counter_mode_call == 0) { - bus->SetPixelColor(i, RgbwColor(r,g,b,w)); + SEGMENT_RUNTIME.aux_param = 0; + SEGMENT_RUNTIME.counter_mode_step = SEGMENT.start; + } + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[1]); + } + + if (SEGMENT_RUNTIME.aux_param2 > ((float)SEGMENT.intensity/255.0)*(float)SEGMENT_LENGTH) + { + SEGMENT_RUNTIME.aux_param = 1; } else { - bus->SetPixelColor(i, RgbColor(r,g,b)); + if (SEGMENT_RUNTIME.aux_param2 < 2) SEGMENT_RUNTIME.aux_param = 0; } + + uint16_t a = SEGMENT_RUNTIME.counter_mode_step; + + if (SEGMENT_RUNTIME.aux_param == 0) + { + if (SEGMENT_RUNTIME.counter_mode_call %3 == 1) {a++;} + else {SEGMENT_RUNTIME.aux_param2++;} + } else + { + a++; + if (SEGMENT_RUNTIME.counter_mode_call %3 != 1) SEGMENT_RUNTIME.aux_param2--; + } + + if (a > SEGMENT.stop) a = SEGMENT.start; + + if (a + SEGMENT_RUNTIME.aux_param2 <= SEGMENT.stop) + { + for(int i = a; i < a+SEGMENT_RUNTIME.aux_param2; i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + } else + { + for(int i = a; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + for(int i = SEGMENT.start; i < SEGMENT_RUNTIME.aux_param2 - (SEGMENT.stop +1 -a); i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + } + SEGMENT_RUNTIME.counter_mode_step = a; + + return 3 + ((8 * (uint32_t)(255 - SEGMENT.speed)) / SEGMENT_LENGTH); } -void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) -{ - if (_reverseMode) i = _led_count - 1 -i; - if (!_cronixieMode) +/* + * color chase function. + * color1 = background color + * color2 and color3 = colors of two adjacent leds + */ +uint16_t WS2812FX::chase(uint32_t color1, uint32_t color2, uint32_t color3) { + uint16_t a = SEGMENT_RUNTIME.counter_mode_step; + uint16_t b = (a + 1) % SEGMENT_LENGTH; + uint16_t c = (b + 1) % SEGMENT_LENGTH; + setPixelColor(SEGMENT.start + a, color1); + setPixelColor(SEGMENT.start + b, color2); + setPixelColor(SEGMENT.start + c, color3); + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; + return SPEED_FORMULA_L; +} + +/* + * Tricolor chase mode + */ +uint16_t WS2812FX::mode_tricolor_chase(void) { + return chase(SEGMENT.colors[0], SEGMENT.colors[1], SEGMENT.colors[2]); +} + +/* + * Bicolor chase, more primary color. + */ +uint16_t WS2812FX::mode_chase_color(void) { + return chase(SEGMENT.colors[1], SEGMENT.colors[0], SEGMENT.colors[0]); +} + +/* + * Primary running followed by random color. + */ +uint16_t WS2812FX::mode_chase_random(void) { + if(SEGMENT_RUNTIME.counter_mode_step == 0) { + SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + } + return chase(color_wheel(SEGMENT_RUNTIME.aux_param), SEGMENT.colors[0], SEGMENT.colors[0]); +} + + +/* + * Primary running on rainbow. + */ +uint16_t WS2812FX::mode_chase_rainbow_white(void) { + uint16_t n = SEGMENT_RUNTIME.counter_mode_step; + uint16_t m = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; + uint32_t color2 = color_wheel(((n * 256 / SEGMENT_LENGTH) + (SEGMENT_RUNTIME.counter_mode_call & 0xFF)) & 0xFF); + uint32_t color3 = color_wheel(((m * 256 / SEGMENT_LENGTH) + (SEGMENT_RUNTIME.counter_mode_call & 0xFF)) & 0xFF); + + return chase(SEGMENT.colors[0], color2, color3); +} + + +/* + * Red - Amber - Green - Blue lights running + */ +uint16_t WS2812FX::mode_colorful(void) { + uint32_t cols[]{0x00FF0000,0x00EEBB00,0x0000EE00,0x000077CC,0x00FF0000,0x00EEBB00,0x0000EE00}; + if (SEGMENT.intensity < 127) //pastel (easter) colors { - if (_skipFirstMode) {i++;if(i==1)setPixelColorRaw(0,0,0,0,0);} - if (_rgbwMode) + cols[0] = 0x00FF8040; + cols[1] = 0x00E5D241; + cols[2] = 0x0077FF77; + cols[3] = 0x0077F0F0; + for (uint8_t i = 4; i < 7; i++) cols[i] = cols[i-4]; + } + int i = SEGMENT.start; + for (i; i <= SEGMENT.stop ; i+=4) + { + setPixelColor(i, cols[SEGMENT_RUNTIME.counter_mode_step]); + setPixelColor(i+1, cols[SEGMENT_RUNTIME.counter_mode_step+1]); + setPixelColor(i+2, cols[SEGMENT_RUNTIME.counter_mode_step+2]); + setPixelColor(i+3, cols[SEGMENT_RUNTIME.counter_mode_step+3]); + } + i+=4; + if(i <= SEGMENT.stop) + { + setPixelColor(i, cols[SEGMENT_RUNTIME.counter_mode_step]); + + if(i+1 <= SEGMENT.stop) { - bus->SetPixelColor(i, RgbwColor(r,g,b,w)); - } else - { - bus->SetPixelColor(i, RgbColor(r,g,b)); - } - } else { - if(i>6)return; - byte o = 10*i; - if (_cronixieBacklightEnabled && _cronixieDigits[i] <11) - { - byte rCorr = (int)(((double)((_color_sec>>16) & 0xFF))*_cronixieSecMultiplier); - byte gCorr = (int)(((double)((_color_sec>>8) & 0xFF))*_cronixieSecMultiplier); - byte bCorr = (int)(((double)((_color_sec) & 0xFF))*_cronixieSecMultiplier); - byte wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier); - for (int j=o; j< o+19; j++) + setPixelColor(i+1, cols[SEGMENT_RUNTIME.counter_mode_step+1]); + + if(i+2 <= SEGMENT.stop) { - setPixelColorRaw((_skipFirstMode)?j+1:j,rCorr,gCorr,bCorr,wCorr); - } - } else - { - for (int j=o; j< o+19; j++) - { - setPixelColorRaw((_skipFirstMode)?j+1:j,0,0,0,0); + setPixelColor(i+2, cols[SEGMENT_RUNTIME.counter_mode_step+2]); } } - switch(_cronixieDigits[i]) + } + + if (SEGMENT.speed > 0) SEGMENT_RUNTIME.counter_mode_step++; //static if lowest speed + if (SEGMENT_RUNTIME.counter_mode_step >3) SEGMENT_RUNTIME.counter_mode_step = 0; + return 50 + (15 * (uint32_t)(255 - SEGMENT.speed)); +} + + +/* + * Emulates a traffic light. + */ +uint16_t WS2812FX::mode_traffic_light(void) { + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) setPixelColor(i, SEGMENT.colors[1]); + uint32_t mdelay = 500; + for (int i = SEGMENT.start; i < SEGMENT.stop-1 ; i+=3) + { + switch (SEGMENT_RUNTIME.counter_mode_step) { - case 0: setPixelColorRaw((_skipFirstMode)?o+6:o+5,r,g,b,w); break; - case 1: setPixelColorRaw((_skipFirstMode)?o+1:o+0,r,g,b,w); break; - case 2: setPixelColorRaw((_skipFirstMode)?o+7:o+6,r,g,b,w); break; - case 3: setPixelColorRaw((_skipFirstMode)?o+2:o+1,r,g,b,w); break; - case 4: setPixelColorRaw((_skipFirstMode)?o+8:o+7,r,g,b,w); break; - case 5: setPixelColorRaw((_skipFirstMode)?o+3:o+2,r,g,b,w); break; - case 6: setPixelColorRaw((_skipFirstMode)?o+9:o+8,r,g,b,w); break; - case 7: setPixelColorRaw((_skipFirstMode)?o+4:o+3,r,g,b,w); break; - case 8: setPixelColorRaw((_skipFirstMode)?o+10:o+9,r,g,b,w); break; - case 9: setPixelColorRaw((_skipFirstMode)?o+5:o+4,r,g,b,w); break; - default: break; + case 0: setPixelColor(i, 0x00FF0000); mdelay = 150 + (100 * (uint32_t)(255 - SEGMENT.speed));break; + case 1: setPixelColor(i, 0x00FF0000); mdelay = 150 + (20 * (uint32_t)(255 - SEGMENT.speed)); setPixelColor(i+1, 0x00EECC00); break; + case 2: setPixelColor(i+2, 0x0000FF00); mdelay = 150 + (100 * (uint32_t)(255 - SEGMENT.speed));break; + case 3: setPixelColor(i+1, 0x00EECC00); mdelay = 150 + (20 * (uint32_t)(255 - SEGMENT.speed));break; } } + + SEGMENT_RUNTIME.counter_mode_step++; + if (SEGMENT_RUNTIME.counter_mode_step >3) SEGMENT_RUNTIME.counter_mode_step = 0; + return mdelay; } -void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b) -{ - setPixelColor(i,r,g,b,0); + +/* + * Primary, secondary running on rainbow. + */ +uint16_t WS2812FX::mode_chase_rainbow(void) { + uint8_t color_sep = 256 / SEGMENT_LENGTH; + uint8_t color_index = SEGMENT_RUNTIME.counter_mode_call & 0xFF; + uint32_t color = color_wheel(((SEGMENT_RUNTIME.counter_mode_step * color_sep) + color_index) & 0xFF); + + return chase(color, SEGMENT.colors[0],SEGMENT.colors[1]); } -void WS2812FX::setPixelColor(uint16_t i, uint32_t c) -{ - setPixelColor(i,(c>>16) & 0xFF,(c>>8) & 0xFF,(c) & 0xFF,(c>>24) & 0xFF); -} -uint32_t WS2812FX::getPixelColor(uint16_t i) -{ - if (_cronixieMode) - { - if(i>6)return 0; - byte o = 10*i; - switch(_cronixieDigits[i]) - { - case 0: i=o+5; break; - case 1: i=o+0; break; - case 2: i=o+6; break; - case 3: i=o+1; break; - case 4: i=o+7; break; - case 5: i=o+2; break; - case 6: i=o+8; break; - case 7: i=o+3; break; - case 8: i=o+9; break; - case 9: i=o+4; break; - default: return 0; - } +/* + * Sec flashes running on prim. + */ +uint16_t WS2812FX::mode_chase_flash(void) { + const static uint8_t flash_count = 4; + uint8_t flash_step = SEGMENT_RUNTIME.counter_mode_call % ((flash_count * 2) + 1); + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, SEGMENT.colors[0]); } - if (_rgbwMode) - { - RgbwColor lColor = bus->GetPixelColorRgbw(i); - return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B; + + uint16_t delay = 10 + ((30 * (uint16_t)(255 - SEGMENT.speed)) / SEGMENT_LENGTH); + if(flash_step < (flash_count * 2)) { + if(flash_step % 2 == 0) { + uint16_t n = SEGMENT_RUNTIME.counter_mode_step; + uint16_t m = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; + setPixelColor(SEGMENT.start + n, SEGMENT.colors[1]); + setPixelColor(SEGMENT.start + m, SEGMENT.colors[1]); + delay = 20; + } else { + delay = 30; + } } else { - RgbColor lColor = bus->GetPixelColor(i); - return lColor.R*65536 + lColor.G*256 + lColor.B; + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; } + return delay; } -void WS2812FX::setBrightness(byte b) + +/* + * Prim flashes running, followed by random color. + */ +uint16_t WS2812FX::mode_chase_flash_random(void) { + const static uint8_t flash_count = 4; + uint8_t flash_step = SEGMENT_RUNTIME.counter_mode_call % ((flash_count * 2) + 1); + + for(uint16_t i=0; i < SEGMENT_RUNTIME.counter_mode_step; i++) { + setPixelColor(SEGMENT.start + i, color_wheel(SEGMENT_RUNTIME.aux_param)); + } + + uint16_t delay = 1 + ((10 * (uint16_t)(255 - SEGMENT.speed)) / SEGMENT_LENGTH); + if(flash_step < (flash_count * 2)) { + uint16_t n = SEGMENT_RUNTIME.counter_mode_step; + uint16_t m = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; + if(flash_step % 2 == 0) { + setPixelColor(SEGMENT.start + n, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + m, SEGMENT.colors[0]); + delay = 20; + } else { + setPixelColor(SEGMENT.start + n, color_wheel(SEGMENT_RUNTIME.aux_param)); + setPixelColor(SEGMENT.start + m, SEGMENT.colors[1]); + delay = 30; + } + } else { + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; + + if(SEGMENT_RUNTIME.counter_mode_step == 0) { + SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + } + } + return delay; +} + + +/* + * Alternating pixels running function. + */ +uint16_t WS2812FX::running(uint32_t color1, uint32_t color2) { + for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { + if((i + SEGMENT_RUNTIME.counter_mode_step) % 4 < 2) { + setPixelColor(SEGMENT.stop - i, color1); + } else { + setPixelColor(SEGMENT.stop - i, color2); + } + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) & 0x3; + return 35 + ((350 * (uint32_t)(255 - SEGMENT.speed)) / 255); +} + +/* + * Alternating color/white pixels running. + */ +uint16_t WS2812FX::mode_running_color(void) { + return running(SEGMENT.colors[0], WHITE); +} + + +/* + * Alternating red/blue pixels running. + */ +uint16_t WS2812FX::mode_running_red_blue(void) { + return running(RED, BLUE); +} + + +/* + * Alternating red/green pixels running. + */ +uint16_t WS2812FX::mode_merry_christmas(void) { + return running(RED, GREEN); +} + +/* + * Alternating orange/purple pixels running. + */ +uint16_t WS2812FX::mode_halloween(void) { + return running(PURPLE, ORANGE); +} + + +/* + * Random colored pixels running. + */ +uint16_t WS2812FX::mode_running_random(void) { + for(uint16_t i=SEGMENT_LENGTH-1; i > 0; i--) { + setPixelColor(SEGMENT.start + i, getPixelColor(SEGMENT.start + i - 1)); + } + + if(SEGMENT_RUNTIME.counter_mode_step == 0) { + SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + setPixelColor(SEGMENT.start, color_wheel(SEGMENT_RUNTIME.aux_param)); + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step == 0) ? 1 : 0; + return SPEED_FORMULA_L; +} + + +/* + * K.I.T.T. + */ +uint16_t WS2812FX::mode_larson_scanner(void) { + fade_out((255-SEGMENT.intensity) / 32); + + if(SEGMENT_RUNTIME.counter_mode_step < SEGMENT_LENGTH) { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } else { + setPixelColor(SEGMENT.start + ((SEGMENT_LENGTH * 2) - SEGMENT_RUNTIME.counter_mode_step) - 2, SEGMENT.colors[0]); + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % ((SEGMENT_LENGTH * 2) - 2); + return SPEED_FORMULA_L; +} + + +/* + * Firing comets from one end. + */ +uint16_t WS2812FX::mode_comet(void) { + fade_out((255-SEGMENT.intensity) / 32); + + if(IS_REVERSE) { + setPixelColor(SEGMENT.stop - SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } else { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; + return SPEED_FORMULA_L; +} + + +/* + * Fireworks function. + */ +uint16_t WS2812FX::fireworks(uint32_t color) { + uint32_t prevLed, thisLed, nextLed; + + fade_out((255-SEGMENT.intensity) / 32); + + // set brightness(i) = ((brightness(i-1)/4 + brightness(i+1))/4) + brightness(i) + for(uint16_t i=SEGMENT.start + 1; i > 2) & 0x3F3F3F3F; + thisLed = getPixelColor(i); + nextLed = (getPixelColor(i+1) >> 2) & 0x3F3F3F3F; + setPixelColor(i, prevLed + thisLed + nextLed); + } + + if(!_triggered) { + for(uint16_t i=0; i> 24) & 0xFF; + byte r = (SEGMENT.colors[0] >> 16) & 0xFF; + byte g = (SEGMENT.colors[0] >> 8) & 0xFF; + byte b = (SEGMENT.colors[0] & 0xFF); + byte lum = max(w, max(r, max(g, b)))/(((256-SEGMENT.intensity)/16)+1); + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + int flicker = random8(lum); + setPixelColor(i, max(r - flicker, 0), max(g - flicker, 0), max(b - flicker, 0), max(w - flicker, 0)); + } + return 10 + (2 * (uint16_t)(255 - SEGMENT.speed)); +} + + +/* + * Gradient run + */ +uint16_t WS2812FX::mode_gradient(void) { + if (SEGMENT_RUNTIME.counter_mode_call == 0) SEGMENT_RUNTIME.counter_mode_step = 0; + byte p_w = (SEGMENT.colors[0] & 0xFF000000) >> 24; + byte p_r = (SEGMENT.colors[0] & 0x00FF0000) >> 16; + byte p_g = (SEGMENT.colors[0] & 0x0000FF00) >> 8; + byte p_b = (SEGMENT.colors[0] & 0x000000FF) >> 0; + byte p_w2 = (SEGMENT.colors[1] & 0xFF000000) >> 24; + byte p_r2 = (SEGMENT.colors[1] & 0x00FF0000) >> 16; + byte p_g2 = (SEGMENT.colors[1] & 0x0000FF00) >> 8; + byte p_b2 = (SEGMENT.colors[1] & 0x000000FF) >> 0; + byte nw,nr,ng,nb; + float per,val; //0.0 = sec 1.0 = pri + float brd = SEGMENT.intensity/2; if (brd <1.0) brd = 1.0; + int pp = SEGMENT_RUNTIME.counter_mode_step; + int p1 = pp-SEGMENT_LENGTH; + int p2 = pp+SEGMENT_LENGTH; + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) + { + val = min(abs(pp-i),min(abs(p1-i),abs(p2-i))); + per = val/brd; + if (per >1.0) per = 1.0; + nw = p_w+((p_w2 - p_w)*per); + nr = p_r+((p_r2 - p_r)*per); + ng = p_g+((p_g2 - p_g)*per); + nb = p_b+((p_b2 - p_b)*per); + setPixelColor(i,nr,ng,nb,nw); + } + + SEGMENT_RUNTIME.counter_mode_step++; + if (SEGMENT_RUNTIME.counter_mode_step > SEGMENT.stop) SEGMENT_RUNTIME.counter_mode_step = SEGMENT.start; + if (SEGMENT.speed == 0) SEGMENT_RUNTIME.counter_mode_step = SEGMENT.start + (SEGMENT_LENGTH >> 1); + return SPEED_FORMULA_L; +} + + +/* + * Gradient run with hard transition + */ +uint16_t WS2812FX::mode_loading(void) { + if (SEGMENT_RUNTIME.counter_mode_call == 0) SEGMENT_RUNTIME.counter_mode_step = 0; + byte p_w = (SEGMENT.colors[0] & 0xFF000000) >> 24; + byte p_r = (SEGMENT.colors[0] & 0x00FF0000) >> 16; + byte p_g = (SEGMENT.colors[0] & 0x0000FF00) >> 8; + byte p_b = (SEGMENT.colors[0] & 0x000000FF) >> 0; + byte p_w2 = (SEGMENT.colors[1] & 0xFF000000) >> 24; + byte p_r2 = (SEGMENT.colors[1] & 0x00FF0000) >> 16; + byte p_g2 = (SEGMENT.colors[1] & 0x0000FF00) >> 8; + byte p_b2 = (SEGMENT.colors[1] & 0x000000FF) >> 0; + byte nw,nr,ng,nb; + float per,val; //0.0 = sec 1.0 = pri + float brd = SEGMENT.intensity; if (brd <1.0) brd = 1.0; + int pp = SEGMENT_RUNTIME.counter_mode_step; + int p1 = pp+SEGMENT_LENGTH; + + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) + { + pp = SEGMENT_RUNTIME.counter_mode_step; + if (i > pp) pp+=SEGMENT_LENGTH; + val = abs(pp-i); + per = val/brd; + if (per >1.0) per = 1.0; + nw = p_w+((p_w2 - p_w)*per); + nr = p_r+((p_r2 - p_r)*per); + ng = p_g+((p_g2 - p_g)*per); + nb = p_b+((p_b2 - p_b)*per); + setPixelColor(i,nr,ng,nb,nw); + } + + SEGMENT_RUNTIME.counter_mode_step++; + if (SEGMENT_RUNTIME.counter_mode_step > SEGMENT.stop) SEGMENT_RUNTIME.counter_mode_step = SEGMENT.start; + if (SEGMENT.speed == 0) SEGMENT_RUNTIME.counter_mode_step = SEGMENT.stop; + return SPEED_FORMULA_L; +} + + +/* + * Lights all LEDs after each other up starting from the outer edges and + * finishing in the middle. Then turns them in reverse order off. Repeat. + */ +uint16_t WS2812FX::mode_dual_color_wipe_in_out(void) { + int end = SEGMENT_LENGTH - SEGMENT_RUNTIME.counter_mode_step - 1; + bool odd = (SEGMENT_LENGTH % 2) == 1; + int mid = odd ? ((SEGMENT_LENGTH / 2) + 1) : (SEGMENT_LENGTH / 2); + if (SEGMENT_RUNTIME.counter_mode_step < mid) { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + end, SEGMENT.colors[0]); + } else { + if (odd) { + // If odd, we need to 'double count' the center LED (once to turn it on, + // once to turn it off). So trail one behind after the middle LED. + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step - 1, 0); + setPixelColor(SEGMENT.start + end + 1, 0); + } else { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, 0); + setPixelColor(SEGMENT.start + end, 0); + } + } + SEGMENT_RUNTIME.counter_mode_step++; + if (odd) { + if (SEGMENT_RUNTIME.counter_mode_step > SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } else { + if (SEGMENT_RUNTIME.counter_mode_step >= SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } + return SPEED_FORMULA_L; +} + + + /* + * Lights all LEDs after each other up starting from the outer edges and + * finishing in the middle. Then turns them in that order off. Repeat. + */ +uint16_t WS2812FX::mode_dual_color_wipe_in_in(void) { + bool odd = (SEGMENT_LENGTH % 2) == 1; + int mid = SEGMENT_LENGTH / 2; + if (odd) { + if (SEGMENT_RUNTIME.counter_mode_step <= mid) { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + SEGMENT_LENGTH - SEGMENT_RUNTIME.counter_mode_step - 1, SEGMENT.colors[0]); + } else { + int i = SEGMENT_RUNTIME.counter_mode_step - mid; + setPixelColor(SEGMENT.start + i - 1, 0); + setPixelColor(SEGMENT.start + SEGMENT_LENGTH - i, 0); + } + } else { + if (SEGMENT_RUNTIME.counter_mode_step < mid) { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + SEGMENT_LENGTH - SEGMENT_RUNTIME.counter_mode_step - 1, SEGMENT.colors[0]); + } else { + int i = SEGMENT_RUNTIME.counter_mode_step - mid; + setPixelColor(SEGMENT.start + i, 0); + setPixelColor(SEGMENT.start + SEGMENT_LENGTH - i - 1, 0); + } + } + SEGMENT_RUNTIME.counter_mode_step++; + if (odd) { + if (SEGMENT_RUNTIME.counter_mode_step > SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } else { + if (SEGMENT_RUNTIME.counter_mode_step >= SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } + return SPEED_FORMULA_L; +} + + + /* + * Lights all LEDs after each other up starting from the middle and + * finishing at the edges. Then turns them off in that order. Repeat. + */ +uint16_t WS2812FX::mode_dual_color_wipe_out_out(void) { + int end = SEGMENT_LENGTH - SEGMENT_RUNTIME.counter_mode_step - 1; + bool odd = (SEGMENT_LENGTH % 2) == 1; + int mid = SEGMENT_LENGTH / 2; + if (odd) { + if (SEGMENT_RUNTIME.counter_mode_step <= mid) { + setPixelColor(SEGMENT.start + mid + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + mid - SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } else { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step - 1, 0); + setPixelColor(SEGMENT.start + end + 1, 0); + } + } else { + if (SEGMENT_RUNTIME.counter_mode_step < mid) { + setPixelColor(SEGMENT.start + mid - SEGMENT_RUNTIME.counter_mode_step - 1, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + mid + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } else { + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, 0); + setPixelColor(SEGMENT.start + end, 0); + } + } + SEGMENT_RUNTIME.counter_mode_step++; + if (odd) { + if (SEGMENT_RUNTIME.counter_mode_step > SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } else { + if (SEGMENT_RUNTIME.counter_mode_step >= SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } + return SPEED_FORMULA_L; +} + + + /* + * Lights all LEDs after each other up starting from the middle and + * finishing at the edges. Then turns them off in reverse order. Repeat. + */ +uint16_t WS2812FX::mode_dual_color_wipe_out_in(void) { + bool odd = (SEGMENT_LENGTH % 2) == 1; + int mid = SEGMENT_LENGTH / 2; + if (odd) { + if (SEGMENT_RUNTIME.counter_mode_step <= mid) { + setPixelColor(SEGMENT.start + mid + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + mid - SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } else { + int i = SEGMENT_RUNTIME.counter_mode_step - mid; + setPixelColor(SEGMENT.start + i - 1, 0); + setPixelColor(SEGMENT.start + SEGMENT_LENGTH - i, 0); + } + } else { + if (SEGMENT_RUNTIME.counter_mode_step < mid) { + setPixelColor(SEGMENT.start + mid - SEGMENT_RUNTIME.counter_mode_step - 1, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + mid + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } else { + int i = SEGMENT_RUNTIME.counter_mode_step - mid; + setPixelColor(SEGMENT.start + i, 0); + setPixelColor(SEGMENT.start + SEGMENT_LENGTH - i - 1, 0); + } + } + SEGMENT_RUNTIME.counter_mode_step++; + if (odd) { + if (SEGMENT_RUNTIME.counter_mode_step > SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } else { + if (SEGMENT_RUNTIME.counter_mode_step >= SEGMENT_LENGTH) { + SEGMENT_RUNTIME.counter_mode_step = 0; + } + } + return SPEED_FORMULA_L; +} + + +/* + * Alternating white/red/black pixels running. + */ +uint16_t WS2812FX::mode_circus_combustus(void) { + return chase(RED, WHITE, BLACK); +} + + +/* + * ICU mode + */ +uint16_t WS2812FX::mode_icu(void) { + uint16_t dest = SEGMENT_RUNTIME.counter_mode_step & 0xFFFF; + + setPixelColor(SEGMENT.start + dest, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, SEGMENT.colors[0]); + + if(SEGMENT_RUNTIME.aux_param == dest) { // pause between eye movements + if(random8(6) == 0) { // blink once in a while + setPixelColor(SEGMENT.start + dest, BLACK); + setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, BLACK); + return 200; + } + SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH/2); + return 1000 + random(2000); + } + + setPixelColor(SEGMENT.start + dest, BLACK); + setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, BLACK); + + if(SEGMENT_RUNTIME.aux_param > SEGMENT_RUNTIME.counter_mode_step) { + SEGMENT_RUNTIME.counter_mode_step++; + dest++; + } else if (SEGMENT_RUNTIME.aux_param < SEGMENT_RUNTIME.counter_mode_step) { + SEGMENT_RUNTIME.counter_mode_step--; + dest--; + } + + setPixelColor(SEGMENT.start + dest, SEGMENT.colors[0]); + setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, SEGMENT.colors[0]); + + return SPEED_FORMULA_L; +} + + +/* + * Custom mode by Aircoookie. Color Wipe, but with 3 colors + */ +uint16_t WS2812FX::mode_tricolor_wipe(void) { - _brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - bus->SetBrightness(_brightness); - if (_mode_last_call_time + _mode_delay > millis()+50 || b == 0) show(); //only update right away if long time until next refresh + if(SEGMENT_RUNTIME.counter_mode_step < SEGMENT_LENGTH) { + uint32_t led_offset = SEGMENT_RUNTIME.counter_mode_step; + setPixelColor(SEGMENT.start + led_offset, SEGMENT.colors[0]); + } else if (SEGMENT_RUNTIME.counter_mode_step < SEGMENT_LENGTH*2) { + uint32_t led_offset = SEGMENT_RUNTIME.counter_mode_step - SEGMENT_LENGTH; + setPixelColor(SEGMENT.start + led_offset, SEGMENT.colors[1]); + } else + { + uint32_t led_offset = SEGMENT_RUNTIME.counter_mode_step - SEGMENT_LENGTH*2; + setPixelColor(SEGMENT.start + led_offset, SEGMENT.colors[2]); + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % (SEGMENT_LENGTH * 3); + return SPEED_FORMULA_L; } -void WS2812FX::show() + +/* + * Fades between 3 colors + * Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/TriFade.h + * Modified by Aircoookie + */ +uint16_t WS2812FX::mode_tricolor_fade(void) { - bus->Show(); + static uint32_t color1 = 0, color2 = 0; + + if(SEGMENT_RUNTIME.counter_mode_step == 0) { + color1 = SEGMENT.colors[0]; + color2 = SEGMENT.colors[1]; + } else if(SEGMENT_RUNTIME.counter_mode_step == 256) { + color1 = SEGMENT.colors[1]; + color2 = SEGMENT.colors[2]; + } else if(SEGMENT_RUNTIME.counter_mode_step == 512) { + color1 = SEGMENT.colors[2]; + color2 = SEGMENT.colors[0]; + } + + uint32_t color = color_blend(color1, color2, SEGMENT_RUNTIME.counter_mode_step % 256); + for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + setPixelColor(i, color); + } + + SEGMENT_RUNTIME.counter_mode_step += 4; + if(SEGMENT_RUNTIME.counter_mode_step >= 768) SEGMENT_RUNTIME.counter_mode_step = 0; + + return 5 + ((uint32_t)(255 - SEGMENT.speed) / 10); } -void WS2812FX::clear() + +/* + * Creates random comets + * Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/MultiComet.h + */ +uint16_t WS2812FX::mode_multi_comet(void) { - bus->ClearTo(RgbColor(0)); + fade_out((255-SEGMENT.intensity) / 32); + + static uint16_t comets[] = {UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX}; + + for(uint8_t i=0; i < 6; i++) { + if(comets[i] < SEGMENT_LENGTH) { + if (SEGMENT.colors[2] != SEGMENT.colors[1]) + { + setPixelColor(SEGMENT.start + comets[i], i % 2 ? SEGMENT.colors[0] : SEGMENT.colors[2]); + } else + { + setPixelColor(SEGMENT.start + comets[i], SEGMENT.colors[0]); + } + comets[i]++; + } else { + if(!random(SEGMENT_LENGTH)) { + comets[i] = 0; + } + } + } + return SPEED_FORMULA_L; } -void WS2812FX::begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst) + +/* + * Creates two Larson scanners moving in opposite directions + * Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/DualLarson.h + */ +uint16_t WS2812FX::mode_dual_larson_scanner(void){ + if (SEGMENT_RUNTIME.aux_param) + { + SEGMENT_RUNTIME.counter_mode_step--; + } else + { + SEGMENT_RUNTIME.counter_mode_step++; + } + + fade_out((255-SEGMENT.intensity) / 32); + + setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + if (SEGMENT.colors[2] != SEGMENT.colors[1]) + { + setPixelColor(SEGMENT.stop - SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[2]); + } else + { + setPixelColor(SEGMENT.stop - SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + } + + if(SEGMENT_RUNTIME.counter_mode_step >= (SEGMENT.stop - SEGMENT.start) || SEGMENT_RUNTIME.counter_mode_step <= 0) + SEGMENT_RUNTIME.aux_param = !SEGMENT_RUNTIME.aux_param; + + return SPEED_FORMULA_L; +} + + +/* + * Running random pixels + * Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/RandomChase.h + */ +uint16_t WS2812FX::mode_random_chase(void) { - if (supportWhite == _rgbwMode && countPixels == _led_count && _locked != NULL) return; - _rgbwMode = supportWhite; - _skipFirstMode = skipFirst; - _led_count = countPixels; - _cc_i2 = _led_count -1; - if (_skipFirstMode) _led_count++; - uint8_t ty = 1; - if (supportWhite) ty =2; - bus->Begin((NeoPixelType)ty, _led_count, pin); - if (_locked != NULL) delete _locked; - _locked = new bool[_led_count]; + for(uint16_t i=SEGMENT.stop; i>SEGMENT.start; i--) { + setPixelColor(i, getPixelColor(i-1)); + } + uint32_t color = getPixelColor(SEGMENT.start + 1); + int r = random(6) != 0 ? (color >> 16 & 0xFF) : random(256); + int g = random(6) != 0 ? (color >> 8 & 0xFF) : random(256); + int b = random(6) != 0 ? (color & 0xFF) : random(256); + setPixelColor(SEGMENT.start, r, g, b); + + return 15 + (15 * (uint32_t)(255 - SEGMENT.speed)); } -//For some reason min and max are not declared here +typedef struct Oscillator { + int16_t pos; + int8_t size; + int8_t dir; + int8_t speed; +} oscillator; -uint16_t WS2812FX::minval (uint16_t v, uint16_t w) +uint16_t WS2812FX::mode_oscillate(void) { - if (w > v) return v; - return w; + static oscillator oscillators[NUM_COLORS] = { + {SEGMENT_LENGTH/4, SEGMENT_LENGTH/8, 1, 1}, + {SEGMENT_LENGTH/4*2, SEGMENT_LENGTH/8, -1, 1}, + {SEGMENT_LENGTH/4*3, SEGMENT_LENGTH/8, 1, 2} + }; + + for(int8_t i=0; i < sizeof(oscillators)/sizeof(oscillators[0]); i++) { + oscillators[i].pos += oscillators[i].dir * oscillators[i].speed; + if((oscillators[i].dir == -1) && (oscillators[i].pos <= 0)) { + oscillators[i].pos = 0; + oscillators[i].dir = 1; + oscillators[i].speed = random(1, 3); + } + if((oscillators[i].dir == 1) && (oscillators[i].pos >= (SEGMENT_LENGTH - 1))) { + oscillators[i].pos = SEGMENT_LENGTH - 1; + oscillators[i].dir = -1; + oscillators[i].speed = random(1, 3); + } + } + + for(int16_t i=0; i < SEGMENT_LENGTH; i++) { + uint32_t color = BLACK; + for(int8_t j=0; j < sizeof(oscillators)/sizeof(oscillators[0]); j++) { + if(i >= oscillators[j].pos - oscillators[j].size && i <= oscillators[j].pos + oscillators[j].size) { + color = (color == BLACK) ? SEGMENT.colors[j] : color_blend(color, SEGMENT.colors[j], 128); + } + } + setPixelColor(SEGMENT.start + i, color); + } + return 15 + (uint32_t)(255 - SEGMENT.speed); } -uint16_t WS2812FX::maxval (uint16_t v, uint16_t w) + +// WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active +// Fire2012 by Mark Kriegsman, July 2012 +// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY +//// +// This basic one-dimensional 'fire' simulation works roughly as follows: +// There's a underlying array of 'heat' cells, that model the temperature +// at each point along the line. Every cycle through the simulation, +// four steps are performed: +// 1) All cells cool down a little bit, losing heat to the air +// 2) The heat from each cell drifts 'up' and diffuses a little +// 3) Sometimes randomly new 'sparks' of heat are added at the bottom +// 4) The heat from each cell is rendered as a color into the leds array +// The heat-to-color mapping uses a black-body radiation approximation. +// +// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). +// +// This simulation scales it self a bit depending on NUM_LEDS; it should look +// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. +// +// I recommend running this simulation at anywhere from 30-100 frames per second, +// meaning an interframe delay of about 10-35 milliseconds. +// +// Looks best on a high-density LED setup (60+ pixels/meter). +// +// +// There are two main parameters you can play with to control the look and +// feel of your fire: COOLING (used in step 1 above), and SPARKING (used +// in step 3 above) (Effect Intensity = Sparking). +// +// COOLING: How much does the air cool as it rises? +// Less cooling = taller flames. More cooling = shorter flames. +// Default 50, suggested range 20-100 +#define COOLING 75 + +uint16_t WS2812FX::mode_fire_2012(void) { - if (w > v) return w; - return v; + // Step 1. Cool down every cell a little + for( int i = SEGMENT.start; i <= SEGMENT.stop; i++) { + _locked[i] = qsub8(_locked[i], random8(0, ((COOLING * 10) / SEGMENT_LENGTH) + 2)); + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for( int k= SEGMENT.stop; k >= SEGMENT.start + 2; k--) { + _locked[k] = (_locked[k - 1] + _locked[k - 2] + _locked[k - 2] ) / 3; + } + + // Step 3. Randomly ignite new 'sparks' of heat near the bottom + if( random8() <= SEGMENT.intensity ) { + int y = SEGMENT.start + random8(7); + if (y <= SEGMENT.stop) _locked[y] = qadd8(_locked[y], random8(160,255) ); + } + + // Step 4. Map from heat cells to LED colors + for( int j = SEGMENT.start; j <= SEGMENT.stop; j++) { + CRGB color = HeatColor(_locked[j]); + setPixelColor(j, color.red, color.green, color.blue); + } + return 10 + (uint16_t)(255 - SEGMENT.speed)/6; } + + +uint16_t WS2812FX::mode_bpm(void) +{ + CRGB fastled_col; + CRGBPalette16 palette = PartyColors_p; + uint8_t beat = beatsin8(SEGMENT.speed, 64, 255); + for ( int i = SEGMENT.start; i <= SEGMENT.stop; i++) { + fastled_col = ColorFromPalette(palette, SEGMENT_RUNTIME.counter_mode_step + (i * 2), beat - SEGMENT_RUNTIME.counter_mode_step + (i * 10)); + setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); + } + SEGMENT_RUNTIME.counter_mode_step++; + if (SEGMENT_RUNTIME.counter_mode_step >= 255) SEGMENT_RUNTIME.counter_mode_step = 0; + return 20; +} + + +uint16_t WS2812FX::mode_juggle(void){ + fade_out((255-SEGMENT.intensity) / 32); + CRGB fastled_col; + byte dothue = 0; + for ( byte i = 0; i < 8; i++) { + uint16_t index = SEGMENT.start + beatsin16(i + 7, 0, SEGMENT_LENGTH); + uint32_t color = getPixelColor(index); + fastled_col.red = (color >> 16 & 0xFF); + fastled_col.green = (color >> 8 & 0xFF); + fastled_col.blue = (color & 0xFF); + fastled_col |= CHSV(dothue, 220, 255); + setPixelColor(index, fastled_col.red, fastled_col.green, fastled_col.blue); + dothue += 32; + } + return 10 + (uint16_t)(255 - SEGMENT.speed)/4; +} + + +CRGBPalette16 currentPalette(CRGB::Black); +CRGBPalette16 targetPalette(CloudColors_p); + + +uint16_t WS2812FX::mode_palette(void) +{ + CRGB fastled_col; + + for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++) + { + uint8_t colorIndex = map(i,SEGMENT.start,SEGMENT.stop,0,255) + (SEGMENT_RUNTIME.counter_mode_step >> 8 & 0xFF); + fastled_col = ColorFromPalette( PartyColors_p, colorIndex, 255, LINEARBLEND); + setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); + } + SEGMENT_RUNTIME.counter_mode_step += SEGMENT.speed; + return 20; +} + + +uint16_t WS2812FX::mode_fillnoise8(void) +{ + if (SEGMENT_RUNTIME.counter_mode_call == 0) SEGMENT_RUNTIME.counter_mode_step = random(12345); + CRGB fastled_col; + nblendPaletteTowardPalette(currentPalette, targetPalette, 42); + for (int i = SEGMENT.start; i <= SEGMENT.stop; i++) { + uint8_t index = inoise8(i * SEGMENT_LENGTH, SEGMENT_RUNTIME.counter_mode_step + i * SEGMENT_LENGTH) % 255; + fastled_col = ColorFromPalette(currentPalette, index, 255, LINEARBLEND); + setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); + } + SEGMENT_RUNTIME.counter_mode_step += beatsin8(10, 1, 4); + + if (SEGMENT_RUNTIME.counter_mode_call >= 20 + (255 - SEGMENT.intensity) *4) //swap to new random palette + { + targetPalette = CRGBPalette16( + CHSV(random8(), 255, random8(128, 255)), + CHSV(random8(), 255, random8(128, 255)), + CHSV(random8(), 192, random8(128, 255)), + CHSV(random8(), 255, random8(128, 255))); + SEGMENT_RUNTIME.counter_mode_call = 1; + } + + return 15 + (uint16_t)(255 - SEGMENT.speed); +} + + +uint16_t WS2812FX::mode_noise16_1(void) +{ + uint16_t scale = 100 + SEGMENT.intensity*7; // the "zoom factor" for the noise + CRGBPalette16 palette = OceanColors_p; + CRGB fastled_col; + SEGMENT_RUNTIME.counter_mode_step += (1 + SEGMENT.speed/16); + + for (int i = SEGMENT.start; i <= SEGMENT.stop; i++) { + + uint16_t shift_x = beatsin8(5); // the x position of the noise field swings @ 17 bpm + uint16_t shift_y = SEGMENT_RUNTIME.counter_mode_step/50; // the y position becomes slowly incremented + + + uint16_t real_x = (i + shift_x) * scale; // the x position of the noise field swings @ 17 bpm + uint16_t real_y = (i + shift_y) * scale; // the y position becomes slowly incremented + uint32_t real_z = SEGMENT_RUNTIME.counter_mode_step*2; // the z position becomes quickly incremented + + uint8_t noise = inoise16(real_x, real_y, real_z) >> 8; // get the noise data and scale it down + + uint8_t index = sin8(noise * 3); // map LED color based on noise data + + fastled_col = ColorFromPalette(palette, index, noise, LINEARBLEND); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); + } + + return 20; +} + + +uint16_t WS2812FX::mode_noise16_2(void) +{ + uint8_t scale = 100 + SEGMENT.intensity*7; // the "zoom factor" for the noise + CRGBPalette16 palette = LavaColors_p; + CRGB fastled_col; + SEGMENT_RUNTIME.counter_mode_step += (1 + SEGMENT.speed); + + for (int i = SEGMENT.start; i <= SEGMENT.stop; i++) { + + uint16_t shift_x = SEGMENT_RUNTIME.counter_mode_step/64; // x as a function of time + uint16_t shift_y = 0; + + uint32_t real_x = (i + shift_x) * scale; // calculate the coordinates within the noise field + uint32_t real_y = (i + shift_y) * scale; // based on the precalculated positions + uint32_t real_z = 4223; + + uint8_t noise = inoise16(real_x, real_y, real_z) >> 8; // get the noise data and scale it down + + uint8_t index = sin8(noise * 3); // map led color based on noise data + + fastled_col = ColorFromPalette(palette, index, noise, LINEARBLEND); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); + } + + return 20; +} + + +uint16_t WS2812FX::mode_noise16_3(void) +{ + uint8_t scale = 100 + SEGMENT.intensity*7; // the "zoom factor" for the noise + CRGBPalette16 palette = CloudColors_p; + CRGB fastled_col; + SEGMENT_RUNTIME.counter_mode_step += (1 + SEGMENT.speed); + + for (int i = SEGMENT.start; i <= SEGMENT.stop; i++) { + + uint16_t shift_x = 4223; // no movement along x and y + uint16_t shift_y = 1234; + + uint32_t real_x = (i + shift_x) * scale; // calculate the coordinates within the noise field + uint32_t real_y = (i + shift_y) * scale; // based on the precalculated positions + uint32_t real_z = SEGMENT_RUNTIME.counter_mode_step/16; + + uint8_t noise = inoise16(real_x, real_y, real_z) >> 7; // get the noise data and scale it down + + uint8_t index = sin8(noise * 3); // map led color based on noise data + + fastled_col = ColorFromPalette(palette, index, noise, LINEARBLEND); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); + } + + return 20; +} + + +//https://github.com/aykevl/ledstrip-spark/blob/master/ledstrip.ino +uint16_t WS2812FX::mode_noise16_4(void) +{ + CRGBPalette16 palette = OceanColors_p; + CRGB fastled_col; + SEGMENT_RUNTIME.counter_mode_step += SEGMENT.speed; + for (int i = SEGMENT.start; i <= SEGMENT.stop; i++) { + int16_t index = inoise16(uint32_t(i - SEGMENT.start) << 12, SEGMENT_RUNTIME.counter_mode_step/8); + fastled_col = ColorFromPalette(palette, index); + setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); + } + return 20; +} + + +uint16_t WS2812FX::mode_lightning(void) +{ + uint16_t ledstart = SEGMENT.start + random8(SEGMENT_LENGTH); // Determine starting location of flash + uint16_t ledlen = random8(SEGMENT.stop - ledstart); // Determine length of flash (not to go beyond NUM_LEDS-1) + uint8_t bri = 255/random8(1, 3); + + if (SEGMENT_RUNTIME.counter_mode_step == 0) + { + SEGMENT_RUNTIME.aux_param = random8(3, 3 + SEGMENT.intensity/20); //number of flashes + bri = 52; + SEGMENT_RUNTIME.aux_param2 = 1; + } + + for (int i = SEGMENT.start; i <= SEGMENT.stop; i++) + { + setPixelColor(i,SEGMENT.colors[1]); + } + + if (SEGMENT_RUNTIME.aux_param2) { + for (int i = ledstart; i < ledstart + ledlen; i++) + { + setPixelColor(i,bri,bri,bri,bri); + } + SEGMENT_RUNTIME.aux_param2 = 0; + SEGMENT_RUNTIME.counter_mode_step++; + return random8(4, 10); // each flash only lasts 4-10 milliseconds + } + + SEGMENT_RUNTIME.aux_param2 = 1; + if (SEGMENT_RUNTIME.counter_mode_step == 1) return (200); // longer delay until next flash after the leader + + if (SEGMENT_RUNTIME.counter_mode_step <= SEGMENT_RUNTIME.aux_param) return (50 + random8(100)); // shorter delay between strokes + + SEGMENT_RUNTIME.counter_mode_step = 0; + return (random8(255 - SEGMENT.speed) * 100); // delay between strikes +} + + diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index 2ea09e4f..f1537938 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -2,18 +2,17 @@ /* WS2812FX.h - Library for WS2812 LED effects. - Harm Aldick - 2016 www.aldick.org FEATURES * A lot of blinken modes and counting - * WS2812FX can be used as drop-in replacement for Adafruit Neopixel Library + * WS2812FX can be used as drop-in replacement for Adafruit NeoPixel Library NOTES - * Uses the Adafruit Neopixel library. Get it here: + * Uses the Adafruit NeoPixel library. Get it here: https://github.com/adafruit/Adafruit_NeoPixel LICENSE The MIT License (MIT) - Copyright (c) 2016 Harm Aldick + Copyright (c) 2016 Harm Aldick Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights @@ -29,27 +28,61 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - Heavily modified to work with WLED - differs from Github WS2812FX + CHANGELOG + 2016-05-28 Initial beta release + 2016-06-03 Code cleanup, minor improvements, new modes + 2016-06-04 2 new fx, fixed setColor (now also resets _mode_color) + 2017-02-02 added external trigger functionality (e.g. for sound-to-light) + Modified for WLED */ #ifndef WS2812FX_h #define WS2812FX_h -#include "Arduino.h" #include "NpbWrapper.h" -#define DEFAULT_BRIGHTNESS 50 -#define DEFAULT_MODE 0 -#define DEFAULT_SPEED 150 -#define DEFAULT_COLOR 0xFFAA00 +#define DEFAULT_BRIGHTNESS (uint8_t)50 +#define DEFAULT_MODE (uint8_t)0 +#define DEFAULT_SPEED (uint16_t)1000 +#define DEFAULT_COLOR (uint32_t)0xFF0000 -#define SPEED_MIN 0 -#define SPEED_MAX 255 +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) -#define BRIGHTNESS_MIN 0 -#define BRIGHTNESS_MAX 255 +/* each segment uses 38 bytes of SRAM memory, so if you're application fails because of + insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ +#define MAX_NUM_SEGMENTS 12 +#define NUM_COLORS 3 /* number of colors per segment */ +#define SEGMENT _segments[_segment_index] +#define SEGMENT_RUNTIME _segment_runtimes[_segment_index] +#define SEGMENT_LENGTH (SEGMENT.stop - SEGMENT.start + 1) +#define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGMENT_LENGTH +#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes)) -#define MODE_COUNT 58 +// some common colors +#define RED (uint32_t)0xFF0000 +#define GREEN (uint32_t)0x00FF00 +#define BLUE (uint32_t)0x0000FF +#define WHITE (uint32_t)0xFFFFFF +#define BLACK (uint32_t)0x000000 +#define YELLOW (uint32_t)0xFFFF00 +#define CYAN (uint32_t)0x00FFFF +#define MAGENTA (uint32_t)0xFF00FF +#define PURPLE (uint32_t)0x400080 +#define ORANGE (uint32_t)0xFF3000 +#define PINK (uint32_t)0xFF1493 +#define ULTRAWHITE (uint32_t)0xFFFFFFFF + +// options +// bit 8: reverse animation +// bits 5-7: fade rate (0-7) +// bit 4: gamma correction +// bits 1-3: TBD +#define NO_OPTIONS (uint8_t)0x00 +#define REVERSE (uint8_t)0x80 +#define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE) + +#define MODE_COUNT 72 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -57,7 +90,7 @@ #define FX_MODE_COLOR_WIPE 3 #define FX_MODE_COLOR_WIPE_RANDOM 4 #define FX_MODE_RANDOM_COLOR 5 -#define FX_MODE_EASTER 6 +#define FX_MODE_COLOR_SWEEP 6 #define FX_MODE_DYNAMIC 7 #define FX_MODE_RAINBOW 8 #define FX_MODE_RAINBOW_CYCLE 9 @@ -104,193 +137,225 @@ #define FX_MODE_DUAL_COLOR_WIPE_OUT_OUT 50 #define FX_MODE_DUAL_COLOR_WIPE_OUT_IN 51 #define FX_MODE_CIRCUS_COMBUSTUS 52 -#define FX_MODE_CUSTOM_CHASE 53 -#define FX_MODE_CC_ON_RAINBOW 54 -#define FX_MODE_CC_ON_RAINBOW_CYCLE 55 -#define FX_MODE_CC_BLINK 56 -#define FX_MODE_CC_RANDOM 57 - +#define FX_MODE_HALLOWEEN 53 +#define FX_MODE_TRICOLOR_CHASE 54 +#define FX_MODE_TRICOLOR_WIPE 55 +#define FX_MODE_TRICOLOR_FADE 56 +#define FX_MODE_LIGHTNING 57 +#define FX_MODE_ICU 58 +#define FX_MODE_MULTI_COMET 59 +#define FX_MODE_DUAL_LARSON_SCANNER 60 +#define FX_MODE_RANDOM_CHASE 61 +#define FX_MODE_OSCILLATE 62 +#define FX_MODE_FIRE_2012 63 +#define FX_MODE_JUGGLE 64 +#define FX_MODE_PALETTE 65 +#define FX_MODE_BPM 66 +#define FX_MODE_FILLNOISE8 67 +#define FX_MODE_NOISE16_1 68 +#define FX_MODE_NOISE16_2 69 +#define FX_MODE_NOISE16_3 70 +#define FX_MODE_NOISE16_4 71 class WS2812FX { - typedef void (WS2812FX::*mode_ptr)(void); + typedef uint16_t (WS2812FX::*mode_ptr)(void); + + // segment parameters public: - WS2812FX(){ + typedef struct Segment { // 20 bytes + uint16_t start; + uint16_t stop; + uint8_t speed; + uint8_t intensity; + uint8_t mode; + uint8_t options; + uint32_t colors[NUM_COLORS]; + } segment; - _mode[FX_MODE_STATIC] = &WS2812FX::mode_static; - _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; - _mode[FX_MODE_BREATH] = &WS2812FX::mode_breath; - _mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe; - _mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random; - _mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color; - _mode[FX_MODE_EASTER] = &WS2812FX::mode_easter; - _mode[FX_MODE_DYNAMIC] = &WS2812FX::mode_dynamic; - _mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow; - _mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle; - _mode[FX_MODE_SCAN] = &WS2812FX::mode_scan; - _mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan; - _mode[FX_MODE_FADE] = &WS2812FX::mode_fade; - _mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase; - _mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow; - _mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights; - _mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle; - _mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random; - _mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade; - _mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random; - _mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle; - _mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle; - _mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle; - _mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe; - _mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow; - _mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe; - _mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow; - _mode[FX_MODE_ANDROID] = &WS2812FX::mode_android; - _mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color; - _mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random; - _mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow; - _mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash; - _mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random; - _mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white; - _mode[FX_MODE_COLORFUL] = &WS2812FX::mode_colorful; - _mode[FX_MODE_TRAFFIC_LIGHT] = &WS2812FX::mode_traffic_light; - _mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random; - _mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color; - _mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue; - _mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random; - _mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner; - _mode[FX_MODE_COMET] = &WS2812FX::mode_comet; - _mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks; - _mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random; - _mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas; - _mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker; - _mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient; - _mode[FX_MODE_LOADING] = &WS2812FX::mode_loading; + // segment runtime parameters + typedef struct Segment_runtime { // 17 bytes + unsigned long next_time; + uint32_t counter_mode_step; + uint32_t counter_mode_call; + uint16_t aux_param; + uint16_t aux_param2; + bool trans_act; + } segment_runtime; + + WS2812FX() { + _mode[FX_MODE_STATIC] = &WS2812FX::mode_static; + _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; + _mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe; + _mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random; + _mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color; + _mode[FX_MODE_COLOR_SWEEP] = &WS2812FX::mode_color_sweep; + _mode[FX_MODE_DYNAMIC] = &WS2812FX::mode_dynamic; + _mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow; + _mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle; + _mode[FX_MODE_SCAN] = &WS2812FX::mode_scan; + _mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan; + _mode[FX_MODE_FADE] = &WS2812FX::mode_fade; + _mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase; + _mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow; + _mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle; + _mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random; + _mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade; + _mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random; + _mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle; + _mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle; + _mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle; + _mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe; + _mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow; + _mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe; + _mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow; + _mode[FX_MODE_ANDROID] = &WS2812FX::mode_android; + _mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color; + _mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random; + _mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow; + _mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash; + _mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random; + _mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white; + _mode[FX_MODE_COLORFUL] = &WS2812FX::mode_colorful; + _mode[FX_MODE_TRAFFIC_LIGHT] = &WS2812FX::mode_traffic_light; + _mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random; + _mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color; + _mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue; + _mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random; + _mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner; + _mode[FX_MODE_COMET] = &WS2812FX::mode_comet; + _mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks; + _mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random; + _mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas; + _mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker; + _mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient; + _mode[FX_MODE_LOADING] = &WS2812FX::mode_loading; _mode[FX_MODE_DUAL_COLOR_WIPE_IN_OUT] = &WS2812FX::mode_dual_color_wipe_in_out; _mode[FX_MODE_DUAL_COLOR_WIPE_IN_IN] = &WS2812FX::mode_dual_color_wipe_in_in; _mode[FX_MODE_DUAL_COLOR_WIPE_OUT_OUT] = &WS2812FX::mode_dual_color_wipe_out_out; _mode[FX_MODE_DUAL_COLOR_WIPE_OUT_IN] = &WS2812FX::mode_dual_color_wipe_out_in; _mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus; - _mode[FX_MODE_CUSTOM_CHASE] = &WS2812FX::mode_cc_standard; - _mode[FX_MODE_CC_ON_RAINBOW] = &WS2812FX::mode_cc_rainbow; - _mode[FX_MODE_CC_ON_RAINBOW_CYCLE] = &WS2812FX::mode_cc_cycle; - _mode[FX_MODE_CC_BLINK] = &WS2812FX::mode_cc_blink; - _mode[FX_MODE_CC_RANDOM] = &WS2812FX::mode_cc_random; + _mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween; + _mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase; + _mode[FX_MODE_TRICOLOR_WIPE] = &WS2812FX::mode_tricolor_wipe; + _mode[FX_MODE_TRICOLOR_FADE] = &WS2812FX::mode_tricolor_fade; + _mode[FX_MODE_BREATH] = &WS2812FX::mode_breath; + _mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights; + _mode[FX_MODE_LIGHTNING] = &WS2812FX::mode_lightning; + _mode[FX_MODE_ICU] = &WS2812FX::mode_icu; + _mode[FX_MODE_MULTI_COMET] = &WS2812FX::mode_multi_comet; + _mode[FX_MODE_DUAL_LARSON_SCANNER] = &WS2812FX::mode_dual_larson_scanner; + _mode[FX_MODE_RANDOM_CHASE] = &WS2812FX::mode_random_chase; + _mode[FX_MODE_OSCILLATE] = &WS2812FX::mode_oscillate; + _mode[FX_MODE_FIRE_2012] = &WS2812FX::mode_fire_2012; + _mode[FX_MODE_BPM] = &WS2812FX::mode_bpm; + _mode[FX_MODE_JUGGLE] = &WS2812FX::mode_juggle; + _mode[FX_MODE_PALETTE] = &WS2812FX::mode_palette; + _mode[FX_MODE_FILLNOISE8] = &WS2812FX::mode_fillnoise8; + _mode[FX_MODE_NOISE16_1] = &WS2812FX::mode_noise16_1; + _mode[FX_MODE_NOISE16_2] = &WS2812FX::mode_noise16_2; + _mode[FX_MODE_NOISE16_3] = &WS2812FX::mode_noise16_3; + _mode[FX_MODE_NOISE16_4] = &WS2812FX::mode_noise16_4; - _mode_index = DEFAULT_MODE; - _speed = DEFAULT_SPEED; _brightness = DEFAULT_BRIGHTNESS; _running = false; - _led_count = 255; - _mode_last_call_time = 0; - _mode_delay = 0; - _color = DEFAULT_COLOR; - _mode_color = DEFAULT_COLOR; - _color_sec = 0; - _mode_var1 = 0; - _cc_fs = true; - _cc_fe = false; - _cc_is = 0; - _cc_i1 = 0; - _cc_i2 = 254; - _cc_num1 = 5; - _cc_num2 = 5; - _ccStep = 1; - _counter_mode_call = 0; - _counter_mode_step = 0; - _counter_ccStep = 0; - _fastStandard = false; + _num_segments = 1; + _segments[0].mode = DEFAULT_MODE; + _segments[0].colors[0] = DEFAULT_COLOR; + _segments[0].start = 0; + _segments[0].speed = DEFAULT_SPEED; _reverseMode = false; _skipFirstMode = false; _locked = NULL; _cronixieDigits = new byte[6]; bus = new NeoPixelWrapper(); + RESET_RUNTIME; } void - show(void), - setPixelColor(uint16_t i, byte r, byte g, byte b), - setPixelColor(uint16_t i, byte r, byte g, byte b, byte w), - init(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst), + init(bool supportWhite, uint16_t countPixels, bool skipFirst), service(void), - start(void), - stop(void), - setMode(byte m), - setCustomChase(byte i1, uint16_t i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe), - setCCIndex1(byte i1), - setCCIndex2(uint16_t i2), - setCCStart(byte is), - setCCNum1(byte np), - setCCNum2(byte ns), - setCCStep(byte stp), - setCCFS(bool fs), - setCCFE(bool fe), - setSpeed(byte s), - setIntensity(byte in), - increaseSpeed(byte s), - decreaseSpeed(byte s), - setColor(byte r, byte g, byte b), - setColor(byte r, byte g, byte b, byte w), + clear(void), + strip_off(void), + fade_out(uint8_t r), + setMode(uint8_t m), + setSpeed(uint8_t s), + setIntensity(uint8_t i), + setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), + setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setColor(uint32_t c), - setSecondaryColor(byte r, byte g, byte b), - setSecondaryColor(byte r, byte g, byte b, byte w), setSecondaryColor(uint32_t c), - setBrightness(byte b), - increaseBrightness(byte s), - decreaseBrightness(byte s), + setBrightness(uint8_t b), setReverseMode(bool b), driverModeCronixie(bool b), setCronixieDigits(byte* d), setCronixieBacklight(bool b), - setIndividual(int i), - setIndividual(int i, uint32_t col), - setRange(int i, int i2), - setRange(int i, int i2, uint32_t col), - lock(int i), - lockRange(int i, int i2), - lockAll(void), - unlock(int i), - unlockRange(int i, int i2), + setIndividual(uint16_t i, uint32_t col), + setRange(uint16_t i, uint16_t i2, uint32_t col), + lock(uint16_t i), + lockRange(uint16_t i, uint16_t i2), + unlock(uint16_t i), + unlockRange(uint16_t i, uint16_t i2), unlockAll(void), - setFastUpdateMode(bool b), trigger(void), - setFade(int sp); + setNumSegments(uint8_t n), + setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint8_t speed, uint8_t intensity, bool reverse), + setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, bool reverse), + setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, uint8_t options), + resetSegments(), + 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); - bool - isRunning(void), - isLocked(int i); - - byte - get_random_wheel_index(byte), + uint8_t + getBrightness(void), getMode(void), getSpeed(void), - getIntensity(void), - getBrightness(void), - getModeCount(void); + getNumSegments(void), + get_random_wheel_index(uint8_t); uint32_t - color_wheel(byte), + color_wheel(uint8_t), + color_blend(uint32_t,uint32_t,uint8_t), + getPixelColor(uint16_t), getColor(void); double getPowerEstimate(uint16_t leds, uint32_t c, byte b), getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b); - private: - NeoPixelWrapper *bus; + WS2812FX::Segment + getSegment(void); - void - begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst), - clear(void), - setPixelColor(uint16_t i, uint32_t c), - setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w), - dofade(void), - strip_off(void), - strip_off_respectLock(void), + WS2812FX::Segment_runtime + getSegmentRuntime(void); + + WS2812FX::Segment* + getSegments(void); + + // mode helper functions + uint16_t + blink(uint32_t, uint32_t, bool strobe), + color_wipe(uint32_t, uint32_t, bool), + theater_chase(uint32_t, uint32_t), + twinkle(uint32_t), + twinkle_fade(uint32_t), + chase(uint32_t, uint32_t, uint32_t), + running(uint32_t, uint32_t), + fireworks(uint32_t), + tricolor_chase(uint32_t, uint32_t, uint32_t); + + // builtin modes + uint16_t mode_static(void), mode_blink(void), + mode_blink_rainbow(void), + mode_strobe(void), + mode_strobe_rainbow(void), mode_color_wipe(void), + mode_color_sweep(void), mode_color_wipe_random(void), + mode_color_sweep_random(void), mode_random_color(void), - mode_easter(void), mode_dynamic(void), mode_breath(void), mode_fade(void), @@ -308,10 +373,7 @@ class WS2812FX { mode_sparkle(void), mode_flash_sparkle(void), mode_hyper_sparkle(void), - mode_strobe(void), - mode_strobe_rainbow(void), mode_multi_strobe(void), - mode_blink_rainbow(void), mode_android(void), mode_chase_color(void), mode_chase_random(void), @@ -320,9 +382,7 @@ class WS2812FX { mode_chase_flash_random(void), mode_chase_rainbow_white(void), mode_colorful(void), - mode_colorful_internal(uint32_t*), mode_traffic_light(void), - mode_color_sweep_random(void), mode_running_color(void), mode_running_red_blue(void), mode_running_random(void), @@ -331,6 +391,7 @@ class WS2812FX { mode_fireworks(void), mode_fireworks_random(void), mode_merry_christmas(void), + mode_halloween(void), mode_fire_flicker(void), mode_gradient(void), mode_loading(void), @@ -339,67 +400,57 @@ class WS2812FX { mode_dual_color_wipe_out_out(void), mode_dual_color_wipe_out_in(void), mode_circus_combustus(void), - mode_cc_core(void), - mode_cc_standard(void), - mode_cc_rainbow(void), - mode_cc_cycle(void), - mode_cc_blink(void), - mode_cc_random(void); + mode_bicolor_chase(void), + mode_tricolor_chase(void), + mode_tricolor_wipe(void), + mode_tricolor_fade(void), + mode_icu(void), + mode_multi_comet(void), + mode_dual_larson_scanner(void), + mode_random_chase(void), + mode_oscillate(void), + mode_fire_2012(void), + mode_bpm(void), + mode_juggle(void), + mode_palette(void), + mode_fillnoise8(void), + mode_noise16_1(void), + mode_noise16_2(void), + mode_noise16_3(void), + mode_noise16_4(void), + mode_lightning(void); - bool - _triggered, - _rgbwMode, - _skipFirstMode, - _fastStandard, - _reverseMode, - _cronixieMode, - _cronixieBacklightEnabled, - _cc_fs, - _cc_fe, - _running; - - bool* - _locked; - - byte - _mode_index, - _speed, - _intensity, - _cc_i1, - _cc_is, - _cc_num1, - _cc_num2, - _ccStep, - _brightness; - - byte* - _cronixieDigits; - - uint16_t - minval(uint16_t v, uint16_t w), - maxval(uint16_t v, uint16_t w), - _cc_i2, - _led_count; - - uint32_t - getPixelColor(uint16_t i), - _color, - _color_sec, - _counter_mode_call, - _counter_mode_step, - _counter_ccStep, - _mode_var1, - _mode_color, - _mode_delay; + private: + NeoPixelWrapper *bus; + + uint16_t _length; + uint16_t _rand16seed; + uint8_t _brightness; double _cronixieSecMultiplier; - unsigned long - _mode_last_call_time; + boolean + _running, + _rgbwMode, + _reverseMode, + _cronixieMode, + _cronixieBacklightEnabled, + _skipFirstMode, + _triggered; - mode_ptr - _mode[MODE_COUNT]; + byte* _locked; + byte* _cronixieDigits; + + mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element + + uint8_t _segment_index = 0; + uint8_t _num_segments = 1; + segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element + // start, stop, speed, intensity, mode, options, color[] + { 0, 7, DEFAULT_SPEED, 128, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}} + }; + segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 17 bytes per element }; #endif diff --git a/wled00/data/index.htm b/wled00/data/index.htm index 1903a027..9d8e935f 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -2,7 +2,7 @@ - WLED 0.7.1 + WLED 0.8.0-a +WLED 0.8.0-a + )====="; //head1 (css) @@ -101,92 +97,21 @@ const char PAGE_index3[] PROGMEM = R"=====( - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
Effect Panel



-

Set secondary color to @@ -194,43 +119,27 @@ Set secondary color to -or -
-
Custom Theater Chase
-using primary and - secondary color LEDs,
-doing steps per tick, -from start and end. -
-
-
-
-
-
-
+or
+
FastLED Palette

+
+
+
Favorite Presets




-Click checkmark to apply brightness, color and effects.

-Cycle through presets to , keep each for ms:

-
-
+Click checkmark to apply brightness, color and effects.

+Cycle through presets to , keep each for ms:

+
Timed Light



Gradually dim down
-1st slider sets duration (1-255min), 2nd sets target brightness. -
-
-
-
-
-
- -
- - - +1st slider sets duration (1-255min), 2nd sets target brightness.
+
+
+
+ )====="; diff --git a/wled00/htmls01.h b/wled00/htmls01.h index 035dd959..3090e683 100644 --- a/wled00/htmls01.h +++ b/wled00/htmls01.h @@ -110,7 +110,6 @@ Use Gamma correction for color:
Brightness factor: %

Transitions

Fade:
-Sweep: Invert direction:
Transition Time: ms
Enable transition for secondary color:

Timed light

@@ -278,10 +277,9 @@ Current local time is unknown. Clock Overlay:
First LED: Last LED:
@@ -358,7 +356,7 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
Enable ArduinoOTA:

About

-WLED version 0.7.1

+WLED version 0.8.0-a

Contributors:
StormPie (Mobile HTML UI)

Thank you so much!

diff --git a/wled00/wled00.ino b/wled00/wled00.ino index c4afae66..0845b46c 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -3,7 +3,7 @@ */ /* * @title WLED project sketch - * @version 0.7.1 + * @version 0.8.0-a * @author Christian Schwinne */ @@ -39,8 +39,8 @@ #include "src/dependencies/e131/E131.h" //version in format yymmddb (b = daily build) -#define VERSION 1808111 -char versionString[] = "0.7.1"; +#define VERSION 1809041 +char versionString[] = "0.8.0-a"; //AP and OTA default passwords (change them!) char apPass[65] = "wled1234"; @@ -53,7 +53,7 @@ char otaPass[33] = "wledota"; //#define DEBUG //Hardware-settings (only changeble via code) -#define PIN 2 //strip pin. Only change for ESP32 +//strip pin changeable in NpbWrapper.h. Only change for ESP32 byte buttonPin = 0; //needs pull-up byte auxPin = 15; //use e.g. for external relay byte auxDefaultState = 0; //0: input 1: high 2: low @@ -87,7 +87,6 @@ byte whiteSecS = 0; byte briS = 127; byte nightlightTargetBri = 0; bool fadeTransition = true; -bool sweepTransition = false, sweepDirection = true; bool disableSecTransition = true; uint16_t transitionDelay = 1200, transitionDelayDefault = transitionDelay; bool reverseMode = false; @@ -103,17 +102,10 @@ uint16_t udpPort = 21324, udpRgbPort = 19446; byte effectDefault = 0; byte effectSpeedDefault = 75; byte effectIntensityDefault = 128; +byte effectPaletteDefault = 0; //NTP stuff bool ntpEnabled = false; char ntpServerName[] = "0.wled.pool.ntp.org"; -//custom chase -byte ccNumPrimary = 2; -byte ccNumSecondary = 4; -byte ccIndex1 = 0; -uint16_t ccIndex2 = ledCount -1; -bool ccFromStart = true, ccFromEnd = false; -byte ccStep = 1; -byte ccStart = 0; //alexa bool alexaEnabled = true; @@ -170,6 +162,7 @@ byte briNlT = 0; byte effectCurrent = 0; byte effectSpeed = 75; byte effectIntensity = 128; +byte effectPalette = 0; bool onlyAP = false; bool udpConnected = false, udpRgbConnected = false; char cssCol[9][5]={"","","","","",""}; diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 682b53f0..5111e680 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -15,6 +15,7 @@ //5 -> 0.5.1 and up //6 -> 0.6.0 and up //7 -> 0.7.1 and up +//8 -> 0.8.0 and up /* * Erase all configuration data @@ -119,8 +120,7 @@ void saveSettingsToEEPROM() EEPROM.write(370, useHSBDefault); EEPROM.write(371, whiteS); EEPROM.write(372, useRGBW); - EEPROM.write(373, sweepTransition); - EEPROM.write(374, sweepDirection); + EEPROM.write(375, apWaitTimeSecs); EEPROM.write(376, recoveryAPDisabled); EEPROM.write(377, EEPVER); //eeprom was updated to latest @@ -128,13 +128,7 @@ void saveSettingsToEEPROM() EEPROM.write(379, colSecS[1]); EEPROM.write(380, colSecS[2]); EEPROM.write(381, whiteSecS); - EEPROM.write(382, ccIndex1); - EEPROM.write(383, ccIndex2); - EEPROM.write(384, ccNumPrimary); - EEPROM.write(385, ccNumSecondary); - EEPROM.write(386, ccFromStart); - EEPROM.write(387, ccFromEnd); - EEPROM.write(388, ccStep); + EEPROM.write(389, bootPreset); EEPROM.write(390, aOtaEnabled); EEPROM.write(391, receiveNotificationColor); @@ -344,6 +338,8 @@ void loadSettingsFromEEPROM(bool first) useGammaCorrectionBri = EEPROM.read(330); useGammaCorrectionRGB = EEPROM.read(331); overlayDefault = EEPROM.read(332); + if (lastEEPROMversion < 8 && overlayDefault > 0) overlayDefault--; //overlay mode 1 (solid) was removed + alexaEnabled = EEPROM.read(333); for (int i = 334; i < 366; ++i) @@ -358,8 +354,7 @@ void loadSettingsFromEEPROM(bool first) useHSBDefault = EEPROM.read(370); whiteS = EEPROM.read(371); white = whiteS; useRGBW = EEPROM.read(372); - sweepTransition = EEPROM.read(373); - sweepDirection = EEPROM.read(374); + if (lastEEPROMversion > 0) { apWaitTimeSecs = EEPROM.read(375); recoveryAPDisabled = EEPROM.read(376); @@ -369,15 +364,7 @@ void loadSettingsFromEEPROM(bool first) colSecS[0] = EEPROM.read(378); colSec[0] = colSecS[0]; colSecS[1] = EEPROM.read(379); colSec[1] = colSecS[1]; colSecS[2] = EEPROM.read(380); colSec[2] = colSecS[2]; - whiteSecS = EEPROM.read(381); whiteSec = whiteSecS; - ccIndex1 = EEPROM.read(382); - ccIndex2 = EEPROM.read(383); - ccNumPrimary = EEPROM.read(384); - ccNumSecondary = EEPROM.read(385); - ccFromStart = EEPROM.read(386); - ccFromEnd = EEPROM.read(387); - ccStep = EEPROM.read(388); - strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd); + whiteSecS = EEPROM.read(381); whiteSec = whiteSecS; } if (lastEEPROMversion > 3) { effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault; @@ -545,12 +532,6 @@ void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX) effectCurrent = EEPROM.read(i+10); effectSpeed = EEPROM.read(i+11); effectIntensity = EEPROM.read(i+16); - ccNumPrimary = EEPROM.read(i+12); - ccNumSecondary = EEPROM.read(i+13); - ccFromEnd = EEPROM.read(i+14); - ccFromStart = (EEPROM.read(i+14)<2); - ccStep = EEPROM.read(i+15); - strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd); if (lastfx != effectCurrent) strip.setMode(effectCurrent); strip.setSpeed(effectSpeed); strip.setIntensity(effectIntensity); @@ -574,13 +555,7 @@ void savePreset(byte index) EEPROM.write(i+9, whiteSec); EEPROM.write(i+10, effectCurrent); EEPROM.write(i+11, effectSpeed); - EEPROM.write(i+12, ccNumPrimary); - EEPROM.write(i+13, ccNumSecondary); - byte m = 1; - if (!ccFromStart) m = 2; - if (!ccFromEnd) m = 0; - EEPROM.write(i+14, m); - EEPROM.write(i+15, ccStep); + EEPROM.write(i+16, effectIntensity); EEPROM.commit(); } diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino index 414d5b94..19dfdfa8 100644 --- a/wled00/wled02_xml.ino +++ b/wled00/wled02_xml.ino @@ -188,8 +188,6 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript sappend('c',"GB",useGammaCorrectionBri); sappend('c',"GC",useGammaCorrectionRGB); sappend('c',"TF",fadeTransition); - sappend('c',"TS",sweepTransition); - sappend('c',"TI",!sweepDirection); sappend('v',"TD",transitionDelay); sappend('c',"T2",!disableSecTransition); sappend('v',"BF",briMultiplier); diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index a43fac2b..ca90b691 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -74,7 +74,6 @@ void handleSettingsSet(byte subPage) if (ledCount > 600) ledCount = 600; #endif } - ccIndex2 = ledCount -1; useRGBW = server.hasArg("EW"); autoRGBtoRGBW = server.hasArg("AW"); if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default @@ -158,8 +157,6 @@ void handleSettingsSet(byte subPage) useGammaCorrectionBri = server.hasArg("GB"); useGammaCorrectionRGB = server.hasArg("GC"); fadeTransition = server.hasArg("TF"); - sweepTransition = server.hasArg("TS"); - sweepDirection = !server.hasArg("TI"); if (server.hasArg("TD")) { int i = server.arg("TD").toInt(); @@ -288,7 +285,7 @@ void handleSettingsSet(byte subPage) if (server.hasArg("OL")){ overlayDefault = server.arg("OL").toInt(); overlayCurrent = overlayDefault; - strip.unlockAll(); + ; } if (server.hasArg("O1")) overlayMin = server.arg("O1").toInt(); if (server.hasArg("O2")) overlayMax = server.arg("O2").toInt(); @@ -357,7 +354,7 @@ void handleSettingsSet(byte subPage) } } saveSettingsToEEPROM(); - if (subPage == 2) strip.init(useRGBW,ledCount,PIN,skipFirstLed); + if (subPage == 2) strip.init(useRGBW,ledCount,skipFirstLed); } bool handleSet(String req) @@ -462,6 +459,7 @@ bool handleSet(String req) colSec[2] = 255; } } + //set 2nd to black pos = req.indexOf("SB"); if (pos > 0) { @@ -470,6 +468,7 @@ bool handleSet(String req) colSec[1] = 0; colSec[2] = 0; } + //set to random hue SR=0->1st SR=1->2nd pos = req.indexOf("SR"); if (pos > 0) { @@ -553,19 +552,6 @@ bool handleSet(String req) overlayCurrent = req.substring(pos + 3).toInt(); strip.unlockAll(); } - //set individual pixel (range) to current color - pos = req.indexOf("&I="); - if (pos > 0){ - int index = req.substring(pos + 3).toInt(); - pos = req.indexOf("I2="); - if (pos > 0){ - int index2 = req.substring(pos + 3).toInt(); - strip.setRange(index, index2); - } else - { - strip.setIndividual(index); - } - } //(un)lock pixel (ranges) pos = req.indexOf("&L="); if (pos > 0){ @@ -591,6 +577,7 @@ bool handleSet(String req) } } } + //apply macro pos = req.indexOf("&M="); if (pos > 0) { @@ -605,6 +592,7 @@ bool handleSet(String req) notifyDirect = false; } } + //toggle receive UDP direct notifications if (req.indexOf("RN=") > 0) { @@ -614,6 +602,7 @@ bool handleSet(String req) receiveNotifications = false; } } + //toggle nightlight mode bool aNlDef = false; if (req.indexOf("&ND") > 0) aNlDef = true; @@ -634,12 +623,14 @@ bool handleSet(String req) nightlightActive = true; nightlightStartTime = millis(); } + //set nightlight target brightness pos = req.indexOf("NT="); if (pos > 0) { nightlightTargetBri = req.substring(pos + 3).toInt(); nightlightActiveOld = false; //re-init } + //toggle nightlight fade if (req.indexOf("NF=") > 0) { @@ -651,6 +642,7 @@ bool handleSet(String req) } nightlightActiveOld = false; //re-init } + //toggle general purpose output pos = req.indexOf("AX="); if (pos > 0) { @@ -662,6 +654,7 @@ bool handleSet(String req) if (pos > 0) { transitionDelay = req.substring(pos + 3).toInt(); } + //main toggle on/off pos = req.indexOf("&T="); if (pos > 0) { @@ -679,6 +672,7 @@ bool handleSet(String req) } } } + //deactivate nightlight if target brightness is reached if (bri == nightlightTargetBri) nightlightActive = false; //set time (unix timestamp) @@ -686,6 +680,7 @@ bool handleSet(String req) if (pos > 0) { setTime(req.substring(pos+3).toInt()); } + //set countdown goal (unix timestamp) pos = req.indexOf("CT="); if (pos > 0) { @@ -693,19 +688,6 @@ bool handleSet(String req) if (countdownTime - now() > 0) countdownOverTriggered = false; } - //set custom chase data - bool _cc_updated = false; - pos = req.indexOf("C0="); if (pos > 0) {ccStart = (req.substring(pos + 3).toInt()); _cc_updated = true;} - pos = req.indexOf("C1="); if (pos > 0) {ccIndex1 = (req.substring(pos + 3).toInt()); _cc_updated = true;} - pos = req.indexOf("C2="); if (pos > 0) {ccIndex2 = (req.substring(pos + 3).toInt()); _cc_updated = true;} - pos = req.indexOf("CP="); if (pos > 0) {ccNumPrimary = (req.substring(pos + 3).toInt()); _cc_updated = true;} - pos = req.indexOf("CS="); if (pos > 0) {ccNumSecondary = (req.substring(pos + 3).toInt()); _cc_updated = true;} - pos = req.indexOf("CM="); if (pos > 0) {ccStep = (req.substring(pos + 3).toInt()); _cc_updated = true;} - pos = req.indexOf("CF="); if (pos > 0) {ccFromStart = (req.substring(pos + 3).toInt()); _cc_updated = true;} - pos = req.indexOf("CE="); if (pos > 0) {ccFromEnd = (req.substring(pos + 3).toInt()); _cc_updated = true;} - if (ccIndex2 == 255) ccIndex2 = ledCount-1; - if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd); - //set presets pos = req.indexOf("P1="); //sets first preset for cycle if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt(); diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index e11d9f9f..66fea65d 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -11,7 +11,7 @@ void wledInit() #ifdef ARDUINO_ARCH_ESP32 if (ledCount > 600) ledCount = 600; #endif - if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,PIN,EEPROM.read(2204)); //quick init + if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,EEPROM.read(2204)); //quick init Serial.begin(115200); Serial.setTimeout(50); @@ -273,11 +273,10 @@ void wledInit() void initStrip() { // Initialize NeoPixel Strip and button - if (initLedsLast) strip.init(useRGBW,ledCount,PIN,skipFirstLed); + if (initLedsLast) strip.init(useRGBW,ledCount,skipFirstLed); strip.setReverseMode(reverseMode); strip.setColor(0); strip.setBrightness(255); - strip.start(); pinMode(buttonPin, INPUT_PULLUP); pinMode(4,OUTPUT); //this is only needed in special cases @@ -572,11 +571,11 @@ void getBuildInfo() oappend("\r\n"); #ifdef ARDUINO_ARCH_ESP32 oappend("strip-pin: gpio"); - oappendi(PIN); + oappendi(LEDPIN); #else oappend("strip-pin: gpio2"); #endif - oappend("\r\nbuild-type: src\r\n"); + oappend("\r\nbuild-type: dev\r\n"); } bool checkClientIsMobile(String useragent) diff --git a/wled00/wled08_led.ino b/wled00/wled08_led.ino index e3b001cc..46e5aed0 100644 --- a/wled00/wled08_led.ino +++ b/wled00/wled08_led.ino @@ -93,7 +93,7 @@ void colorUpdated(int callMode) briIT = bri; if (bri > 0) briLast = bri; notify(callMode); - if (fadeTransition || sweepTransition) + if (fadeTransition) { //set correct delay if not using notification delay if (callMode != 3) transitionDelayTemp = transitionDelay; @@ -114,7 +114,6 @@ void colorUpdated(int callMode) } transitionActive = true; transitionStartTime = millis(); - strip.setFastUpdateMode(true); } else { setLedsStandard(); @@ -132,9 +131,7 @@ void handleTransitions() { transitionActive = false; tperLast = 0; - if (sweepTransition) strip.unlockAll(); setLedsStandard(); - strip.setFastUpdateMode(false); return; } if (tper - tperLast < 0.004) @@ -153,21 +150,7 @@ void handleTransitions() whiteSecT = whiteSecOld +((whiteSec - whiteSecOld )*tper); briT = briOld +((bri - briOld )*tper); } - if (sweepTransition) - { - strip.lockAll(); - if (sweepDirection) - { - strip.unlockRange(0, (int)(tper*(double)ledCount)); - } else - { - strip.unlockRange(ledCount - (int)(tper*(double)ledCount), ledCount); - } - if (!fadeTransition) - { - setLedsStandard(); - } - } + //TODO: properly remove sweep transition if (fadeTransition) setAllLeds(); } } diff --git a/wled00/wled11_ol.ino b/wled00/wled11_ol.ino index 1cdc9cdd..8695d51a 100644 --- a/wled00/wled11_ol.ino +++ b/wled00/wled11_ol.ino @@ -125,24 +125,15 @@ void handleOverlays() switch (overlayCurrent) { case 0: break;//no overlay - case 1: _overlaySolid(); break;//solid secondary color - case 2: _overlayAnalogClock(); break;//2 analog clock - case 3: _overlayNixieClock(); break;//nixie 1-digit - case 4: _overlayCronixie();//Diamex cronixie clock kit + case 1: _overlayAnalogClock(); break;//2 analog clock + case 2: _overlayNixieClock(); break;//nixie 1-digit + case 3: _overlayCronixie();//Diamex cronixie clock kit } if (!countdownMode || overlayCurrent < 2) checkCountdown(); //countdown macro activation must work overlayRefreshedTime = millis(); } } -void _overlaySolid() -{ - strip.unlockAll(); - uint32_t cls = (useGammaCorrectionRGB)? gamma8[whiteSec*16777216] + gamma8[colSec[0]]*65536 + gamma8[colSec[1]]*256 + gamma8[colSec[2]]:whiteSec*16777216 + colSec[0]*65536 + colSec[1]*256 + colSec[2]; - strip.setRange(overlayMin,overlayMax,cls); - overlayRefreshMs = 1902; -} - void _overlayAnalogClock() { int overlaySize = overlayMax - overlayMin +1; @@ -151,7 +142,6 @@ void _overlayAnalogClock() { _overlayAnalogCountdown(); return; } - _overlaySolid(); double hourP = ((double)(hour(local)%12))/12; double minuteP = ((double)minute(local))/60; hourP = hourP + minuteP/12; diff --git a/wled00/wled16_blynk.ino b/wled00/wled16_blynk.ino index 4120f03b..82aae164 100644 --- a/wled00/wled16_blynk.ino +++ b/wled00/wled16_blynk.ino @@ -58,18 +58,21 @@ BLYNK_WRITE(V3) BLYNK_WRITE(V4) { effectCurrent = param.asInt()-1;//fx - colorUpdated(9); + strip.setMode(effectCurrent); + colorUpdated(6); } BLYNK_WRITE(V5) { effectSpeed = param.asInt();//sx + strip.setSpeed(effectSpeed); colorUpdated(6); } BLYNK_WRITE(V6) { effectIntensity = param.asInt();//ix + strip.setIntensity(effectIntensity); colorUpdated(6); }