From 06459aca336c8a57d553f9a434e55b445c1d2117 Mon Sep 17 00:00:00 2001 From: Mariusz Ryndzionek Date: Thu, 9 Jan 2025 18:23:52 +0100 Subject: [PATCH 1/4] Added new effect usermod - Diffusion Fire --- .../diffusionfire/usermod_diffusionfire.h | 118 ++++++++++++++++++ wled00/const.h | 2 + wled00/usermods_list.cpp | 9 +- 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 usermods/diffusionfire/usermod_diffusionfire.h diff --git a/usermods/diffusionfire/usermod_diffusionfire.h b/usermods/diffusionfire/usermod_diffusionfire.h new file mode 100644 index 0000000000..fbce9a6fbd --- /dev/null +++ b/usermods/diffusionfire/usermod_diffusionfire.h @@ -0,0 +1,118 @@ +static uint16_t mode_static(void) +{ + SEGMENT.fill(SEGCOLOR(0)); + return strip.isOffRefreshRequired() ? FRAMETIME : 350; +} + +static uint16_t mode_diffusionfire(void) +{ + static uint32_t call = 0; + + if (!strip.isMatrix || !SEGMENT.is2D()) + return mode_static(); // not a 2D set-up + + const int cols = SEG_W; + const int rows = SEG_H; + + const uint8_t refresh_hz = map(SEGMENT.speed, 0, 255, 20, 80); + const unsigned refresh_ms = 1000 / refresh_hz; + const int16_t diffusion = map(SEGMENT.custom1, 0, 255, 0, 100); + const uint8_t spark_rate = SEGMENT.intensity; + const uint8_t turbulence = SEGMENT.custom2; + + unsigned dataSize = SEGMENT.length() + (cols * sizeof(uint16_t)); + if (!SEGENV.allocateData(dataSize)) + return mode_static(); // allocation failed + + if (SEGENV.call == 0) + { + SEGMENT.fill(BLACK); + SEGENV.step = 0; + call = 0; + } + + if ((strip.now - SEGENV.step) >= refresh_ms) + { + uint16_t *tmp_row = (uint16_t *)(SEGMENT.data + SEGMENT.length()); + SEGENV.step = strip.now; + call++; + + // scroll up + for (unsigned y = 1; y < rows; y++) + for (unsigned x = 0; x < cols; x++) + { + unsigned src = SEGMENT.XY(x, y); + unsigned dst = SEGMENT.XY(x, y - 1); + SEGMENT.data[dst] = SEGMENT.data[src]; + } + + if (random8() > turbulence) + { + // create new sparks at bottom row + for (unsigned x = 0; x < cols; x++) + { + uint8_t p = random8(); + if (p < spark_rate) + { + unsigned dst = SEGMENT.XY(x, rows - 1); + SEGMENT.data[dst] = 255; + } + } + } + + // diffuse + for (unsigned y = 0; y < rows; y++) + { + for (unsigned x = 0; x < cols; x++) + { + unsigned v = SEGMENT.data[SEGMENT.XY(x, y)]; + if (x > 0) + { + v += SEGMENT.data[SEGMENT.XY(x - 1, y)]; + } + if (x < (cols - 1)) + { + v += SEGMENT.data[SEGMENT.XY(x + 1, y)]; + } + tmp_row[x] = min(255, (int)(v / (3.0 + (float)diffusion / 100.0))); + } + + for (unsigned x = 0; x < cols; x++) + { + SEGMENT.data[SEGMENT.XY(x, y)] = tmp_row[x]; + if (SEGMENT.check1) + { + CRGB color = ColorFromPalette(SEGPALETTE, tmp_row[x], 255, NOBLEND); + SEGMENT.setPixelColorXY(x, y, color); + } + else + { + uint32_t color = SEGCOLOR(0); + SEGMENT.setPixelColorXY(x, y, color_fade(color, tmp_row[x])); + } + } + } + } + return FRAMETIME; +} +static const char _data_FX_MODE_DIFFUSIONFIRE[] PROGMEM = "Diffusion Fire@!,Spark rate,Diffusion Speed,Turbulence,,Use palette;;Color;;2;pal=35"; + +class DiffusionFireUsermod : public Usermod +{ + +private: +public: + void setup() + { + strip.addEffect(255, &mode_diffusionfire, _data_FX_MODE_DIFFUSIONFIRE); + } + + void loop() + { + } + + uint16_t getId() + { + return USERMOD_ID_DIFFUSIONFIRE; + } +}; diff --git a/wled00/const.h b/wled00/const.h index bdd20beba1..71f36781e4 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -204,6 +204,8 @@ #define USERMOD_ID_POV_DISPLAY 53 //Usermod "usermod_pov_display.h" #define USERMOD_ID_PIXELS_DICE_TRAY 54 //Usermod "pixels_dice_tray.h" #define USERMOD_ID_DEEP_SLEEP 55 //Usermod "usermod_deep_sleep.h" +#define USERMOD_ID_DIFFUSIONFIRE 56 //Usermod "usermod_diffusionfire.h" + //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 627fa6308a..5055bfb101 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -242,9 +242,12 @@ #include "../usermods/LD2410_v2/usermod_ld2410.h" #endif - #ifdef USERMOD_DEEP_SLEEP #include "../usermods/deep_sleep/usermod_deep_sleep.h" +#endif + +#ifdef USERMOD_DIFFUSIONFIRE +#include "../usermods/diffusionfire/usermod_diffusionfire.h" #endif void registerUsermods() @@ -479,4 +482,8 @@ void registerUsermods() #ifdef USERMOD_DEEP_SLEEP usermods.add(new DeepSleepUsermod()); #endif + + #ifdef USERMOD_DIFFUSIONFIRE + UsermodManager::add(new DiffusionFireUsermod()); + #endif } From eae504e24132a51fffc6a7779ebeceb19f7dc611 Mon Sep 17 00:00:00 2001 From: Mariusz Ryndzionek Date: Wed, 15 Jan 2025 07:45:59 +0100 Subject: [PATCH 2/4] Renamed the usermod to 'user_fx' (code review request) --- .../usermod_diffusionfire.h => user_fx/usermod_user_fx.h} | 4 ++-- wled00/const.h | 2 +- wled00/usermods_list.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) rename usermods/{diffusionfire/usermod_diffusionfire.h => user_fx/usermod_user_fx.h} (97%) diff --git a/usermods/diffusionfire/usermod_diffusionfire.h b/usermods/user_fx/usermod_user_fx.h similarity index 97% rename from usermods/diffusionfire/usermod_diffusionfire.h rename to usermods/user_fx/usermod_user_fx.h index fbce9a6fbd..5bde7c4c98 100644 --- a/usermods/diffusionfire/usermod_diffusionfire.h +++ b/usermods/user_fx/usermod_user_fx.h @@ -97,7 +97,7 @@ static uint16_t mode_diffusionfire(void) } static const char _data_FX_MODE_DIFFUSIONFIRE[] PROGMEM = "Diffusion Fire@!,Spark rate,Diffusion Speed,Turbulence,,Use palette;;Color;;2;pal=35"; -class DiffusionFireUsermod : public Usermod +class UserFxUsermod : public Usermod { private: @@ -113,6 +113,6 @@ class DiffusionFireUsermod : public Usermod uint16_t getId() { - return USERMOD_ID_DIFFUSIONFIRE; + return USERMOD_ID_USER_FX; } }; diff --git a/wled00/const.h b/wled00/const.h index 71f36781e4..cd77470230 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -204,7 +204,7 @@ #define USERMOD_ID_POV_DISPLAY 53 //Usermod "usermod_pov_display.h" #define USERMOD_ID_PIXELS_DICE_TRAY 54 //Usermod "pixels_dice_tray.h" #define USERMOD_ID_DEEP_SLEEP 55 //Usermod "usermod_deep_sleep.h" -#define USERMOD_ID_DIFFUSIONFIRE 56 //Usermod "usermod_diffusionfire.h" +#define USERMOD_ID_USER_FX 56 //Usermod "usermod_user_fx.h" //Access point behavior diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 5055bfb101..54cef37626 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -246,8 +246,8 @@ #include "../usermods/deep_sleep/usermod_deep_sleep.h" #endif -#ifdef USERMOD_DIFFUSIONFIRE -#include "../usermods/diffusionfire/usermod_diffusionfire.h" +#ifdef USERMOD_USER_FX +#include "../usermods/user_fx/usermod_user_fx.h" #endif void registerUsermods() @@ -483,7 +483,7 @@ void registerUsermods() usermods.add(new DeepSleepUsermod()); #endif - #ifdef USERMOD_DIFFUSIONFIRE - UsermodManager::add(new DiffusionFireUsermod()); + #ifdef USERMOD_USER_FX + UsermodManager::add(new UserFxUsermod()); #endif } From 4218da5e5d731a46dbd158750de7356ed7312df8 Mon Sep 17 00:00:00 2001 From: Mariusz Ryndzionek Date: Wed, 15 Jan 2025 09:45:08 +0100 Subject: [PATCH 3/4] Further code review adjustments: - use hw_random8 instead of random8 - changed diffusion calculation to fixed point math - adjusted general code formatting --- usermods/user_fx/usermod_user_fx.h | 78 +++++++++++------------------- 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/usermods/user_fx/usermod_user_fx.h b/usermods/user_fx/usermod_user_fx.h index 5bde7c4c98..627591b95d 100644 --- a/usermods/user_fx/usermod_user_fx.h +++ b/usermods/user_fx/usermod_user_fx.h @@ -1,15 +1,13 @@ -static uint16_t mode_static(void) -{ +static uint16_t mode_static(void) { SEGMENT.fill(SEGCOLOR(0)); return strip.isOffRefreshRequired() ? FRAMETIME : 350; } -static uint16_t mode_diffusionfire(void) -{ +static uint16_t mode_diffusionfire(void) { static uint32_t call = 0; if (!strip.isMatrix || !SEGMENT.is2D()) - return mode_static(); // not a 2D set-up + return mode_static(); // not a 2D set-up const int cols = SEG_W; const int rows = SEG_H; @@ -22,38 +20,32 @@ static uint16_t mode_diffusionfire(void) unsigned dataSize = SEGMENT.length() + (cols * sizeof(uint16_t)); if (!SEGENV.allocateData(dataSize)) - return mode_static(); // allocation failed + return mode_static(); // allocation failed - if (SEGENV.call == 0) - { + if (SEGENV.call == 0) { SEGMENT.fill(BLACK); SEGENV.step = 0; call = 0; } - if ((strip.now - SEGENV.step) >= refresh_ms) - { + if ((strip.now - SEGENV.step) >= refresh_ms) { uint16_t *tmp_row = (uint16_t *)(SEGMENT.data + SEGMENT.length()); SEGENV.step = strip.now; call++; // scroll up for (unsigned y = 1; y < rows; y++) - for (unsigned x = 0; x < cols; x++) - { + for (unsigned x = 0; x < cols; x++) { unsigned src = SEGMENT.XY(x, y); unsigned dst = SEGMENT.XY(x, y - 1); SEGMENT.data[dst] = SEGMENT.data[src]; } - if (random8() > turbulence) - { + if (hw_random8() > turbulence) { // create new sparks at bottom row - for (unsigned x = 0; x < cols; x++) - { - uint8_t p = random8(); - if (p < spark_rate) - { + for (unsigned x = 0; x < cols; x++) { + uint8_t p = hw_random8(); + if (p < spark_rate) { unsigned dst = SEGMENT.XY(x, rows - 1); SEGMENT.data[dst] = 255; } @@ -61,32 +53,24 @@ static uint16_t mode_diffusionfire(void) } // diffuse - for (unsigned y = 0; y < rows; y++) - { - for (unsigned x = 0; x < cols; x++) - { + for (unsigned y = 0; y < rows; y++) { + for (unsigned x = 0; x < cols; x++) { unsigned v = SEGMENT.data[SEGMENT.XY(x, y)]; - if (x > 0) - { + if (x > 0) { v += SEGMENT.data[SEGMENT.XY(x - 1, y)]; } - if (x < (cols - 1)) - { + if (x < (cols - 1)) { v += SEGMENT.data[SEGMENT.XY(x + 1, y)]; } - tmp_row[x] = min(255, (int)(v / (3.0 + (float)diffusion / 100.0))); + tmp_row[x] = min(255, (int)(v * 100 / (300 + diffusion))); } - for (unsigned x = 0; x < cols; x++) - { + for (unsigned x = 0; x < cols; x++) { SEGMENT.data[SEGMENT.XY(x, y)] = tmp_row[x]; - if (SEGMENT.check1) - { + if (SEGMENT.check1) { CRGB color = ColorFromPalette(SEGPALETTE, tmp_row[x], 255, NOBLEND); SEGMENT.setPixelColorXY(x, y, color); - } - else - { + } else { uint32_t color = SEGCOLOR(0); SEGMENT.setPixelColorXY(x, y, color_fade(color, tmp_row[x])); } @@ -95,24 +79,18 @@ static uint16_t mode_diffusionfire(void) } return FRAMETIME; } -static const char _data_FX_MODE_DIFFUSIONFIRE[] PROGMEM = "Diffusion Fire@!,Spark rate,Diffusion Speed,Turbulence,,Use palette;;Color;;2;pal=35"; - -class UserFxUsermod : public Usermod -{ +static const char _data_FX_MODE_DIFFUSIONFIRE[] PROGMEM = + "Diffusion Fire@!,Spark rate,Diffusion Speed,Turbulence,,Use " + "palette;;Color;;2;pal=35"; -private: -public: - void setup() - { +class UserFxUsermod : public Usermod { + private: + public: + void setup() { strip.addEffect(255, &mode_diffusionfire, _data_FX_MODE_DIFFUSIONFIRE); } - void loop() - { - } + void loop() {} - uint16_t getId() - { - return USERMOD_ID_USER_FX; - } + uint16_t getId() { return USERMOD_ID_USER_FX; } }; From 7b3a9885c4e84d5119479c5e9904b79c2c8d87b7 Mon Sep 17 00:00:00 2001 From: Mariusz Ryndzionek Date: Wed, 15 Jan 2025 09:47:50 +0100 Subject: [PATCH 4/4] Added short readme file --- usermods/user_fx/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 usermods/user_fx/README.md diff --git a/usermods/user_fx/README.md b/usermods/user_fx/README.md new file mode 100644 index 0000000000..8dc1d128ef --- /dev/null +++ b/usermods/user_fx/README.md @@ -0,0 +1,4 @@ +# Usermod user FX + +This Usermod is a common place to put various user's LED effects. +