From 5befcd24b526cb5822f0dec3de071ba44af6fe2e Mon Sep 17 00:00:00 2001 From: Def3nder <33399267+Def3nder@users.noreply.github.com> Date: Mon, 17 Feb 2020 11:01:05 +0100 Subject: [PATCH] Effect "Heartbeat" (#680) --- wled00/FX.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 6 +++++- wled00/NpbWrapper.h | 9 +++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 36dcecc6..bb290038 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3119,4 +3119,44 @@ uint16_t WS2812FX::mode_percent(void) { } return FRAMETIME; +} + +uint16_t WS2812FX::mode_heartbeat(void) { + static unsigned long lastBeat = 0; + static bool secondBeatActive = false; + + uint8_t bpm = 40 + (SEGMENT.speed >> 4); + uint32_t msPerBeat = (60000 / bpm); + uint32_t secondBeat = (msPerBeat / 3); + + // Get and translate the segment's size option + uint8_t size = 2 << ((SEGMENT.options >> 1) & 0x03); // 2,4,8,16 + + // copy pixels from the middle of the segment to the edges + uint16_t bytesPerPixelBlock = size * 4; + uint16_t centerOffset = (SEGLEN / 2) * 4; + uint16_t byteCount = centerOffset - bytesPerPixelBlock; + memmove(bus->GetPixels(), bus->GetPixels() + bytesPerPixelBlock, byteCount); + memmove(bus->GetPixels() + centerOffset + bytesPerPixelBlock, bus->GetPixels() + centerOffset, byteCount); + + fade_out(255 - SEGMENT.intensity); + + unsigned long beatTimer = millis() - lastBeat; + if((beatTimer > secondBeat) && !secondBeatActive) { // time for the second beat? + uint16_t startLed = (SEGLEN / 2) - size; + for (uint16_t i = startLed; i < startLed + (size * 2); i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + secondBeatActive = 1; + } + if(beatTimer > msPerBeat) { // time to reset the beat timer? + uint16_t startLed = (SEGLEN / 2) - size; + for (uint16_t i = startLed; i < startLed + (size * 2); i++) { + setPixelColor(i, SEGMENT.colors[0]); + } + secondBeatActive = 0; + lastBeat = millis(); + } + + return FRAMETIME; } \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 998c546b..79629ece 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -193,6 +193,7 @@ #define FX_MODE_PLASMA 97 #define FX_MODE_PERCENT 98 #define FX_MODE_RIPPLE_RAINBOW 99 +#define FX_MODE_HEARTBEAT 100 class WS2812FX { typedef uint16_t (WS2812FX::*mode_ptr)(void); @@ -380,6 +381,7 @@ class WS2812FX { _mode[FX_MODE_DRIP] = &WS2812FX::mode_drip; _mode[FX_MODE_PLASMA] = &WS2812FX::mode_plasma; _mode[FX_MODE_PERCENT] = &WS2812FX::mode_percent; + _mode[FX_MODE_HEARTBEAT] = &WS2812FX::mode_heartbeat; _mode[FX_MODE_RIPPLE_RAINBOW] = &WS2812FX::mode_ripple_rainbow; _brightness = DEFAULT_BRIGHTNESS; @@ -565,6 +567,7 @@ class WS2812FX { mode_drip(void), mode_plasma(void), mode_percent(void), + mode_heartbeat(void); mode_ripple_rainbow(void); @@ -646,7 +649,8 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst", -"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent", "Ripple Rainbow" +"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow", +"Heartbeat" ])====="; diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index 9f391556..54d21ac1 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -287,6 +287,15 @@ public: return 0; } + uint8_t* GetPixels(void) + { + switch (_type) { + case NeoPixelType_Grb: return _pGrb->Pixels(); break; + case NeoPixelType_Grbw: return _pGrbw->Pixels(); break; + } + return 0; + } + private: NeoPixelType _type;