kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			
		
			
				
	
	
		
			2079 wiersze
		
	
	
		
			52 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			2079 wiersze
		
	
	
		
			52 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|   WS2812FX.cpp - 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
 | |
|   NOTES
 | |
|     * Uses the Adafruit Neopixel library. Get it here: 
 | |
|       https://github.com/adafruit/Adafruit_NeoPixel
 | |
|   LICENSE
 | |
|   The MIT License (MIT)
 | |
|   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
 | |
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
|   copies of the Software, and to permit persons to whom the Software is
 | |
|   furnished to do so, subject to the following conditions:
 | |
|   The above copyright notice and this permission notice shall be included in
 | |
|   all copies or substantial portions of the Software.
 | |
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
|   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.
 | |
|   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)
 | |
| */
 | |
| 
 | |
| #include "Arduino.h"
 | |
| #include "WS2812FX.h"
 | |
| 
 | |
| #define CALL_MODE(n) (this->*_mode[n])();
 | |
| 
 | |
| void WS2812FX::init() {
 | |
|   for (int i=0; i < _led_count; i++) _locked[i] = false;
 | |
|   begin();
 | |
|   WS2812FX::setBrightness(_brightness);
 | |
|   show();
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| void WS2812FX::stop() {
 | |
|   _running = false;
 | |
|   strip_off();
 | |
| }
 | |
| 
 | |
| void WS2812FX::setMode(uint8_t 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;
 | |
|   setBrightness(_brightness);
 | |
|   strip_off_respectLock();
 | |
| }
 | |
| 
 | |
| void WS2812FX::setSpeed(uint8_t s) {
 | |
|   _counter_mode_call = 0;
 | |
|   _counter_mode_step = 0;
 | |
|   _mode_last_call_time = 0;
 | |
|   _speed = constrain(s, SPEED_MIN, SPEED_MAX);
 | |
|   strip_off_respectLock();
 | |
| }
 | |
| 
 | |
| void WS2812FX::increaseSpeed(uint8_t s) {
 | |
|   s = constrain(_speed + s, SPEED_MIN, SPEED_MAX);
 | |
|   setSpeed(s);
 | |
| }
 | |
| 
 | |
| void WS2812FX::decreaseSpeed(uint8_t s) {
 | |
|   s = constrain(_speed - s, SPEED_MIN, SPEED_MAX);
 | |
|   setSpeed(s);
 | |
| }
 | |
| 
 | |
| void WS2812FX::setIntensity(uint8_t in) {
 | |
|   _intensity=in;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b) {
 | |
|   setColor(((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
 | |
| }
 | |
| 
 | |
| 
 | |
| 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) {
 | |
|   setSecondaryColor(((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) {
 | |
|   _color = c;
 | |
|   _mode_color = _color;
 | |
|   setBrightness(_brightness);
 | |
| }
 | |
| 
 | |
| void WS2812FX::setSecondaryColor(uint32_t c) {
 | |
|   _color_sec = c;
 | |
|   _mode_color_sec = _color;
 | |
|   if (_cronixieMode) _cronixieSecMultiplier = getSafePowerMultiplier(900, 100, c, _brightness);
 | |
|   setBrightness(_brightness);
 | |
| }
 | |
| 
 | |
| void WS2812FX::increaseBrightness(uint8_t s) {
 | |
|   s = constrain(_brightness + s, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
 | |
|   setBrightness(s);
 | |
| }
 | |
| 
 | |
| void WS2812FX::decreaseBrightness(uint8_t s) {
 | |
|   s = constrain(_brightness - s, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
 | |
|   setBrightness(s);
 | |
| }
 | |
| 
 | |
| boolean WS2812FX::isRunning() {
 | |
|   return _running; 
 | |
| }
 | |
| 
 | |
| uint8_t WS2812FX::getMode(void) {
 | |
|   return _mode_index;
 | |
| }
 | |
| 
 | |
| uint8_t WS2812FX::getSpeed(void) {
 | |
|   return _speed;
 | |
| }
 | |
| 
 | |
| uint8_t WS2812FX::getBrightness(void) {
 | |
|   return _brightness;
 | |
| }
 | |
| 
 | |
| uint8_t 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(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);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * 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 = 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 every LED in a random color. Changes one random LED after the other
 | |
|  * to another random color.
 | |
|  */
 | |
| void WS2812FX::mode_single_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)));
 | |
|     }
 | |
|   }
 | |
|   int ran = random(_led_count);
 | |
|   if (!_locked[ran])
 | |
|   setPixelColor(ran, color_wheel(random(256)));
 | |
|   show();
 | |
|   _mode_delay = 10 + ((5000 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Lights multiple random leds in a random color (higher intensity, more updates)
 | |
|  */
 | |
| void WS2812FX::mode_multi_dynamic(void) {
 | |
|   for(uint16_t i=0; i < _led_count; i++) {
 | |
|     if (!_locked[i] && random(256)<=_intensity)
 | |
|     setPixelColor(i, 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
 | |
|   uint8_t 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;
 | |
|   }
 | |
| 
 | |
|   uint8_t 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(uint8_t));
 | |
|   }
 | |
|   
 | |
|   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
 | |
|   NeoPixelBrightnessBus::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;
 | |
|   uint8_t w = ((_color >> 24) & 0xFF), ws = ((_color_sec >> 24) & 0xFF);
 | |
|   uint8_t r = ((_color >> 16) & 0xFF), rs = ((_color_sec >> 16) & 0xFF);
 | |
|   uint8_t g = ((_color >> 8) & 0xFF), gs = ((_color_sec >> 8) & 0xFF);
 | |
|   uint8_t 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) {
 | |
|   uint8_t 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) {
 | |
|   uint8_t 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) {
 | |
|   uint8_t w = ((_color >> 24) & 0xFF);
 | |
|   uint8_t r = ((_color >> 16) & 0xFF);
 | |
|   uint8_t g = ((_color >> 8) & 0xFF);
 | |
|   uint8_t 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(3) == 0) {
 | |
|     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(10) == 7) {
 | |
|     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(10) < 4) {
 | |
|     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);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * _color running on _color_sec.
 | |
|  */
 | |
| void WS2812FX::mode_chase_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);
 | |
|   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 on _color.
 | |
|  */
 | |
| void WS2812FX::mode_chase_color(void) {
 | |
|   for(uint16_t i=0; i < _led_count; i++) {
 | |
|     if (!_locked[i])
 | |
|     setPixelColor(i, _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 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 uint8_t flash_count = 4;
 | |
|   uint8_t 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 uint8_t flash_count = 4;
 | |
|   uint8_t 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};
 | |
|   int i = 0;
 | |
|   for (i; i < _led_count-3 ; 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]);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   show();
 | |
|   if (_speed > SPEED_MIN) _counter_mode_step++; //static if lowest speed
 | |
|   if (_counter_mode_step >3) _counter_mode_step = 0;
 | |
|   _mode_delay = 100 + (25 * (uint32_t)(SPEED_MAX - _speed));
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * 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)
 | |
|   {
 | |
|     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));
 | |
|   } 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 (!_locked[i-1])
 | |
|       {
 | |
|         setPixelColor(i, getPixelColor(i-1));
 | |
|       } else
 | |
|       {
 | |
|         setPixelColor(i, color_wheel(_mode_color));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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<maxval(1,_led_count/20); i++) {
 | |
|     if(random(10) == 0) {
 | |
|       int ran = random(_led_count);
 | |
|       if (!_locked[ran])
 | |
|       setPixelColor(random(_led_count), _mode_color);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   show();
 | |
| 
 | |
|   _mode_delay = 20 + ((20 * (uint32_t)(SPEED_MAX - _speed)) / _led_count);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Random colored firework sparks.
 | |
|  */
 | |
| void WS2812FX::mode_fireworks_random(void) {
 | |
|   _mode_color = color_wheel(random(256));
 | |
|   mode_fireworks();
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Alternating red/green pixels running. (RED)
 | |
|  */
 | |
| void WS2812FX::mode_merry_christmas(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, 255, 0);
 | |
|     }
 | |
|   }
 | |
|   show();
 | |
| 
 | |
|   _counter_mode_step = (_counter_mode_step + 1) % 4;
 | |
|   _mode_delay = 50 + ((75 * (uint32_t)(SPEED_MAX - _speed)) / _led_count);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Random flickering.
 | |
|  */
 | |
| void WS2812FX::mode_fire_flicker(void) {
 | |
|    mode_fire_flicker_int(3);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Random flickering, less intesity.
 | |
|  */
 | |
| void WS2812FX::mode_fire_flicker_soft(void) {
 | |
|    mode_fire_flicker_int(6);
 | |
| }
 | |
| 
 | |
| void WS2812FX::mode_fire_flicker_int(int rev_intensity)
 | |
| {
 | |
|     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 flicker_val = maxval(p_r,maxval(p_g, maxval(p_b, p_w)))/rev_intensity;
 | |
|     for(uint16_t i=0; i < _led_count; 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 + ((500 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX);
 | |
| }
 | |
| 
 | |
| void WS2812FX::mode_fade_down(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);
 | |
|     } 
 | |
|     show();
 | |
| 
 | |
|     _mode_delay = 100 + ((100 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * 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);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   _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_cc_step) % _cc_i2) +_cc_i1;
 | |
|       if (_cc_fs) setPixelColor(num, _color);
 | |
|       if (_cc_fe) setPixelColor(_cc_i2 - num, _color);
 | |
|     }
 | |
|   }
 | |
|   show();
 | |
|   _counter_cc_step = (_counter_cc_step + _cc_step) % (_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::setLedCount(uint16_t i)
 | |
| {
 | |
|   _led_count = i;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setFastUpdateMode(bool y)
 | |
| {
 | |
|   _fastStandard = y;
 | |
|   if (_mode_index == 0) _mode_delay = 20;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setReverseMode(bool b)
 | |
| {
 | |
|   _reverseMode = b;
 | |
| }
 | |
| 
 | |
| void WS2812FX::driverModeCronixie(bool b)
 | |
| {
 | |
|   _cronixieMode = b;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCronixieBacklight(bool b)
 | |
| {
 | |
|   _cronixieBacklightEnabled = b;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCronixieDigits(uint8_t d[])
 | |
| {
 | |
|   for (int i = 0; i<6; i++)
 | |
|   {
 | |
|     _cronixieDigits[i] = d[i];
 | |
|   }
 | |
| }
 | |
| 
 | |
| double WS2812FX::getPowerEstimate(uint8_t leds, uint32_t c, uint8_t 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);
 | |
|   #ifdef RGBW
 | |
|   _sum /= 1024;
 | |
|   #else
 | |
|   _sum /= 768;
 | |
|   #endif
 | |
|   double _mAPerLed = 50*(_mul*_sum);
 | |
|   _mARequired += leds*_mAPerLed;
 | |
|   return _mARequired;
 | |
| }
 | |
| 
 | |
| //DISCLAIMER
 | |
| //This is just a helper function for huge amounts of LEDs.
 | |
| //It is NOT guaranteed to stay within the safeAmps margin.
 | |
| //Stay safe with high amperage and have a reasonable safety margin!
 | |
| //I am NOT to be held liable for burned down garages!
 | |
| double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, uint8_t leds, uint32_t c, uint8_t b)
 | |
| {
 | |
|   double _mARequired = getPowerEstimate(leds,c,b);
 | |
|   if (_mARequired > safeMilliAmps)
 | |
|   {
 | |
|     return safeMilliAmps/_mARequired;
 | |
|   }
 | |
|   return 1.0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCIndex1(uint8_t i1)
 | |
| {
 | |
|   if (i1 < _led_count-1) _cc_i1 = i1;
 | |
|   if (_cc_i2 <= i1) _cc_i2 = i1+1;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCIndex2(uint8_t i2)
 | |
| {
 | |
|   if (i2 > _cc_i1) _cc_i2 = i2;
 | |
|   if (_cc_i2 >= _led_count) _cc_i2 = _led_count-1;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCStart(uint8_t is)
 | |
| {
 | |
|   _cc_is = (is < _cc_i1 || is > _cc_i2) ? _cc_i1 : is;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCNum1(uint8_t np)
 | |
| {
 | |
|   _cc_num1 = np;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCNum2(uint8_t ns)
 | |
| {
 | |
|   _cc_num2 = ns;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCStep(uint8_t stp)
 | |
| {
 | |
|   _cc_step = stp;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCFS(bool fs)
 | |
| {
 | |
|   _cc_fs = fs;
 | |
|   _cc_fe = (fs) ? _cc_fe : true;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCCFE(bool fe)
 | |
| {
 | |
|   _cc_fe = fe;
 | |
|   _cc_fs = (fe) ? _cc_fs : true;
 | |
|   _counter_cc_step = 0;
 | |
| }
 | |
| 
 | |
| void WS2812FX::setCustomChase(uint8_t i1, uint8_t i2, uint8_t is, uint8_t np, uint8_t ns, uint8_t stp, bool fs, bool fe)
 | |
| {
 | |
|   setCCIndex1(i1);
 | |
|   setCCIndex2(i2);
 | |
|   setCCStart(is);
 | |
|   _cc_num1 = np;
 | |
|   _cc_num2 = ns;
 | |
|   _cc_step = stp;
 | |
|   setCCFS(fs);
 | |
|   setCCFE(fe);
 | |
| }
 | |
| 
 | |
| //Added for quick NeoPixelBus compatibility with Adafruit syntax
 | |
| void WS2812FX::setPixelColorRaw(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
 | |
| {
 | |
|   #ifdef RGBW
 | |
|     NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w));
 | |
|     #else
 | |
|     NeoPixelBrightnessBus::SetPixelColor(i, RgbColor(r,g,b));
 | |
|     #endif
 | |
| }
 | |
| 
 | |
| void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
 | |
| {
 | |
|   if (_reverseMode) i = _led_count - 1 -i;
 | |
|   if (!_cronixieMode)
 | |
|   {
 | |
|     #ifdef RGBW
 | |
|     NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w));
 | |
|     #else
 | |
|     NeoPixelBrightnessBus::SetPixelColor(i, RgbColor(r,g,b));
 | |
|     #endif
 | |
|   } else {
 | |
|     if(i>6)return;
 | |
|     uint8_t o = 10*i;
 | |
|     if (_cronixieBacklightEnabled && _cronixieDigits[i] <11)
 | |
|     {
 | |
|       uint8_t rCorr = (int)(((double)((_color_sec>>16) & 0xFF))*_cronixieSecMultiplier);
 | |
|       uint8_t gCorr = (int)(((double)((_color_sec>>8) & 0xFF))*_cronixieSecMultiplier);
 | |
|       uint8_t bCorr = (int)(((double)((_color_sec) & 0xFF))*_cronixieSecMultiplier);
 | |
|       uint8_t wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier);
 | |
|       for (int j=o; j< o+19; j++)
 | |
|       {
 | |
|         setPixelColorRaw(j,rCorr,gCorr,bCorr,wCorr);
 | |
|       }
 | |
|     } else
 | |
|     {
 | |
|       for (int j=o; j< o+19; j++)
 | |
|       {
 | |
|         setPixelColorRaw(j,0,0,0,0);
 | |
|       }
 | |
|     }
 | |
|     switch(_cronixieDigits[i])
 | |
|     {
 | |
|       case 0: setPixelColorRaw(o+5,r,g,b,w); break;
 | |
|       case 1: setPixelColorRaw(o+0,r,g,b,w); break;
 | |
|       case 2: setPixelColorRaw(o+6,r,g,b,w); break;
 | |
|       case 3: setPixelColorRaw(o+1,r,g,b,w); break;
 | |
|       case 4: setPixelColorRaw(o+7,r,g,b,w); break;
 | |
|       case 5: setPixelColorRaw(o+2,r,g,b,w); break;
 | |
|       case 6: setPixelColorRaw(o+8,r,g,b,w); break;
 | |
|       case 7: setPixelColorRaw(o+3,r,g,b,w); break;
 | |
|       case 8: setPixelColorRaw(o+9,r,g,b,w); break;
 | |
|       case 9: setPixelColorRaw(o+4,r,g,b,w); break;
 | |
|       default: break;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b)
 | |
| {
 | |
|   setPixelColor(i,r,g,b,0);
 | |
| }
 | |
| 
 | |
| 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;
 | |
|     uint8_t 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;
 | |
|     }
 | |
|   }
 | |
|   #ifdef RGBW
 | |
|   RgbwColor lColor = NeoPixelBrightnessBus::GetPixelColor(i);
 | |
|   return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B;
 | |
|   #else
 | |
|   RgbColor lColor = NeoPixelBrightnessBus::GetPixelColor(i);
 | |
|   return lColor.R*65536 + lColor.G*256 + lColor.B;
 | |
|   #endif
 | |
| }
 | |
| 
 | |
| void WS2812FX::setBrightness(uint8_t b)
 | |
| {
 | |
|   _brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
 | |
|   NeoPixelBrightnessBus::SetBrightness(_brightness);
 | |
|   show();
 | |
| }
 | |
| 
 | |
| void WS2812FX::show()
 | |
| {
 | |
|   #ifdef ARDUINO_ARCH_ESP32
 | |
|   delay(1);
 | |
|   portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
 | |
|   NeoPixelBrightnessBus::Show();
 | |
|   portENABLE_INTERRUPTS();
 | |
|   #else
 | |
|   NeoPixelBrightnessBus::Show();
 | |
|   #endif
 | |
| }
 | |
| 
 | |
| void WS2812FX::clear()
 | |
| {
 | |
|   #ifdef RGBW
 | |
|   NeoPixelBrightnessBus::ClearTo(RgbwColor(0));
 | |
|   #else
 | |
|   NeoPixelBrightnessBus::ClearTo(RgbColor(0));
 | |
|   #endif
 | |
| }
 | |
| 
 | |
| void WS2812FX::begin()
 | |
| {
 | |
|   NeoPixelBrightnessBus::Begin();
 | |
| }
 | |
| 
 | |
| //For some reason min and max are not declared here
 | |
| 
 | |
| uint8_t WS2812FX::minval (uint8_t v, uint8_t w)
 | |
| {
 | |
|   if (w > v) return v;
 | |
|   return w;
 | |
| }
 | |
| 
 | |
| uint8_t WS2812FX::maxval (uint8_t v, uint8_t w)
 | |
| {
 | |
|   if (w > v) return w;
 | |
|   return v;
 | |
| }
 |