From: Nathael Pajani Date: Mon, 27 Feb 2023 13:24:49 +0000 (+0100) Subject: Move ws2812fx library to extlib/ws2812fx directory X-Git-Url: http://git.techno-innov.fr/?a=commitdiff_plain;h=8f072e5ddf7bc24285f579edfb6f3f24b1da9ac6;p=soft%2Flpc122x%2Fcore Move ws2812fx library to extlib/ws2812fx directory Update header. --- diff --git a/extdrv/ws2812fx.c b/extdrv/ws2812fx.c deleted file mode 100644 index f66c023..0000000 --- a/extdrv/ws2812fx.c +++ /dev/null @@ -1,1392 +0,0 @@ -/* - 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) - 2017-02-02 added external trigger functionality (e.g. for sound-to-light) - 2017-02-02 removed "blackout" on mode, speed or color-change -*/ - -#include "core/systick.h" -#include "lib/utils.h" -#include "extdrv/ws2812.h" -#include "extdrv/ws2812fx.h" - -static uint32_t random(uint32_t max) -{ - static uint32_t seed = 0; - /* Numerical Recipes */ - seed = seed * 1664525 + 1013904223; - return seed % max; -} - -static unsigned long millis(void) -{ - return systick_get_tick_count(); -} - - -/* ##################################################### -# -# Color and Blinken Functions -# -##################################################### */ - -/* - * Turns everything off. Doh. - */ -static void strip_off(struct ws2812fx* fx) -{ - ws2812_clear(fx->wsconf); - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - -#define WHITE 0xffffff -#define RED 0xff0000 -#define GREEN 0x00ff00 -#define BLUE 0x0000ff -#define BLACK 0x000000 - -static void set_pixel_rgb_color(struct ws2812fx* fx, uint32_t i, uint8_t r, uint8_t g, uint8_t b) -{ - ws2812_set_pixel(fx->wsconf, i, r, g, b); -} - -static void set_pixel_color(struct ws2812fx* fx, uint32_t i, uint32_t color) -{ - ws2812_set_pixel(fx->wsconf, i, color >> 16, (color >> 8) & 0xff, color & 0xff); -} - -static uint32_t get_pixel_color(struct ws2812fx* fx, uint32_t i) -{ - uint8_t r, g, b; - ws2812_get_pixel(fx->wsconf, i, &r, &g, &b); - return (r << 16) | (g << 8) | b; -} - -/* - * 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. - */ -static uint32_t 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. - */ -static uint8_t 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 = min(x, y); - } - - return r; -} - - -/* - * No blinking. Just plain old static light. - */ -static void mode_static(struct ws2812fx* fx) -{ - for (uint16_t i = 0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_mode_delay = 50; -} - - -/* - * Normal blinking. 50% on/off time. - */ -static void mode_blink(struct ws2812fx* fx) -{ - if (fx->_counter_mode_call % 2 == 1) { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - } else { - strip_off(fx); - } - - fx->_mode_delay = 100 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Lights all LEDs after each other up. Then turns them in - * that order off. Repeat. - */ -static void mode_color_wipe(struct ws2812fx* fx) -{ - if (fx->_counter_mode_step < fx->_led_count) { - set_pixel_color(fx, fx->_counter_mode_step, fx->_color); - } else { - set_pixel_color(fx, fx->_counter_mode_step - fx->_led_count, 0); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % (fx->_led_count * 2); - - fx->_mode_delay = 5 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Turns all LEDs after each other to a random color. - * Then starts over with another color. - */ -static void mode_color_wipe_random(struct ws2812fx* fx) -{ - if (fx->_counter_mode_step == 0) { - fx->_mode_color = get_random_wheel_index(fx->_mode_color); - } - - set_pixel_color(fx, fx->_counter_mode_step, color_wheel(fx->_mode_color)); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - - fx->_mode_delay = 5 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Lights all LEDs in one random color up. Then switches them - * to the next random color. - */ -static void mode_random_color(struct ws2812fx* fx) -{ - fx->_mode_color = get_random_wheel_index(fx->_mode_color); - - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(fx->_mode_color)); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_mode_delay = 100 + ((5000 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Lights every LED in a random color. Changes one random LED after the other - * to another random color. - */ -static void mode_single_dynamic(struct ws2812fx* fx) -{ - if (fx->_counter_mode_call == 0) { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(random(256))); - } - } - - set_pixel_color(fx, random(fx->_led_count), color_wheel(random(256))); - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_mode_delay = 10 + ((5000 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Lights every LED in a random color. Changes all LED at the same time - * to new random colors. - */ -static void mode_multi_dynamic(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(random(256))); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_mode_delay = 100 + ((5000 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_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. - */ -static void mode_breath(struct ws2812fx* fx) -{ - // 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 (fx->_counter_mode_call == 0) { - fx->_mode_color = breath_brightness_steps[0] + 1; - } - - uint32_t breath_brightness = fx->_mode_color; // we use fx->_mode_color to store the brightness - - if (fx->_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[fx->_counter_mode_step]) { - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % (sizeof(breath_brightness_steps)/sizeof(uint8_t)); - } - - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); // set all LEDs to selected color - } - int b = (breath_brightness * (fx->_brightness + 1)) >> 8; // keep brightness below brightness set by user - ws2812_set_brightness(fx->wsconf, b); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_mode_color = breath_brightness; // we use fx->_mode_color to store the brightness - fx->_mode_delay = breath_delay_steps[fx->_counter_mode_step]; -} - - -/* - * Fades the LEDs on and (almost) off again. - */ -static void mode_fade(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - - int b = fx->_counter_mode_step - 127; - b = 255 - (abs(b) * 2); - b = (b * (min(20, fx->_brightness) + 1)) >> 8; - ws2812_set_brightness(fx->wsconf, b); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 255; - fx->_mode_delay = 5 + ((15 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Runs a single pixel back and forth. - */ -static void mode_scan(struct ws2812fx* fx) -{ - if (fx->_counter_mode_step > (fx->_led_count*2) - 2) { - fx->_counter_mode_step = 0; - } - fx->_counter_mode_step++; - - int i = fx->_counter_mode_step - (fx->_led_count - 1); - i = abs(i); - - ws2812_clear(fx->wsconf); - set_pixel_color(fx, abs(i), fx->_color); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Runs two pixel back and forth in opposite directions. - */ -static void mode_dual_scan(struct ws2812fx* fx) -{ - if (fx->_counter_mode_step > (fx->_led_count*2) - 2) { - fx->_counter_mode_step = 0; - } - fx->_counter_mode_step++; - - int i = fx->_counter_mode_step - (fx->_led_count - 1); - i = abs(i); - - ws2812_clear(fx->wsconf); - set_pixel_color(fx, i, fx->_color); - set_pixel_color(fx, fx->_led_count - (i+1), fx->_color); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Cycles all LEDs at once through a rainbow. - */ -static void mode_rainbow(struct ws2812fx* fx) -{ - uint32_t color = color_wheel(fx->_counter_mode_step); - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 256; - - fx->_mode_delay = 1 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Cycles a rainbow over the entire string of LEDs. - */ -static void mode_rainbow_cycle(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(((i * 256 / fx->_led_count) + fx->_counter_mode_step) % 256)); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 256; - - fx->_mode_delay = 1 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Theatre-style crawling lights. - * Inspired by the Adafruit examples. - */ -static void mode_theater_chase(struct ws2812fx* fx) -{ - uint8_t j = fx->_counter_mode_call % 6; - if (j % 2 == 0) { - for (uint16_t i=0; i < fx->_led_count; i=i+3) { - set_pixel_color(fx, i+(j/2), fx->_color); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_mode_delay = 50 + ((500 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); - } else { - for (uint16_t i=0; i < fx->_led_count; i=i+3) { - set_pixel_color(fx, i+(j/2), 0); - } - fx->_mode_delay = 1; - } -} - - -/* - * Theatre-style crawling lights with rainbow effect. - * Inspired by the Adafruit examples. - */ -static void mode_theater_chase_rainbow(struct ws2812fx* fx) -{ - uint8_t j = fx->_counter_mode_call % 6; - if (j % 2 == 0) { - for (uint16_t i=0; i < fx->_led_count; i=i+3) { - set_pixel_color(fx, i+(j/2), color_wheel((i+fx->_counter_mode_step) % 256)); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_mode_delay = 50 + ((500 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); - } else { - for (uint16_t i=0; i < fx->_led_count; i=i+3) { - set_pixel_color(fx, i+(j/2), 0); - } - fx->_mode_delay = 1; - } - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 256; -} - - -#if 0 -/* - * Running lights effect with smooth sine transition. - */ -static void mode_running_lights(struct ws2812fx* fx) -{ - uint8_t r = ((fx->_color >> 16) & 0xFF); - uint8_t g = ((fx->_color >> 8) & 0xFF); - uint8_t b = (fx->_color & 0xFF); - - for (uint16_t i=0; i < fx->_led_count; i++) { - int s = (sin(i+fx->_counter_mode_call) * 127) + 128; - set_pixel_rgb_color(fx, i, (((uint32_t)(r * s)) / 255), (((uint32_t)(g * s)) / 255), (((uint32_t)(b * s)) / 255)); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_mode_delay = 35 + ((350 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} -#endif - - -/* - * Blink several LEDs on, reset, repeat. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -static void mode_twinkle(struct ws2812fx* fx) -{ - if (fx->_counter_mode_step == 0) { - strip_off(fx); - uint16_t min_leds = max(1, fx->_led_count/5); // make sure, at least one LED is on - uint16_t max_leds = max(1, fx->_led_count/2); // make sure, at least one LED is on - fx->_counter_mode_step = min_leds + random(max_leds - min_leds); - } - - set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step--; - fx->_mode_delay = 50 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Blink several LEDs in random colors on, reset, repeat. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -static void mode_twinkle_random(struct ws2812fx* fx) -{ - fx->_mode_color = color_wheel(random(256)); - mode_twinkle(fx); -} - - -/* - * Blink several LEDs on, fading out. - */ -static void mode_twinkle_fade(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - uint32_t px_rgb = get_pixel_color(fx, i); - - uint8_t px_r = (px_rgb & 0x00FF0000) >> 16; - uint8_t px_g = (px_rgb & 0x0000FF00) >> 8; - uint8_t 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; - - set_pixel_rgb_color(fx, i, px_r, px_g, px_b); - } - - if (random(3) == 0) { - set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_mode_delay = 100 + ((100 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Blink several LEDs in random colors on, fading out. - */ -static void mode_twinkle_fade_random(struct ws2812fx* fx) -{ - fx->_mode_color = color_wheel(random(256)); - mode_twinkle_fade(fx); -} - - -/* - * Blinks one LED at a time. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -static void mode_sparkle(struct ws2812fx* fx) -{ - ws2812_clear(fx->wsconf); - set_pixel_color(fx, random(fx->_led_count),fx->_color); - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_mode_delay = 10 + ((200 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * Lights all LEDs in the fx->_color. Flashes single white pixels randomly. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -static void mode_flash_sparkle(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - - if (random(10) == 7) { - set_pixel_color(fx, random(fx->_led_count), WHITE); - fx->_mode_delay = 20; - } else { - fx->_mode_delay = 20 + ((200 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - - -/* - * Like flash sparkle. With more flash. - * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ - */ -static void mode_hyper_sparkle(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - - if (random(10) < 4) { - for (uint16_t i=0; i < max(1, fx->_led_count/3); i++) { - set_pixel_color(fx, random(fx->_led_count), WHITE); - } - fx->_mode_delay = 20; - } else { - fx->_mode_delay = 15 + ((120 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - - -/* - * Classic Strobe effect. - */ -static void mode_strobe(struct ws2812fx* fx) -{ - if (fx->_counter_mode_call % 2 == 0) { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - fx->_mode_delay = 20; - } else { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, 0); - } - fx->_mode_delay = 50 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - - -/* - * Strobe effect with different strobe count and pause, controled by fx->_speed. - */ -static void mode_multi_strobe(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, 0); - } - - if (fx->_counter_mode_step < (2 * ((fx->_speed / 10) + 1))) { - if (fx->_counter_mode_step % 2 == 0) { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - fx->_mode_delay = 20; - } else { - fx->_mode_delay = 50; - } - - } else { - fx->_mode_delay = 100 + ((9 - (fx->_speed % 10)) * 125); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % ((2 * ((fx->_speed / 10) + 1)) + 1); -} - - -/* - * Classic Strobe effect. Cycling through the rainbow. - */ -static void mode_strobe_rainbow(struct ws2812fx* fx) -{ - if (fx->_counter_mode_call % 2 == 0) { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(fx->_counter_mode_call % 256)); - } - fx->_mode_delay = 20; - } else { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, 0); - } - fx->_mode_delay = 50 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - - -/* - * Classic Blink effect. Cycling through the rainbow. - */ -static void mode_blink_rainbow(struct ws2812fx* fx) -{ - if (fx->_counter_mode_call % 2 == 1) { - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(fx->_counter_mode_call % 256)); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - } else { - strip_off(fx); - } - - fx->_mode_delay = 100 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - - -/* - * fx->_color running on white. - */ -static void mode_chase_white(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, WHITE); - } - - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, fx->_color); - set_pixel_color(fx, m, fx->_color); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * White running on fx->_color. - */ -static void mode_chase_color(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, WHITE); - set_pixel_color(fx, m, WHITE); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * White running followed by random color. - */ -static void mode_chase_random(struct ws2812fx* fx) -{ - if (fx->_counter_mode_step == 0) { - set_pixel_color(fx, fx->_led_count-1, color_wheel(fx->_mode_color)); - fx->_mode_color = get_random_wheel_index(fx->_mode_color); - } - - for (uint16_t i=0; i < fx->_counter_mode_step; i++) { - set_pixel_color(fx, i, color_wheel(fx->_mode_color)); - } - - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, WHITE); - set_pixel_color(fx, m, WHITE); - - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * White running on rainbow. - */ -static void mode_chase_rainbow(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(((i * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); - } - - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, WHITE); - set_pixel_color(fx, m, WHITE); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * White flashes running on fx->_color. - */ -static void mode_chase_flash(struct ws2812fx* fx) -{ - const static uint8_t flash_count = 4; - uint8_t flash_step = fx->_counter_mode_call % ((flash_count * 2) + 1); - - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - - if (flash_step < (flash_count * 2)) { - if (flash_step % 2 == 0) { - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, WHITE); - set_pixel_color(fx, m, WHITE); - fx->_mode_delay = 20; - } else { - fx->_mode_delay = 30; - } - } else { - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - - -/* - * White flashes running, followed by random color. - */ -static void mode_chase_flash_random(struct ws2812fx* fx) -{ - const static uint8_t flash_count = 4; - uint8_t flash_step = fx->_counter_mode_call % ((flash_count * 2) + 1); - - for (uint16_t i=0; i < fx->_counter_mode_step; i++) { - set_pixel_color(fx, i, color_wheel(fx->_mode_color)); - } - - if (flash_step < (flash_count * 2)) { - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - if (flash_step % 2 == 0) { - set_pixel_color(fx, n, WHITE); - set_pixel_color(fx, m, WHITE); - fx->_mode_delay = 20; - } else { - set_pixel_color(fx, n, color_wheel(fx->_mode_color)); - set_pixel_color(fx, m, BLACK); - fx->_mode_delay = 30; - } - } else { - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 1 + ((10 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); - - if (fx->_counter_mode_step == 0) { - fx->_mode_color = get_random_wheel_index(fx->_mode_color); - } - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - - -/* - * Rainbow running on white. - */ -static void mode_chase_rainbow_white(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, WHITE); - } - - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, color_wheel(((n * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); - set_pixel_color(fx, m, color_wheel(((m * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Black running on fx->_color. - */ -static void mode_chase_blackout(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, fx->_color); - } - - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, BLACK); - set_pixel_color(fx, m, BLACK); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Black running on rainbow. - */ -static void mode_chase_blackout_rainbow(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - set_pixel_color(fx, i, color_wheel(((i * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); - } - - uint16_t n = fx->_counter_mode_step; - uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; - set_pixel_color(fx, n, BLACK); - set_pixel_color(fx, m, BLACK); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Random color intruduced alternating from start and end of strip. - */ -static void mode_color_sweep_random(struct ws2812fx* fx) -{ - if (fx->_counter_mode_step == 0 || fx->_counter_mode_step == fx->_led_count) { - fx->_mode_color = get_random_wheel_index(fx->_mode_color); - } - - if (fx->_counter_mode_step < fx->_led_count) { - set_pixel_color(fx, fx->_counter_mode_step, color_wheel(fx->_mode_color)); - } else { - set_pixel_color(fx, (fx->_led_count * 2) - fx->_counter_mode_step - 1, color_wheel(fx->_mode_color)); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % (fx->_led_count * 2); - fx->_mode_delay = 5 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Alternating color/white pixels running. - */ -static void mode_running_color(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - if ((i + fx->_counter_mode_step) % 4 < 2) { - set_pixel_color(fx, i, fx->_mode_color); - } else { - set_pixel_color(fx, i, WHITE); - } - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 4; - fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Alternating red/blue pixels running. - */ -static void mode_running_red_blue(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - if ((i + fx->_counter_mode_step) % 4 < 2) { - set_pixel_color(fx, i, RED); - } else { - set_pixel_color(fx, i, BLUE); - } - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 4; - fx->_mode_delay = 100 + ((100 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Random colored pixels running. - */ -static void mode_running_random(struct ws2812fx* fx) -{ - for (uint16_t i=fx->_led_count-1; i > 0; i--) { - set_pixel_color(fx, i, get_pixel_color(fx, i-1)); - } - - if (fx->_counter_mode_step == 0) { - fx->_mode_color = get_random_wheel_index(fx->_mode_color); - set_pixel_color(fx, 0, color_wheel(fx->_mode_color)); - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 2; - - fx->_mode_delay = 50 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * K.I.T.T. - */ -static void mode_larson_scanner(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - uint32_t px_rgb = get_pixel_color(fx, i); - - uint8_t px_r = (px_rgb & 0x00FF0000) >> 16; - uint8_t px_g = (px_rgb & 0x0000FF00) >> 8; - uint8_t 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; - - set_pixel_rgb_color(fx, i, px_r, px_g, px_b); - } - - uint16_t pos = 0; - - if (fx->_counter_mode_step < fx->_led_count) { - pos = fx->_counter_mode_step; - } else { - pos = (fx->_led_count * 2) - fx->_counter_mode_step - 2; - } - - set_pixel_color(fx, pos, fx->_color); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % ((fx->_led_count * 2) - 2); - fx->_mode_delay = 10 + ((10 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Fireing comets from one end. - */ -static void mode_comet(struct ws2812fx* fx) -{ - - for (uint16_t i=0; i < fx->_led_count; i++) { - uint32_t px_rgb = get_pixel_color(fx, i); - - uint8_t px_r = (px_rgb & 0x00FF0000) >> 16; - uint8_t px_g = (px_rgb & 0x0000FF00) >> 8; - uint8_t 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; - - set_pixel_rgb_color(fx, i, px_r, px_g, px_b); - } - - set_pixel_color(fx, fx->_counter_mode_step, fx->_color); - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; - fx->_mode_delay = 10 + ((10 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Firework sparks. - */ -static void mode_fireworks(struct ws2812fx* fx) -{ - uint32_t px_rgb = 0; - uint8_t px_r = 0; - uint8_t px_g = 0; - uint8_t px_b = 0; - - for (uint16_t i=0; i < fx->_led_count; i++) { - px_rgb = get_pixel_color(fx, 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; - - set_pixel_rgb_color(fx, i, px_r, px_g, px_b); - } - - // first LED has only one neighbour - px_r = (((get_pixel_color(fx, 1) & 0x00FF0000) >> 16) >> 1) + ((get_pixel_color(fx, 0) & 0x00FF0000) >> 16); - px_g = (((get_pixel_color(fx, 1) & 0x0000FF00) >> 8) >> 1) + ((get_pixel_color(fx, 0) & 0x0000FF00) >> 8); - px_b = (((get_pixel_color(fx, 1) & 0x000000FF) >> 0) >> 1) + ((get_pixel_color(fx, 0) & 0x000000FF) >> 0); - set_pixel_rgb_color(fx, 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 < fx->_led_count-1; i++) { - px_r = (( - (((get_pixel_color(fx, i-1) & 0x00FF0000) >> 16) >> 1) + - (((get_pixel_color(fx, i+1) & 0x00FF0000) >> 16) >> 0) ) >> 1) + - (((get_pixel_color(fx, i ) & 0x00FF0000) >> 16) >> 0); - - px_g = (( - (((get_pixel_color(fx, i-1) & 0x0000FF00) >> 8) >> 1) + - (((get_pixel_color(fx, i+1) & 0x0000FF00) >> 8) >> 0) ) >> 1) + - (((get_pixel_color(fx, i ) & 0x0000FF00) >> 8) >> 0); - - px_b = (( - (((get_pixel_color(fx, i-1) & 0x000000FF) >> 0) >> 1) + - (((get_pixel_color(fx, i+1) & 0x000000FF) >> 0) >> 0) ) >> 1) + - (((get_pixel_color(fx, i ) & 0x000000FF) >> 0) >> 0); - - set_pixel_rgb_color(fx, i, px_r, px_g, px_b); - } - - // last LED has only one neighbour - px_r = (((get_pixel_color(fx, fx->_led_count-2) & 0x00FF0000) >> 16) >> 2) + ((get_pixel_color(fx, fx->_led_count-1) & 0x00FF0000) >> 16); - px_g = (((get_pixel_color(fx, fx->_led_count-2) & 0x0000FF00) >> 8) >> 2) + ((get_pixel_color(fx, fx->_led_count-1) & 0x0000FF00) >> 8); - px_b = (((get_pixel_color(fx, fx->_led_count-2) & 0x000000FF) >> 0) >> 2) + ((get_pixel_color(fx, fx->_led_count-1) & 0x000000FF) >> 0); - set_pixel_rgb_color(fx, fx->_led_count-1, px_r, px_g, px_b); - - if (!fx->_triggered) { - for (uint16_t i=0; i_led_count/20); i++) { - if (random(10) == 0) { - set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); - } - } - } else { - for (uint16_t i=0; i_led_count/10); i++) { - set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); - } - } - - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_mode_delay = 20 + ((20 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -/* - * Random colored firework sparks. - */ -static void mode_fireworks_random(struct ws2812fx* fx) -{ - fx->_mode_color = color_wheel(random(256)); - mode_fireworks(fx); -} - - -/* - * Alternating red/green pixels running. - */ -static void mode_merry_christmas(struct ws2812fx* fx) -{ - for (uint16_t i=0; i < fx->_led_count; i++) { - if ((i + fx->_counter_mode_step) % 4 < 2) { - set_pixel_color(fx, i, RED); - } else { - set_pixel_color(fx, i, GREEN); - } - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - - fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 4; - fx->_mode_delay = 100 + ((100 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); -} - - -static void mode_fire_flicker_int(struct ws2812fx* fx, int rev_intensity) -{ - uint8_t p_r = (fx->_color & 0x00FF0000) >> 16; - uint8_t p_g = (fx->_color & 0x0000FF00) >> 8; - uint8_t p_b = (fx->_color & 0x000000FF) >> 0; - uint8_t flicker_val = max(p_r,max(p_g, p_b))/rev_intensity; - for (uint16_t i=0; i < fx->_led_count; i++) - { - int flicker = random(flicker_val); - int r1 = p_r-flicker; - int g1 = p_g-flicker; - int b1 = p_b-flicker; - if (g1<0) g1=0; - if (r1<0) r1=0; - if (b1<0) b1=0; - set_pixel_rgb_color(fx, i, r1, g1, b1); - } - ws2812_send_frame(fx->wsconf, fx->_led_count); - fx->_mode_delay = 10 + ((500 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); -} - -/* - * Random flickering. - */ -static void mode_fire_flicker(struct ws2812fx* fx) -{ - mode_fire_flicker_int(fx, 3); -} - -/* - * Random flickering, less intesity. - */ -static void mode_fire_flicker_soft(struct ws2812fx* fx) -{ - mode_fire_flicker_int(fx, 6); -} - - -typedef void (*mode_ptr)(struct ws2812fx* fx); - -static struct { - mode_ptr _fn; - char *_name; -} const modes[] = { - { mode_static, "Static" }, - { mode_blink, "Blink" }, - { mode_breath, "Breath" }, - { mode_color_wipe, "Color Wipe" }, - { mode_color_wipe_random, "Color Wipe Random" }, - { mode_random_color, "Random Color" }, - { mode_single_dynamic, "Single Dynamic" }, - { mode_multi_dynamic, "Multi Dynamic" }, - { mode_rainbow, "Rainbow" }, - { mode_rainbow_cycle, "Rainbow Cycle" }, - { mode_theater_chase, "Theater Chase" }, - { mode_theater_chase_rainbow, "Theater Chase Rainbow" }, - { mode_scan, "Scan" }, - { mode_dual_scan, "Dual Scan" }, - { mode_fade, "Fade" }, -#if 0 - { mode_running_lights, "Running Lights" }, -#endif - { mode_twinkle, "Twinkle" }, - { mode_twinkle_random, "Twinkle Random" }, - { mode_twinkle_fade, "Twinkle Fade" }, - { mode_twinkle_fade_random, "Twinkle Fade Random" }, - { mode_sparkle, "Sparkle" }, - { mode_flash_sparkle, "Flash Sparkle" }, - { mode_hyper_sparkle, "Hyper Sparkle" }, - { mode_strobe, "Strobe" }, - { mode_strobe_rainbow, "Strobe Rainbow" }, - { mode_multi_strobe, "Multi Strobe" }, - { mode_blink_rainbow, "Blink Rainbow" }, - { mode_chase_white, "Chase White" }, - { mode_chase_color, "Chase Color" }, - { mode_chase_random, "Chase Random" }, - { mode_chase_rainbow, "Chase Rainbow" }, - { mode_chase_flash, "Chase Flash" }, - { mode_chase_flash_random, "Chase Flash Random" }, - { mode_chase_rainbow_white, "Chase Rainbow White" }, - { mode_chase_blackout, "Chase Blackout" }, - { mode_chase_blackout_rainbow, "Chase Blackout Rainbow" }, - { mode_color_sweep_random, "Color Sweep Random" }, - { mode_running_color, "Running Color" }, - { mode_running_red_blue, "Running Red Blue" }, - { mode_running_random, "Running Random" }, - { mode_larson_scanner, "Larson Scanner" }, - { mode_comet, "Comet" }, - { mode_fireworks, "Fireworks" }, - { mode_fireworks_random, "Fireworks Random" }, - { mode_merry_christmas, "Merry Christmas" }, - { mode_fire_flicker, "Fire Flicker" }, - { mode_fire_flicker_soft, "Fire Flicker (soft)" }, -}; - -#define CALL_MODE(fx, n) (modes[n]._fn)(fx); - -void WS2812FX(struct ws2812fx* fx, uint16_t n, const struct pio *pin) -{ - fx->wsconf->nb_leds = n; - ws2812_config(fx->wsconf, pin); - - fx->_speed = FX_DEFAULT_SPEED; - fx->_brightness = FX_DEFAULT_BRIGHTNESS; - fx->_running = 0; - fx->_led_count = n; - fx->_mode_last_call_time = 0; - fx->_mode_delay = 0; - fx->_color = FX_DEFAULT_COLOR; - fx->_mode_color = FX_DEFAULT_COLOR; - fx->_counter_mode_call = 0; - fx->_counter_mode_step = 0; -} - -void FX_init(struct ws2812fx* fx) -{ - FX_setBrightness(fx, fx->_brightness); - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - -void FX_service(struct ws2812fx* fx) -{ - if (fx->_running || fx->_triggered) { - unsigned long now = millis(); - - if (now - fx->_mode_last_call_time > fx->_mode_delay || fx->_triggered) { - CALL_MODE(fx, fx->_mode_index); - fx->_counter_mode_call++; - fx->_mode_last_call_time = now; - fx->_triggered = 0; - } - } -} - -void FX_start(struct ws2812fx* fx) -{ - fx->_counter_mode_call = 0; - fx->_counter_mode_step = 0; - fx->_mode_last_call_time = 0; - fx->_running = 1; -} - -void FX_stop(struct ws2812fx* fx) -{ - fx->_running = 0; - strip_off(fx); -} - -void FX_trigger(struct ws2812fx* fx) -{ - fx->_triggered = 1; -} - -void FX_setMode(struct ws2812fx* fx, uint8_t m) -{ - fx->_counter_mode_call = 0; - fx->_counter_mode_step = 0; - fx->_mode_last_call_time = 0; - fx->_mode_index = constrain(m, 0, FX_MODE_COUNT-1); - fx->_mode_color = fx->_color; - ws2812_set_brightness(fx->wsconf, fx->_brightness); - //strip_off(fx); -} - -void FX_setSpeed(struct ws2812fx* fx, uint8_t s) -{ - fx->_counter_mode_call = 0; - fx->_counter_mode_step = 0; - fx->_mode_last_call_time = 0; - fx->_speed = constrain(s, FX_SPEED_MIN, FX_SPEED_MAX); - //strip_off(fx); -} - -void FX_increaseSpeed(struct ws2812fx* fx, uint8_t s) -{ - s = constrain(fx->_speed + s, FX_SPEED_MIN, FX_SPEED_MAX); - FX_setSpeed(fx, s); -} - -void FX_decreaseSpeed(struct ws2812fx* fx, uint8_t s) -{ - s = constrain(fx->_speed - s, FX_SPEED_MIN, FX_SPEED_MAX); - FX_setSpeed(fx, s); -} - -void FX_setRGBColor(struct ws2812fx* fx, uint8_t r, uint8_t g, uint8_t b) -{ - FX_setColor(fx, ((uint32_t)r << 16) | ((uint32_t)g << 8) | b); -} - -void FX_setColor(struct ws2812fx* fx, uint32_t c) -{ - fx->_color = c; - fx->_counter_mode_call = 0; - fx->_counter_mode_step = 0; - fx->_mode_last_call_time = 0; - fx->_mode_color = fx->_color; - ws2812_set_brightness(fx->wsconf, fx->_brightness); - //strip_off(fx); -} - -void FX_setBrightness(struct ws2812fx* fx, uint8_t b) -{ - fx->_brightness = constrain(b, FX_BRIGHTNESS_MIN, FX_BRIGHTNESS_MAX); - ws2812_set_brightness(fx->wsconf, fx->_brightness); - ws2812_send_frame(fx->wsconf, fx->_led_count); -} - -void FX_increaseBrightness(struct ws2812fx* fx, uint8_t s) -{ - s = constrain(fx->_brightness + s, FX_BRIGHTNESS_MIN, FX_BRIGHTNESS_MAX); - FX_setBrightness(fx, s); -} - -void FX_decreaseBrightness(struct ws2812fx* fx, uint8_t s) -{ - s = constrain(fx->_brightness - s, FX_BRIGHTNESS_MIN, FX_BRIGHTNESS_MAX); - FX_setBrightness(fx, s); -} - -int FX_isRunning(struct ws2812fx* fx) -{ - return fx->_running; -} - -uint8_t FX_getMode(struct ws2812fx* fx) -{ - return fx->_mode_index; -} - -uint8_t FX_getSpeed(struct ws2812fx* fx) -{ - return fx->_speed; -} - -uint8_t FX_getBrightness(struct ws2812fx* fx) -{ - return fx->_brightness; -} - -uint8_t FX_getModeCount(struct ws2812fx* fx) -{ - return FX_MODE_COUNT; -} - -uint32_t FX_getColor(struct ws2812fx* fx) -{ - return fx->_color; -} - -const char* FX_getModeName(uint8_t m) -{ - if (m < FX_MODE_COUNT) { - return modes[m]._name; - } else { - return ""; - } -} diff --git a/extlib/ws2812fx/ws2812fx.c b/extlib/ws2812fx/ws2812fx.c new file mode 100644 index 0000000..bc1f3a5 --- /dev/null +++ b/extlib/ws2812fx/ws2812fx.c @@ -0,0 +1,1395 @@ +/**************************************************************************** + * + * extlib/ws2812fx/ws2812fx.c - Library for WS2812 LED effects. + * + * Fork from Harm Aldick's work - 2016 - www.aldick.org + * https://github.com/kitesurfer1404/WS2812FX.git + * + * FEATURES + * - A lot of blinken modes and counting + * - WS2812FX can be used as drop-in replacement for Adafruit Neopixel Library + * + * 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) + * 2017-02-02 added external trigger functionality (e.g. for sound-to-light) + * 2017-02-02 removed "blackout" on mode, speed or color-change + * + *************************************************************************** */ + +#include "core/systick.h" +#include "lib/utils.h" +#include "extdrv/ws2812.h" +#include "extlib/ws2812fx/ws2812fx.h" + +static uint32_t random(uint32_t max) +{ + static uint32_t seed = 0; + /* Numerical Recipes */ + seed = seed * 1664525 + 1013904223; + return seed % max; +} + +static unsigned long millis(void) +{ + return systick_get_tick_count(); +} + + +/* ##################################################### +# +# Color and Blinken Functions +# +##################################################### */ + +/* + * Turns everything off. Doh. + */ +static void strip_off(struct ws2812fx* fx) +{ + ws2812_clear(fx->wsconf); + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + +#define WHITE 0xffffff +#define RED 0xff0000 +#define GREEN 0x00ff00 +#define BLUE 0x0000ff +#define BLACK 0x000000 + +static void set_pixel_rgb_color(struct ws2812fx* fx, uint32_t i, uint8_t r, uint8_t g, uint8_t b) +{ + ws2812_set_pixel(fx->wsconf, i, r, g, b); +} + +static void set_pixel_color(struct ws2812fx* fx, uint32_t i, uint32_t color) +{ + ws2812_set_pixel(fx->wsconf, i, color >> 16, (color >> 8) & 0xff, color & 0xff); +} + +static uint32_t get_pixel_color(struct ws2812fx* fx, uint32_t i) +{ + uint8_t r, g, b; + ws2812_get_pixel(fx->wsconf, i, &r, &g, &b); + return (r << 16) | (g << 8) | b; +} + +/* + * 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. + */ +static uint32_t 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. + */ +static uint8_t 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 = min(x, y); + } + + return r; +} + + +/* + * No blinking. Just plain old static light. + */ +static void mode_static(struct ws2812fx* fx) +{ + for (uint16_t i = 0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_mode_delay = 50; +} + + +/* + * Normal blinking. 50% on/off time. + */ +static void mode_blink(struct ws2812fx* fx) +{ + if (fx->_counter_mode_call % 2 == 1) { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + } else { + strip_off(fx); + } + + fx->_mode_delay = 100 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Lights all LEDs after each other up. Then turns them in + * that order off. Repeat. + */ +static void mode_color_wipe(struct ws2812fx* fx) +{ + if (fx->_counter_mode_step < fx->_led_count) { + set_pixel_color(fx, fx->_counter_mode_step, fx->_color); + } else { + set_pixel_color(fx, fx->_counter_mode_step - fx->_led_count, 0); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % (fx->_led_count * 2); + + fx->_mode_delay = 5 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Turns all LEDs after each other to a random color. + * Then starts over with another color. + */ +static void mode_color_wipe_random(struct ws2812fx* fx) +{ + if (fx->_counter_mode_step == 0) { + fx->_mode_color = get_random_wheel_index(fx->_mode_color); + } + + set_pixel_color(fx, fx->_counter_mode_step, color_wheel(fx->_mode_color)); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + + fx->_mode_delay = 5 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Lights all LEDs in one random color up. Then switches them + * to the next random color. + */ +static void mode_random_color(struct ws2812fx* fx) +{ + fx->_mode_color = get_random_wheel_index(fx->_mode_color); + + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(fx->_mode_color)); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_mode_delay = 100 + ((5000 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Lights every LED in a random color. Changes one random LED after the other + * to another random color. + */ +static void mode_single_dynamic(struct ws2812fx* fx) +{ + if (fx->_counter_mode_call == 0) { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(random(256))); + } + } + + set_pixel_color(fx, random(fx->_led_count), color_wheel(random(256))); + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_mode_delay = 10 + ((5000 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Lights every LED in a random color. Changes all LED at the same time + * to new random colors. + */ +static void mode_multi_dynamic(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(random(256))); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_mode_delay = 100 + ((5000 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_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. + */ +static void mode_breath(struct ws2812fx* fx) +{ + // 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 (fx->_counter_mode_call == 0) { + fx->_mode_color = breath_brightness_steps[0] + 1; + } + + uint32_t breath_brightness = fx->_mode_color; // we use fx->_mode_color to store the brightness + + if (fx->_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[fx->_counter_mode_step]) { + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % (sizeof(breath_brightness_steps)/sizeof(uint8_t)); + } + + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); // set all LEDs to selected color + } + int b = (breath_brightness * (fx->_brightness + 1)) >> 8; // keep brightness below brightness set by user + ws2812_set_brightness(fx->wsconf, b); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_mode_color = breath_brightness; // we use fx->_mode_color to store the brightness + fx->_mode_delay = breath_delay_steps[fx->_counter_mode_step]; +} + + +/* + * Fades the LEDs on and (almost) off again. + */ +static void mode_fade(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + + int b = fx->_counter_mode_step - 127; + b = 255 - (abs(b) * 2); + b = (b * (min(20, fx->_brightness) + 1)) >> 8; + ws2812_set_brightness(fx->wsconf, b); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 255; + fx->_mode_delay = 5 + ((15 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Runs a single pixel back and forth. + */ +static void mode_scan(struct ws2812fx* fx) +{ + if (fx->_counter_mode_step > (fx->_led_count*2) - 2) { + fx->_counter_mode_step = 0; + } + fx->_counter_mode_step++; + + int i = fx->_counter_mode_step - (fx->_led_count - 1); + i = abs(i); + + ws2812_clear(fx->wsconf); + set_pixel_color(fx, abs(i), fx->_color); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Runs two pixel back and forth in opposite directions. + */ +static void mode_dual_scan(struct ws2812fx* fx) +{ + if (fx->_counter_mode_step > (fx->_led_count*2) - 2) { + fx->_counter_mode_step = 0; + } + fx->_counter_mode_step++; + + int i = fx->_counter_mode_step - (fx->_led_count - 1); + i = abs(i); + + ws2812_clear(fx->wsconf); + set_pixel_color(fx, i, fx->_color); + set_pixel_color(fx, fx->_led_count - (i+1), fx->_color); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Cycles all LEDs at once through a rainbow. + */ +static void mode_rainbow(struct ws2812fx* fx) +{ + uint32_t color = color_wheel(fx->_counter_mode_step); + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 256; + + fx->_mode_delay = 1 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Cycles a rainbow over the entire string of LEDs. + */ +static void mode_rainbow_cycle(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(((i * 256 / fx->_led_count) + fx->_counter_mode_step) % 256)); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 256; + + fx->_mode_delay = 1 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Theatre-style crawling lights. + * Inspired by the Adafruit examples. + */ +static void mode_theater_chase(struct ws2812fx* fx) +{ + uint8_t j = fx->_counter_mode_call % 6; + if (j % 2 == 0) { + for (uint16_t i=0; i < fx->_led_count; i=i+3) { + set_pixel_color(fx, i+(j/2), fx->_color); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_mode_delay = 50 + ((500 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); + } else { + for (uint16_t i=0; i < fx->_led_count; i=i+3) { + set_pixel_color(fx, i+(j/2), 0); + } + fx->_mode_delay = 1; + } +} + + +/* + * Theatre-style crawling lights with rainbow effect. + * Inspired by the Adafruit examples. + */ +static void mode_theater_chase_rainbow(struct ws2812fx* fx) +{ + uint8_t j = fx->_counter_mode_call % 6; + if (j % 2 == 0) { + for (uint16_t i=0; i < fx->_led_count; i=i+3) { + set_pixel_color(fx, i+(j/2), color_wheel((i+fx->_counter_mode_step) % 256)); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_mode_delay = 50 + ((500 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); + } else { + for (uint16_t i=0; i < fx->_led_count; i=i+3) { + set_pixel_color(fx, i+(j/2), 0); + } + fx->_mode_delay = 1; + } + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 256; +} + + +#if 0 +/* + * Running lights effect with smooth sine transition. + */ +static void mode_running_lights(struct ws2812fx* fx) +{ + uint8_t r = ((fx->_color >> 16) & 0xFF); + uint8_t g = ((fx->_color >> 8) & 0xFF); + uint8_t b = (fx->_color & 0xFF); + + for (uint16_t i=0; i < fx->_led_count; i++) { + int s = (sin(i+fx->_counter_mode_call) * 127) + 128; + set_pixel_rgb_color(fx, i, (((uint32_t)(r * s)) / 255), (((uint32_t)(g * s)) / 255), (((uint32_t)(b * s)) / 255)); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_mode_delay = 35 + ((350 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} +#endif + + +/* + * Blink several LEDs on, reset, repeat. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +static void mode_twinkle(struct ws2812fx* fx) +{ + if (fx->_counter_mode_step == 0) { + strip_off(fx); + uint16_t min_leds = max(1, fx->_led_count/5); // make sure, at least one LED is on + uint16_t max_leds = max(1, fx->_led_count/2); // make sure, at least one LED is on + fx->_counter_mode_step = min_leds + random(max_leds - min_leds); + } + + set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step--; + fx->_mode_delay = 50 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Blink several LEDs in random colors on, reset, repeat. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +static void mode_twinkle_random(struct ws2812fx* fx) +{ + fx->_mode_color = color_wheel(random(256)); + mode_twinkle(fx); +} + + +/* + * Blink several LEDs on, fading out. + */ +static void mode_twinkle_fade(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + uint32_t px_rgb = get_pixel_color(fx, i); + + uint8_t px_r = (px_rgb & 0x00FF0000) >> 16; + uint8_t px_g = (px_rgb & 0x0000FF00) >> 8; + uint8_t 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; + + set_pixel_rgb_color(fx, i, px_r, px_g, px_b); + } + + if (random(3) == 0) { + set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_mode_delay = 100 + ((100 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Blink several LEDs in random colors on, fading out. + */ +static void mode_twinkle_fade_random(struct ws2812fx* fx) +{ + fx->_mode_color = color_wheel(random(256)); + mode_twinkle_fade(fx); +} + + +/* + * Blinks one LED at a time. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +static void mode_sparkle(struct ws2812fx* fx) +{ + ws2812_clear(fx->wsconf); + set_pixel_color(fx, random(fx->_led_count),fx->_color); + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_mode_delay = 10 + ((200 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * Lights all LEDs in the fx->_color. Flashes single white pixels randomly. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +static void mode_flash_sparkle(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + + if (random(10) == 7) { + set_pixel_color(fx, random(fx->_led_count), WHITE); + fx->_mode_delay = 20; + } else { + fx->_mode_delay = 20 + ((200 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + + +/* + * Like flash sparkle. With more flash. + * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ +static void mode_hyper_sparkle(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + + if (random(10) < 4) { + for (uint16_t i=0; i < max(1, fx->_led_count/3); i++) { + set_pixel_color(fx, random(fx->_led_count), WHITE); + } + fx->_mode_delay = 20; + } else { + fx->_mode_delay = 15 + ((120 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + + +/* + * Classic Strobe effect. + */ +static void mode_strobe(struct ws2812fx* fx) +{ + if (fx->_counter_mode_call % 2 == 0) { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + fx->_mode_delay = 20; + } else { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, 0); + } + fx->_mode_delay = 50 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + + +/* + * Strobe effect with different strobe count and pause, controled by fx->_speed. + */ +static void mode_multi_strobe(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, 0); + } + + if (fx->_counter_mode_step < (2 * ((fx->_speed / 10) + 1))) { + if (fx->_counter_mode_step % 2 == 0) { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + fx->_mode_delay = 20; + } else { + fx->_mode_delay = 50; + } + + } else { + fx->_mode_delay = 100 + ((9 - (fx->_speed % 10)) * 125); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % ((2 * ((fx->_speed / 10) + 1)) + 1); +} + + +/* + * Classic Strobe effect. Cycling through the rainbow. + */ +static void mode_strobe_rainbow(struct ws2812fx* fx) +{ + if (fx->_counter_mode_call % 2 == 0) { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(fx->_counter_mode_call % 256)); + } + fx->_mode_delay = 20; + } else { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, 0); + } + fx->_mode_delay = 50 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + + +/* + * Classic Blink effect. Cycling through the rainbow. + */ +static void mode_blink_rainbow(struct ws2812fx* fx) +{ + if (fx->_counter_mode_call % 2 == 1) { + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(fx->_counter_mode_call % 256)); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + } else { + strip_off(fx); + } + + fx->_mode_delay = 100 + ((1986 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + + +/* + * fx->_color running on white. + */ +static void mode_chase_white(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, WHITE); + } + + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, fx->_color); + set_pixel_color(fx, m, fx->_color); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * White running on fx->_color. + */ +static void mode_chase_color(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, WHITE); + set_pixel_color(fx, m, WHITE); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * White running followed by random color. + */ +static void mode_chase_random(struct ws2812fx* fx) +{ + if (fx->_counter_mode_step == 0) { + set_pixel_color(fx, fx->_led_count-1, color_wheel(fx->_mode_color)); + fx->_mode_color = get_random_wheel_index(fx->_mode_color); + } + + for (uint16_t i=0; i < fx->_counter_mode_step; i++) { + set_pixel_color(fx, i, color_wheel(fx->_mode_color)); + } + + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, WHITE); + set_pixel_color(fx, m, WHITE); + + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * White running on rainbow. + */ +static void mode_chase_rainbow(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(((i * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); + } + + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, WHITE); + set_pixel_color(fx, m, WHITE); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * White flashes running on fx->_color. + */ +static void mode_chase_flash(struct ws2812fx* fx) +{ + const static uint8_t flash_count = 4; + uint8_t flash_step = fx->_counter_mode_call % ((flash_count * 2) + 1); + + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + + if (flash_step < (flash_count * 2)) { + if (flash_step % 2 == 0) { + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, WHITE); + set_pixel_color(fx, m, WHITE); + fx->_mode_delay = 20; + } else { + fx->_mode_delay = 30; + } + } else { + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + + +/* + * White flashes running, followed by random color. + */ +static void mode_chase_flash_random(struct ws2812fx* fx) +{ + const static uint8_t flash_count = 4; + uint8_t flash_step = fx->_counter_mode_call % ((flash_count * 2) + 1); + + for (uint16_t i=0; i < fx->_counter_mode_step; i++) { + set_pixel_color(fx, i, color_wheel(fx->_mode_color)); + } + + if (flash_step < (flash_count * 2)) { + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + if (flash_step % 2 == 0) { + set_pixel_color(fx, n, WHITE); + set_pixel_color(fx, m, WHITE); + fx->_mode_delay = 20; + } else { + set_pixel_color(fx, n, color_wheel(fx->_mode_color)); + set_pixel_color(fx, m, BLACK); + fx->_mode_delay = 30; + } + } else { + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 1 + ((10 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); + + if (fx->_counter_mode_step == 0) { + fx->_mode_color = get_random_wheel_index(fx->_mode_color); + } + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + + +/* + * Rainbow running on white. + */ +static void mode_chase_rainbow_white(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, WHITE); + } + + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, color_wheel(((n * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); + set_pixel_color(fx, m, color_wheel(((m * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Black running on fx->_color. + */ +static void mode_chase_blackout(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, fx->_color); + } + + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, BLACK); + set_pixel_color(fx, m, BLACK); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Black running on rainbow. + */ +static void mode_chase_blackout_rainbow(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + set_pixel_color(fx, i, color_wheel(((i * 256 / fx->_led_count) + (fx->_counter_mode_call % 256)) % 256)); + } + + uint16_t n = fx->_counter_mode_step; + uint16_t m = (fx->_counter_mode_step + 1) % fx->_led_count; + set_pixel_color(fx, n, BLACK); + set_pixel_color(fx, m, BLACK); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Random color intruduced alternating from start and end of strip. + */ +static void mode_color_sweep_random(struct ws2812fx* fx) +{ + if (fx->_counter_mode_step == 0 || fx->_counter_mode_step == fx->_led_count) { + fx->_mode_color = get_random_wheel_index(fx->_mode_color); + } + + if (fx->_counter_mode_step < fx->_led_count) { + set_pixel_color(fx, fx->_counter_mode_step, color_wheel(fx->_mode_color)); + } else { + set_pixel_color(fx, (fx->_led_count * 2) - fx->_counter_mode_step - 1, color_wheel(fx->_mode_color)); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % (fx->_led_count * 2); + fx->_mode_delay = 5 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Alternating color/white pixels running. + */ +static void mode_running_color(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + if ((i + fx->_counter_mode_step) % 4 < 2) { + set_pixel_color(fx, i, fx->_mode_color); + } else { + set_pixel_color(fx, i, WHITE); + } + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 4; + fx->_mode_delay = 10 + ((30 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Alternating red/blue pixels running. + */ +static void mode_running_red_blue(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + if ((i + fx->_counter_mode_step) % 4 < 2) { + set_pixel_color(fx, i, RED); + } else { + set_pixel_color(fx, i, BLUE); + } + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 4; + fx->_mode_delay = 100 + ((100 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Random colored pixels running. + */ +static void mode_running_random(struct ws2812fx* fx) +{ + for (uint16_t i=fx->_led_count-1; i > 0; i--) { + set_pixel_color(fx, i, get_pixel_color(fx, i-1)); + } + + if (fx->_counter_mode_step == 0) { + fx->_mode_color = get_random_wheel_index(fx->_mode_color); + set_pixel_color(fx, 0, color_wheel(fx->_mode_color)); + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 2; + + fx->_mode_delay = 50 + ((50 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * K.I.T.T. + */ +static void mode_larson_scanner(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + uint32_t px_rgb = get_pixel_color(fx, i); + + uint8_t px_r = (px_rgb & 0x00FF0000) >> 16; + uint8_t px_g = (px_rgb & 0x0000FF00) >> 8; + uint8_t 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; + + set_pixel_rgb_color(fx, i, px_r, px_g, px_b); + } + + uint16_t pos = 0; + + if (fx->_counter_mode_step < fx->_led_count) { + pos = fx->_counter_mode_step; + } else { + pos = (fx->_led_count * 2) - fx->_counter_mode_step - 2; + } + + set_pixel_color(fx, pos, fx->_color); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % ((fx->_led_count * 2) - 2); + fx->_mode_delay = 10 + ((10 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Fireing comets from one end. + */ +static void mode_comet(struct ws2812fx* fx) +{ + + for (uint16_t i=0; i < fx->_led_count; i++) { + uint32_t px_rgb = get_pixel_color(fx, i); + + uint8_t px_r = (px_rgb & 0x00FF0000) >> 16; + uint8_t px_g = (px_rgb & 0x0000FF00) >> 8; + uint8_t 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; + + set_pixel_rgb_color(fx, i, px_r, px_g, px_b); + } + + set_pixel_color(fx, fx->_counter_mode_step, fx->_color); + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % fx->_led_count; + fx->_mode_delay = 10 + ((10 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Firework sparks. + */ +static void mode_fireworks(struct ws2812fx* fx) +{ + uint32_t px_rgb = 0; + uint8_t px_r = 0; + uint8_t px_g = 0; + uint8_t px_b = 0; + + for (uint16_t i=0; i < fx->_led_count; i++) { + px_rgb = get_pixel_color(fx, 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; + + set_pixel_rgb_color(fx, i, px_r, px_g, px_b); + } + + // first LED has only one neighbour + px_r = (((get_pixel_color(fx, 1) & 0x00FF0000) >> 16) >> 1) + ((get_pixel_color(fx, 0) & 0x00FF0000) >> 16); + px_g = (((get_pixel_color(fx, 1) & 0x0000FF00) >> 8) >> 1) + ((get_pixel_color(fx, 0) & 0x0000FF00) >> 8); + px_b = (((get_pixel_color(fx, 1) & 0x000000FF) >> 0) >> 1) + ((get_pixel_color(fx, 0) & 0x000000FF) >> 0); + set_pixel_rgb_color(fx, 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 < fx->_led_count-1; i++) { + px_r = (( + (((get_pixel_color(fx, i-1) & 0x00FF0000) >> 16) >> 1) + + (((get_pixel_color(fx, i+1) & 0x00FF0000) >> 16) >> 0) ) >> 1) + + (((get_pixel_color(fx, i ) & 0x00FF0000) >> 16) >> 0); + + px_g = (( + (((get_pixel_color(fx, i-1) & 0x0000FF00) >> 8) >> 1) + + (((get_pixel_color(fx, i+1) & 0x0000FF00) >> 8) >> 0) ) >> 1) + + (((get_pixel_color(fx, i ) & 0x0000FF00) >> 8) >> 0); + + px_b = (( + (((get_pixel_color(fx, i-1) & 0x000000FF) >> 0) >> 1) + + (((get_pixel_color(fx, i+1) & 0x000000FF) >> 0) >> 0) ) >> 1) + + (((get_pixel_color(fx, i ) & 0x000000FF) >> 0) >> 0); + + set_pixel_rgb_color(fx, i, px_r, px_g, px_b); + } + + // last LED has only one neighbour + px_r = (((get_pixel_color(fx, fx->_led_count-2) & 0x00FF0000) >> 16) >> 2) + ((get_pixel_color(fx, fx->_led_count-1) & 0x00FF0000) >> 16); + px_g = (((get_pixel_color(fx, fx->_led_count-2) & 0x0000FF00) >> 8) >> 2) + ((get_pixel_color(fx, fx->_led_count-1) & 0x0000FF00) >> 8); + px_b = (((get_pixel_color(fx, fx->_led_count-2) & 0x000000FF) >> 0) >> 2) + ((get_pixel_color(fx, fx->_led_count-1) & 0x000000FF) >> 0); + set_pixel_rgb_color(fx, fx->_led_count-1, px_r, px_g, px_b); + + if (!fx->_triggered) { + for (uint16_t i=0; i_led_count/20); i++) { + if (random(10) == 0) { + set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); + } + } + } else { + for (uint16_t i=0; i_led_count/10); i++) { + set_pixel_color(fx, random(fx->_led_count), fx->_mode_color); + } + } + + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_mode_delay = 20 + ((20 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +/* + * Random colored firework sparks. + */ +static void mode_fireworks_random(struct ws2812fx* fx) +{ + fx->_mode_color = color_wheel(random(256)); + mode_fireworks(fx); +} + + +/* + * Alternating red/green pixels running. + */ +static void mode_merry_christmas(struct ws2812fx* fx) +{ + for (uint16_t i=0; i < fx->_led_count; i++) { + if ((i + fx->_counter_mode_step) % 4 < 2) { + set_pixel_color(fx, i, RED); + } else { + set_pixel_color(fx, i, GREEN); + } + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + + fx->_counter_mode_step = (fx->_counter_mode_step + 1) % 4; + fx->_mode_delay = 100 + ((100 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / fx->_led_count); +} + + +static void mode_fire_flicker_int(struct ws2812fx* fx, int rev_intensity) +{ + uint8_t p_r = (fx->_color & 0x00FF0000) >> 16; + uint8_t p_g = (fx->_color & 0x0000FF00) >> 8; + uint8_t p_b = (fx->_color & 0x000000FF) >> 0; + uint8_t flicker_val = max(p_r,max(p_g, p_b))/rev_intensity; + for (uint16_t i=0; i < fx->_led_count; i++) + { + int flicker = random(flicker_val); + int r1 = p_r-flicker; + int g1 = p_g-flicker; + int b1 = p_b-flicker; + if (g1<0) g1=0; + if (r1<0) r1=0; + if (b1<0) b1=0; + set_pixel_rgb_color(fx, i, r1, g1, b1); + } + ws2812_send_frame(fx->wsconf, fx->_led_count); + fx->_mode_delay = 10 + ((500 * (uint32_t)(FX_SPEED_MAX - fx->_speed)) / FX_SPEED_MAX); +} + +/* + * Random flickering. + */ +static void mode_fire_flicker(struct ws2812fx* fx) +{ + mode_fire_flicker_int(fx, 3); +} + +/* + * Random flickering, less intesity. + */ +static void mode_fire_flicker_soft(struct ws2812fx* fx) +{ + mode_fire_flicker_int(fx, 6); +} + + +typedef void (*mode_ptr)(struct ws2812fx* fx); + +static struct { + mode_ptr _fn; + char *_name; +} const modes[] = { + { mode_static, "Static" }, + { mode_blink, "Blink" }, + { mode_breath, "Breath" }, + { mode_color_wipe, "Color Wipe" }, + { mode_color_wipe_random, "Color Wipe Random" }, + { mode_random_color, "Random Color" }, + { mode_single_dynamic, "Single Dynamic" }, + { mode_multi_dynamic, "Multi Dynamic" }, + { mode_rainbow, "Rainbow" }, + { mode_rainbow_cycle, "Rainbow Cycle" }, + { mode_theater_chase, "Theater Chase" }, + { mode_theater_chase_rainbow, "Theater Chase Rainbow" }, + { mode_scan, "Scan" }, + { mode_dual_scan, "Dual Scan" }, + { mode_fade, "Fade" }, +#if 0 + { mode_running_lights, "Running Lights" }, +#endif + { mode_twinkle, "Twinkle" }, + { mode_twinkle_random, "Twinkle Random" }, + { mode_twinkle_fade, "Twinkle Fade" }, + { mode_twinkle_fade_random, "Twinkle Fade Random" }, + { mode_sparkle, "Sparkle" }, + { mode_flash_sparkle, "Flash Sparkle" }, + { mode_hyper_sparkle, "Hyper Sparkle" }, + { mode_strobe, "Strobe" }, + { mode_strobe_rainbow, "Strobe Rainbow" }, + { mode_multi_strobe, "Multi Strobe" }, + { mode_blink_rainbow, "Blink Rainbow" }, + { mode_chase_white, "Chase White" }, + { mode_chase_color, "Chase Color" }, + { mode_chase_random, "Chase Random" }, + { mode_chase_rainbow, "Chase Rainbow" }, + { mode_chase_flash, "Chase Flash" }, + { mode_chase_flash_random, "Chase Flash Random" }, + { mode_chase_rainbow_white, "Chase Rainbow White" }, + { mode_chase_blackout, "Chase Blackout" }, + { mode_chase_blackout_rainbow, "Chase Blackout Rainbow" }, + { mode_color_sweep_random, "Color Sweep Random" }, + { mode_running_color, "Running Color" }, + { mode_running_red_blue, "Running Red Blue" }, + { mode_running_random, "Running Random" }, + { mode_larson_scanner, "Larson Scanner" }, + { mode_comet, "Comet" }, + { mode_fireworks, "Fireworks" }, + { mode_fireworks_random, "Fireworks Random" }, + { mode_merry_christmas, "Merry Christmas" }, + { mode_fire_flicker, "Fire Flicker" }, + { mode_fire_flicker_soft, "Fire Flicker (soft)" }, +}; + +#define CALL_MODE(fx, n) (modes[n]._fn)(fx); + +void WS2812FX(struct ws2812fx* fx, uint16_t n, const struct pio *pin) +{ + fx->wsconf->nb_leds = n; + ws2812_config(fx->wsconf, pin); + + fx->_speed = FX_DEFAULT_SPEED; + fx->_brightness = FX_DEFAULT_BRIGHTNESS; + fx->_running = 0; + fx->_led_count = n; + fx->_mode_last_call_time = 0; + fx->_mode_delay = 0; + fx->_color = FX_DEFAULT_COLOR; + fx->_mode_color = FX_DEFAULT_COLOR; + fx->_counter_mode_call = 0; + fx->_counter_mode_step = 0; +} + +void FX_init(struct ws2812fx* fx) +{ + FX_setBrightness(fx, fx->_brightness); + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + +void FX_service(struct ws2812fx* fx) +{ + if (fx->_running || fx->_triggered) { + unsigned long now = millis(); + + if (now - fx->_mode_last_call_time > fx->_mode_delay || fx->_triggered) { + CALL_MODE(fx, fx->_mode_index); + fx->_counter_mode_call++; + fx->_mode_last_call_time = now; + fx->_triggered = 0; + } + } +} + +void FX_start(struct ws2812fx* fx) +{ + fx->_counter_mode_call = 0; + fx->_counter_mode_step = 0; + fx->_mode_last_call_time = 0; + fx->_running = 1; +} + +void FX_stop(struct ws2812fx* fx) +{ + fx->_running = 0; + strip_off(fx); +} + +void FX_trigger(struct ws2812fx* fx) +{ + fx->_triggered = 1; +} + +void FX_setMode(struct ws2812fx* fx, uint8_t m) +{ + fx->_counter_mode_call = 0; + fx->_counter_mode_step = 0; + fx->_mode_last_call_time = 0; + fx->_mode_index = constrain(m, 0, FX_MODE_COUNT-1); + fx->_mode_color = fx->_color; + ws2812_set_brightness(fx->wsconf, fx->_brightness); + //strip_off(fx); +} + +void FX_setSpeed(struct ws2812fx* fx, uint8_t s) +{ + fx->_counter_mode_call = 0; + fx->_counter_mode_step = 0; + fx->_mode_last_call_time = 0; + fx->_speed = constrain(s, FX_SPEED_MIN, FX_SPEED_MAX); + //strip_off(fx); +} + +void FX_increaseSpeed(struct ws2812fx* fx, uint8_t s) +{ + s = constrain(fx->_speed + s, FX_SPEED_MIN, FX_SPEED_MAX); + FX_setSpeed(fx, s); +} + +void FX_decreaseSpeed(struct ws2812fx* fx, uint8_t s) +{ + s = constrain(fx->_speed - s, FX_SPEED_MIN, FX_SPEED_MAX); + FX_setSpeed(fx, s); +} + +void FX_setRGBColor(struct ws2812fx* fx, uint8_t r, uint8_t g, uint8_t b) +{ + FX_setColor(fx, ((uint32_t)r << 16) | ((uint32_t)g << 8) | b); +} + +void FX_setColor(struct ws2812fx* fx, uint32_t c) +{ + fx->_color = c; + fx->_counter_mode_call = 0; + fx->_counter_mode_step = 0; + fx->_mode_last_call_time = 0; + fx->_mode_color = fx->_color; + ws2812_set_brightness(fx->wsconf, fx->_brightness); + //strip_off(fx); +} + +void FX_setBrightness(struct ws2812fx* fx, uint8_t b) +{ + fx->_brightness = constrain(b, FX_BRIGHTNESS_MIN, FX_BRIGHTNESS_MAX); + ws2812_set_brightness(fx->wsconf, fx->_brightness); + ws2812_send_frame(fx->wsconf, fx->_led_count); +} + +void FX_increaseBrightness(struct ws2812fx* fx, uint8_t s) +{ + s = constrain(fx->_brightness + s, FX_BRIGHTNESS_MIN, FX_BRIGHTNESS_MAX); + FX_setBrightness(fx, s); +} + +void FX_decreaseBrightness(struct ws2812fx* fx, uint8_t s) +{ + s = constrain(fx->_brightness - s, FX_BRIGHTNESS_MIN, FX_BRIGHTNESS_MAX); + FX_setBrightness(fx, s); +} + +int FX_isRunning(struct ws2812fx* fx) +{ + return fx->_running; +} + +uint8_t FX_getMode(struct ws2812fx* fx) +{ + return fx->_mode_index; +} + +uint8_t FX_getSpeed(struct ws2812fx* fx) +{ + return fx->_speed; +} + +uint8_t FX_getBrightness(struct ws2812fx* fx) +{ + return fx->_brightness; +} + +uint8_t FX_getModeCount(struct ws2812fx* fx) +{ + return FX_MODE_COUNT; +} + +uint32_t FX_getColor(struct ws2812fx* fx) +{ + return fx->_color; +} + +const char* FX_getModeName(uint8_t m) +{ + if (m < FX_MODE_COUNT) { + return modes[m]._name; + } else { + return ""; + } +} diff --git a/include/extdrv/ws2812fx.h b/include/extdrv/ws2812fx.h deleted file mode 100644 index df00f2e..0000000 --- a/include/extdrv/ws2812fx.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - WS2812FX.h - Library for WS2812 LED effects. - - Harm Aldick - 2016 - www.aldick.org - FEATURES -/ * A lot of blinken modes and countin2 - * 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) - 2017-02-02 added external trigger functionality (e.g. for sound-to-light) -*/ - -#ifndef WS2812FX_h -#define WS2812FX_h - -#include "core/pio.h" -#include "extdrv/ws2812.h" - -#define FX_DEFAULT_BRIGHTNESS 50 -#define FX_DEFAULT_MODE 0 -#define FX_DEFAULT_SPEED 150 -#define FX_DEFAULT_COLOR 0xFF0000 - -#define FX_SPEED_MIN 0 -#define FX_SPEED_MAX 255 - -#define FX_BRIGHTNESS_MIN 0 -#define FX_BRIGHTNESS_MAX 255 - -enum ModeFX { - FX_MODE_STATIC, - FX_MODE_BLINK, - FX_MODE_BREATH, - FX_MODE_COLOR_WIPE, - FX_MODE_COLOR_WIPE_RANDOM, - FX_MODE_RANDOM_COLOR, - FX_MODE_SINGLE_DYNAMIC, - FX_MODE_MULTI_DYNAMIC, - FX_MODE_RAINBOW, - FX_MODE_RAINBOW_CYCLE, - FX_MODE_THEATER_CHASE, - FX_MODE_THEATER_CHASE_RAINBOW, - FX_MODE_SCAN, - FX_MODE_DUAL_SCAN, - FX_MODE_FADE, -#if 0 - FX_MODE_RUNNING_LIGHTS, -#endif - FX_MODE_TWINKLE, - FX_MODE_TWINKLE_RANDOM, - FX_MODE_TWINKLE_FADE, - FX_MODE_TWINKLE_FADE_RANDOM, - FX_MODE_SPARKLE, - FX_MODE_FLASH_SPARKLE, - FX_MODE_HYPER_SPARKLE, - FX_MODE_STROBE, - FX_MODE_STROBE_RAINBOW, - FX_MODE_MULTI_STROBE, - FX_MODE_BLINK_RAINBOW, - FX_MODE_CHASE_WHITE, - FX_MODE_CHASE_COLOR, - FX_MODE_CHASE_RANDOM, - FX_MODE_CHASE_RAINBOW, - FX_MODE_CHASE_FLASH, - FX_MODE_CHASE_FLASH_RANDOM, - FX_MODE_CHASE_RAINBOW_WHITE, - FX_MODE_CHASE_BLACKOUT, - FX_MODE_CHASE_BLACKOUT_RAINBOW, - FX_MODE_COLOR_SWEEP_RANDOM, - FX_MODE_RUNNING_COLOR, - FX_MODE_RUNNING_RED_BLUE, - FX_MODE_RUNNING_RANDOM, - FX_MODE_LARSON_SCANNER, - FX_MODE_COMET, - FX_MODE_FIREWORKS, - FX_MODE_FIREWORKS_RANDOM, - FX_MODE_MERRY_CHRISTMAS, - FX_MODE_FIRE_FLICKER, - FX_MODE_FIRE_FLICKER_SOFT, - FX_MODE_COUNT -}; - -struct ws2812fx { - struct ws2812_conf* wsconf; - int _running; - int _triggered; - - uint32_t _color; - uint32_t _counter_mode_call; - uint32_t _counter_mode_step; - uint32_t _mode_color; - uint32_t _mode_delay; - - unsigned long _mode_last_call_time; - - uint16_t _led_count; - - uint8_t _mode_index; - uint8_t _speed; - uint8_t _brightness; -}; - -void WS2812FX(struct ws2812fx* fx, uint16_t n, const struct pio* pin); - -void FX_init(struct ws2812fx* fx); -void FX_service(struct ws2812fx* fx); -void FX_start(struct ws2812fx* fx); -void FX_stop(struct ws2812fx* fx); -void FX_setMode(struct ws2812fx* fx, uint8_t m); -void FX_setSpeed(struct ws2812fx* fx, uint8_t s); -void FX_increaseSpeed(struct ws2812fx* fx, uint8_t s); -void FX_decreaseSpeed(struct ws2812fx* fx, uint8_t s); -void FX_setRGBColor(struct ws2812fx* fx, uint8_t r, uint8_t g, uint8_t b); -void FX_setColor(struct ws2812fx* fx, uint32_t c); -void FX_trigger(struct ws2812fx* fx); -void FX_setBrightness(struct ws2812fx* fx, uint8_t b); -void FX_increaseBrightness(struct ws2812fx* fx, uint8_t s); -void FX_decreaseBrightness(struct ws2812fx* fx, uint8_t s); - -int FX_isRunning(struct ws2812fx* fx); - -uint8_t FX_getMode(struct ws2812fx* fx); -uint8_t FX_getSpeed(struct ws2812fx* fx); -uint8_t FX_getBrightness(struct ws2812fx* fx); -uint8_t FX_getModeCount(struct ws2812fx* fx); - -uint32_t FX_getColor(struct ws2812fx* fx); - -const char* FX_getModeName(uint8_t m); - -#endif diff --git a/include/extlib/ws2812fx/ws2812fx.h b/include/extlib/ws2812fx/ws2812fx.h new file mode 100644 index 0000000..51b1cc7 --- /dev/null +++ b/include/extlib/ws2812fx/ws2812fx.h @@ -0,0 +1,158 @@ +/**************************************************************************** + * + * include/extlib/ws2812fx/ws2812fx.h - Library for WS2812 LED effects. + * + * Fork from Harm Aldick's work - 2016 - www.aldick.org + * https://github.com/kitesurfer1404/WS2812FX.git + * + * FEATURES + * - A lot of blinken modes and counting + * - WS2812FX can be used as drop-in replacement for Adafruit Neopixel Library + * + * 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) + * 2017-02-02 added external trigger functionality (e.g. for sound-to-light) + * 2017-02-02 removed "blackout" on mode, speed or color-change + * + *************************************************************************** */ + +#ifndef WS2812FX_h +#define WS2812FX_h + +#include "core/pio.h" +#include "extdrv/ws2812.h" + +#define FX_DEFAULT_BRIGHTNESS 50 +#define FX_DEFAULT_MODE 0 +#define FX_DEFAULT_SPEED 150 +#define FX_DEFAULT_COLOR 0xFF0000 + +#define FX_SPEED_MIN 0 +#define FX_SPEED_MAX 255 + +#define FX_BRIGHTNESS_MIN 0 +#define FX_BRIGHTNESS_MAX 255 + +enum ModeFX { + FX_MODE_STATIC, + FX_MODE_BLINK, + FX_MODE_BREATH, + FX_MODE_COLOR_WIPE, + FX_MODE_COLOR_WIPE_RANDOM, + FX_MODE_RANDOM_COLOR, + FX_MODE_SINGLE_DYNAMIC, + FX_MODE_MULTI_DYNAMIC, + FX_MODE_RAINBOW, + FX_MODE_RAINBOW_CYCLE, + FX_MODE_THEATER_CHASE, + FX_MODE_THEATER_CHASE_RAINBOW, + FX_MODE_SCAN, + FX_MODE_DUAL_SCAN, + FX_MODE_FADE, +#if 0 + FX_MODE_RUNNING_LIGHTS, +#endif + FX_MODE_TWINKLE, + FX_MODE_TWINKLE_RANDOM, + FX_MODE_TWINKLE_FADE, + FX_MODE_TWINKLE_FADE_RANDOM, + FX_MODE_SPARKLE, + FX_MODE_FLASH_SPARKLE, + FX_MODE_HYPER_SPARKLE, + FX_MODE_STROBE, + FX_MODE_STROBE_RAINBOW, + FX_MODE_MULTI_STROBE, + FX_MODE_BLINK_RAINBOW, + FX_MODE_CHASE_WHITE, + FX_MODE_CHASE_COLOR, + FX_MODE_CHASE_RANDOM, + FX_MODE_CHASE_RAINBOW, + FX_MODE_CHASE_FLASH, + FX_MODE_CHASE_FLASH_RANDOM, + FX_MODE_CHASE_RAINBOW_WHITE, + FX_MODE_CHASE_BLACKOUT, + FX_MODE_CHASE_BLACKOUT_RAINBOW, + FX_MODE_COLOR_SWEEP_RANDOM, + FX_MODE_RUNNING_COLOR, + FX_MODE_RUNNING_RED_BLUE, + FX_MODE_RUNNING_RANDOM, + FX_MODE_LARSON_SCANNER, + FX_MODE_COMET, + FX_MODE_FIREWORKS, + FX_MODE_FIREWORKS_RANDOM, + FX_MODE_MERRY_CHRISTMAS, + FX_MODE_FIRE_FLICKER, + FX_MODE_FIRE_FLICKER_SOFT, + FX_MODE_COUNT +}; + +struct ws2812fx { + struct ws2812_conf* wsconf; + int _running; + int _triggered; + + uint32_t _color; + uint32_t _counter_mode_call; + uint32_t _counter_mode_step; + uint32_t _mode_color; + uint32_t _mode_delay; + + unsigned long _mode_last_call_time; + + uint16_t _led_count; + + uint8_t _mode_index; + uint8_t _speed; + uint8_t _brightness; +}; + +void WS2812FX(struct ws2812fx* fx, uint16_t n, const struct pio* pin); + +void FX_init(struct ws2812fx* fx); +void FX_service(struct ws2812fx* fx); +void FX_start(struct ws2812fx* fx); +void FX_stop(struct ws2812fx* fx); +void FX_setMode(struct ws2812fx* fx, uint8_t m); +void FX_setSpeed(struct ws2812fx* fx, uint8_t s); +void FX_increaseSpeed(struct ws2812fx* fx, uint8_t s); +void FX_decreaseSpeed(struct ws2812fx* fx, uint8_t s); +void FX_setRGBColor(struct ws2812fx* fx, uint8_t r, uint8_t g, uint8_t b); +void FX_setColor(struct ws2812fx* fx, uint32_t c); +void FX_trigger(struct ws2812fx* fx); +void FX_setBrightness(struct ws2812fx* fx, uint8_t b); +void FX_increaseBrightness(struct ws2812fx* fx, uint8_t s); +void FX_decreaseBrightness(struct ws2812fx* fx, uint8_t s); + +int FX_isRunning(struct ws2812fx* fx); + +uint8_t FX_getMode(struct ws2812fx* fx); +uint8_t FX_getSpeed(struct ws2812fx* fx); +uint8_t FX_getBrightness(struct ws2812fx* fx); +uint8_t FX_getModeCount(struct ws2812fx* fx); + +uint32_t FX_getColor(struct ws2812fx* fx); + +const char* FX_getModeName(uint8_t m); + +#endif