From 70d0aae07cc3d7e371d0463769965ce20a5e9124 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 4 Sep 2018 15:51:38 +0200 Subject: [PATCH] First commit of 0.8.0 dev cycle Updated to newer WS2812FX version which supports segments (not supported in WLED yet) Added new (FastLED) effects Adjusted FX speed timings Removed Sweep transition and Custom Chase (seldomly used - hinder development) Removed solid overlay (no longer needed once segments are added) Fixed Blynk effect set --- wled00/NpbWrapper.h | 18 +- wled00/WS2812FX.cpp | 3980 ++++++++++++++++----------------- wled00/WS2812FX.h | 485 ++-- wled00/data/index.htm | 69 +- wled00/data/settings_leds.htm | Bin 8538 -> 8336 bytes wled00/data/settings_time.htm | Bin 12512 -> 12424 bytes wled00/htmls00.h | 145 +- wled00/htmls01.h | 10 +- wled00/wled00.ino | 19 +- wled00/wled01_eeprom.ino | 41 +- wled00/wled02_xml.ino | 2 - wled00/wled03_set.ino | 44 +- wled00/wled05_init.ino | 9 +- wled00/wled08_led.ino | 21 +- wled00/wled11_ol.ino | 16 +- wled00/wled16_blynk.ino | 5 +- 16 files changed, 2374 insertions(+), 2490 deletions(-) diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index b97ae8e5e..5912966a1 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 9b2e0e746..505f0ba84 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 2ea09e4f8..f1537938e 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 1903a027e..9d8e935f6 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 035dd9599..3090e6835 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 c4afae66f..0845b46c4 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 682b53f0c..5111e680a 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 414d5b946..19dfdfa8f 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 a43fac2b2..ca90b6911 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 e11d9f9fe..66fea65db 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 e3b001cc6..46e5aed0b 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 1cdc9cddb..8695d51af 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 4120f03b6..82aae164d 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); }