2025-01-19 10:37:57 +00:00
# pragma once
2016-12-17 22:43:07 +00:00
/*
WS2812FX . h - Library for WS2812 LED effects .
Harm Aldick - 2016
www . aldick . org
2024-10-15 22:07:19 +00:00
2018-09-04 13:51:38 +00:00
Copyright ( c ) 2016 Harm Aldick
2024-10-15 22:07:19 +00:00
Licensed under the EUPL v . 1.2 or later
Adapted from code originally licensed under the MIT license
2019-02-09 15:37:20 +00:00
2018-09-04 13:51:38 +00:00
Modified for WLED
2025-01-19 10:37:57 +00:00
Segment class / struct ( c ) 2022 Blaz Kristan ( @ blazoncek )
2016-12-17 22:43:07 +00:00
*/
# ifndef WS2812FX_h
# define WS2812FX_h
2022-07-17 13:58:41 +00:00
# include <vector>
2025-01-19 10:37:57 +00:00
# include "wled.h"
2022-07-17 13:58:41 +00:00
2025-04-22 20:37:18 +00:00
# ifdef WLED_DEBUG
// enable additional debug output
# if defined(WLED_DEBUG_HOST)
# include "net_debug.h"
# define DEBUGOUT NetDebug
# else
# define DEBUGOUT Serial
# endif
# define DEBUGFX_PRINT(x) DEBUGOUT.print(x)
# define DEBUGFX_PRINTLN(x) DEBUGOUT.println(x)
# define DEBUGFX_PRINTF(x...) DEBUGOUT.printf(x)
# define DEBUGFX_PRINTF_P(x...) DEBUGOUT.printf_P(x)
# else
# define DEBUGFX_PRINT(x)
# define DEBUGFX_PRINTLN(x)
# define DEBUGFX_PRINTF(x...)
# define DEBUGFX_PRINTF_P(x...)
# endif
2018-11-09 16:00:36 +00:00
# define FASTLED_INTERNAL //remove annoying pragma messages
2020-08-25 15:23:17 +00:00
# define USE_GET_MILLISECOND_TIMER
2018-11-04 19:14:23 +00:00
# include "FastLED.h"
2016-12-17 22:43:07 +00:00
2018-11-16 18:59:00 +00:00
# define DEFAULT_BRIGHTNESS (uint8_t)127
2018-09-04 13:51:38 +00:00
# define DEFAULT_MODE (uint8_t)0
2018-11-16 18:59:00 +00:00
# define DEFAULT_SPEED (uint8_t)128
2020-09-07 19:01:10 +00:00
# define DEFAULT_INTENSITY (uint8_t)128
2019-03-05 09:59:15 +00:00
# define DEFAULT_COLOR (uint32_t)0xFFAA00
2022-05-08 08:50:48 +00:00
# define DEFAULT_C1 (uint8_t)128
# define DEFAULT_C2 (uint8_t)128
2022-08-12 15:58:20 +00:00
# define DEFAULT_C3 (uint8_t)16
2018-09-04 13:51:38 +00:00
2020-11-17 21:46:17 +00:00
# ifndef MIN
2020-03-26 09:18:19 +00:00
# define MIN(a,b) ((a)<(b)?(a):(b))
2020-11-17 21:46:17 +00:00
# endif
# ifndef MAX
2020-03-26 09:18:19 +00:00
# define MAX(a,b) ((a)>(b)?(a):(b))
2020-11-17 21:46:17 +00:00
# endif
2018-09-04 13:51:38 +00:00
2022-03-25 15:36:05 +00:00
//color mangling macros
# ifndef RGBW32
# define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
# endif
2024-09-23 16:03:17 +00:00
extern bool realtimeRespectLedMaps ; // used in getMappedPixelIndex()
extern byte realtimeMode ; // used in getMappedPixelIndex()
2019-10-03 14:33:37 +00:00
/* Not used in all effects yet */
2019-10-03 23:21:18 +00:00
# define WLED_FPS 42
2021-12-25 00:30:27 +00:00
# define FRAMETIME_FIXED (1000 / WLED_FPS)
2022-07-06 11:13:54 +00:00
# define FRAMETIME strip.getFrameTime()
2024-11-07 22:15:39 +00:00
# if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
# define MIN_FRAME_DELAY 2 // minimum wait between repaints, to keep other functions like WiFi alive
2024-11-21 21:16:03 +00:00
# elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
# define MIN_FRAME_DELAY 3 // S2/C3 are slower than normal esp32, and only have one core
2024-11-01 22:19:38 +00:00
# else
2024-11-07 22:15:39 +00:00
# define MIN_FRAME_DELAY 8 // 8266 legacy MIN_SHOW_DELAY
2024-11-01 22:19:38 +00:00
# endif
2024-11-04 18:49:43 +00:00
# define FPS_UNLIMITED 0
2019-10-03 14:33:37 +00:00
2024-11-04 07:10:05 +00:00
// FPS calculation (can be defined as compile flag for debugging)
# ifndef FPS_CALC_AVG
# define FPS_CALC_AVG 7 // average FPS calculation over this many frames (moving average)
# endif
# ifndef FPS_MULTIPLIER
# define FPS_MULTIPLIER 1 // dev option: multiplier to get sub-frame FPS without floats
# endif
2024-11-04 18:33:42 +00:00
# define FPS_CALC_SHIFT 7 // bit shift for fixed point math
2019-10-03 14:33:37 +00:00
2023-12-31 17:05:21 +00:00
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
2018-09-04 13:51:38 +00:00
insufficient memory , decreasing MAX_NUM_SEGMENTS may help */
2019-12-31 10:11:05 +00:00
# ifdef ESP8266
2025-01-19 10:37:57 +00:00
# define MAX_NUM_SEGMENTS 16
2021-01-08 23:35:48 +00:00
/* How much data bytes all segments combined may allocate */
2022-07-30 12:20:36 +00:00
# define MAX_SEGMENT_DATA 5120
2025-01-19 10:37:57 +00:00
# elif defined(CONFIG_IDF_TARGET_ESP32S2)
# define MAX_NUM_SEGMENTS 20
# define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*512) // 10k by default (S2 is short on free RAM)
2019-12-31 10:11:05 +00:00
# else
2025-01-19 10:37:57 +00:00
# define MAX_NUM_SEGMENTS 32 // warning: going beyond 32 may consume too much RAM for stable operation
# define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1280) // 40k by default
2019-12-31 10:11:05 +00:00
# endif
2021-09-20 19:22:50 +00:00
/* How much data bytes each segment should max allocate to leave enough space for other segments,
assuming each segment uses the same amount of data . 256 for ESP8266 , 640 for ESP32 . */
2025-04-22 20:37:18 +00:00
# define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / WS2812FX::getMaxSegments())
# define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15)
2021-09-20 19:22:50 +00:00
2019-05-21 22:23:09 +00:00
# define NUM_COLORS 3 /* number of colors per segment */
2025-04-22 20:37:18 +00:00
# define SEGMENT (*strip._currentSegment)
# define SEGENV (*strip._currentSegment)
2024-09-28 16:14:43 +00:00
# define SEGCOLOR(x) Segment::getCurrentColor(x)
2024-05-15 13:34:53 +00:00
# define SEGPALETTE Segment::getCurrentPalette()
2024-09-28 16:14:43 +00:00
# define SEGLEN Segment::vLength()
# define SEG_W Segment::vWidth()
# define SEG_H Segment::vHeight()
2022-07-06 18:41:12 +00:00
# define SPEED_FORMULA_L (5U + (50U*(255U - SEGMENT.speed)) / SEGLEN)
2016-12-17 22:43:07 +00:00
2018-09-04 13:51:38 +00:00
// some common colors
# define RED (uint32_t)0xFF0000
# define GREEN (uint32_t)0x00FF00
# define BLUE (uint32_t)0x0000FF
# define WHITE (uint32_t)0xFFFFFF
# define BLACK (uint32_t)0x000000
# define YELLOW (uint32_t)0xFFFF00
# define CYAN (uint32_t)0x00FFFF
# define MAGENTA (uint32_t)0xFF00FF
# define PURPLE (uint32_t)0x400080
# define ORANGE (uint32_t)0xFF3000
# define PINK (uint32_t)0xFF1493
2024-05-09 22:02:28 +00:00
# define GREY (uint32_t)0x808080
# define GRAY GREY
# define DARKGREY (uint32_t)0x333333
# define DARKGRAY DARKGREY
2018-09-04 13:51:38 +00:00
# define ULTRAWHITE (uint32_t)0xFFFFFFFF
2022-08-02 16:27:32 +00:00
# define DARKSLATEGRAY (uint32_t)0x2F4F4F
2023-09-10 16:52:14 +00:00
# define DARKSLATEGREY DARKSLATEGRAY
// segment options
2022-07-06 11:13:54 +00:00
# define NO_OPTIONS (uint16_t)0x0000
2023-09-10 16:52:14 +00:00
# define TRANSPOSED (uint16_t)0x0100 // rotated 90deg & reversed
# define MIRROR_Y_2D (uint16_t)0x0080
# define REVERSE_Y_2D (uint16_t)0x0040
# define RESET_REQ (uint16_t)0x0020
# define FROZEN (uint16_t)0x0010
2022-07-06 11:13:54 +00:00
# define MIRROR (uint16_t)0x0008
# define SEGMENT_ON (uint16_t)0x0004
# define REVERSE (uint16_t)0x0002
# define SELECTED (uint16_t)0x0001
2016-12-17 22:43:07 +00:00
# define FX_MODE_STATIC 0
# define FX_MODE_BLINK 1
# define FX_MODE_BREATH 2
# define FX_MODE_COLOR_WIPE 3
# define FX_MODE_COLOR_WIPE_RANDOM 4
# define FX_MODE_RANDOM_COLOR 5
2018-09-04 13:51:38 +00:00
# define FX_MODE_COLOR_SWEEP 6
2018-03-31 22:08:50 +00:00
# define FX_MODE_DYNAMIC 7
2016-12-17 22:43:07 +00:00
# define FX_MODE_RAINBOW 8
# define FX_MODE_RAINBOW_CYCLE 9
# define FX_MODE_SCAN 10
2025-04-22 20:37:18 +00:00
# define FX_MODE_DUAL_SCAN 11 // candidate for removal (use Scan)
2016-12-17 22:43:07 +00:00
# define FX_MODE_FADE 12
# define FX_MODE_THEATER_CHASE 13
2025-04-22 20:37:18 +00:00
# define FX_MODE_THEATER_CHASE_RAINBOW 14 // candidate for removal (use Theater)
2016-12-17 22:43:07 +00:00
# define FX_MODE_RUNNING_LIGHTS 15
2019-02-05 20:53:39 +00:00
# define FX_MODE_SAW 16
# define FX_MODE_TWINKLE 17
2019-01-31 22:42:48 +00:00
# define FX_MODE_DISSOLVE 18
2023-01-18 21:56:49 +00:00
# define FX_MODE_DISSOLVE_RANDOM 19 // candidate for removal (use Dissolve with with check 3)
2016-12-17 22:43:07 +00:00
# define FX_MODE_SPARKLE 20
# define FX_MODE_FLASH_SPARKLE 21
# define FX_MODE_HYPER_SPARKLE 22
# define FX_MODE_STROBE 23
# define FX_MODE_STROBE_RAINBOW 24
# define FX_MODE_MULTI_STROBE 25
# define FX_MODE_BLINK_RAINBOW 26
2018-03-18 22:16:53 +00:00
# define FX_MODE_ANDROID 27
2016-12-17 22:43:07 +00:00
# define FX_MODE_CHASE_COLOR 28
# define FX_MODE_CHASE_RANDOM 29
# define FX_MODE_CHASE_RAINBOW 30
# define FX_MODE_CHASE_FLASH 31
# define FX_MODE_CHASE_FLASH_RANDOM 32
# define FX_MODE_CHASE_RAINBOW_WHITE 33
2018-01-10 22:57:58 +00:00
# define FX_MODE_COLORFUL 34
2017-12-13 23:12:02 +00:00
# define FX_MODE_TRAFFIC_LIGHT 35
2016-12-17 22:43:07 +00:00
# define FX_MODE_COLOR_SWEEP_RANDOM 36
2025-04-22 20:37:18 +00:00
# define FX_MODE_RUNNING_COLOR 37 // candidate for removal (use Theater)
2021-01-04 10:11:36 +00:00
# define FX_MODE_AURORA 38
2016-12-17 22:43:07 +00:00
# define FX_MODE_RUNNING_RANDOM 39
# define FX_MODE_LARSON_SCANNER 40
# define FX_MODE_COMET 41
# define FX_MODE_FIREWORKS 42
2019-02-11 22:49:04 +00:00
# define FX_MODE_RAIN 43
2021-12-07 10:03:41 +00:00
# define FX_MODE_TETRIX 44 //was Merry Christmas prior to 0.12.0 (use "Chase 2" with Red/Green)
2016-12-17 22:43:07 +00:00
# define FX_MODE_FIRE_FLICKER 45
2018-03-18 22:16:53 +00:00
# define FX_MODE_GRADIENT 46
# define FX_MODE_LOADING 47
2023-09-05 16:39:51 +00:00
# define FX_MODE_ROLLINGBALLS 48 //was Police before 0.14
2021-12-07 10:03:41 +00:00
# define FX_MODE_FAIRY 49 //was Police All prior to 0.13.0-b6 (use "Two Dots" with Red/Blue and full intensity)
2019-12-04 11:15:12 +00:00
# define FX_MODE_TWO_DOTS 50
2021-12-07 10:03:41 +00:00
# define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity)
2025-04-22 20:37:18 +00:00
# define FX_MODE_RUNNING_DUAL 52 // candidate for removal (use Running)
2025-01-14 18:26:41 +00:00
# define FX_MODE_IMAGE 53
2018-09-04 13:51:38 +00:00
# define FX_MODE_TRICOLOR_CHASE 54
# define FX_MODE_TRICOLOR_WIPE 55
# define FX_MODE_TRICOLOR_FADE 56
# define FX_MODE_LIGHTNING 57
# define FX_MODE_ICU 58
# define FX_MODE_MULTI_COMET 59
2024-02-17 11:58:04 +00:00
# define FX_MODE_DUAL_LARSON_SCANNER 60 // candidate for removal (use Scanner with with check 1)
2018-09-04 13:51:38 +00:00
# define FX_MODE_RANDOM_CHASE 61
# define FX_MODE_OSCILLATE 62
2018-09-10 22:20:12 +00:00
# define FX_MODE_PRIDE_2015 63
# define FX_MODE_JUGGLE 64
# define FX_MODE_PALETTE 65
# define FX_MODE_FIRE_2012 66
2018-09-08 14:21:44 +00:00
# define FX_MODE_COLORWAVES 67
# define FX_MODE_BPM 68
# define FX_MODE_FILLNOISE8 69
# define FX_MODE_NOISE16_1 70
# define FX_MODE_NOISE16_2 71
# define FX_MODE_NOISE16_3 72
# define FX_MODE_NOISE16_4 73
2018-11-04 19:14:23 +00:00
# define FX_MODE_COLORTWINKLE 74
2018-11-07 19:22:05 +00:00
# define FX_MODE_LAKE 75
2018-11-20 20:31:07 +00:00
# define FX_MODE_METEOR 76
2025-04-22 20:37:18 +00:00
//#define FX_MODE_METEOR_SMOOTH 77 // replaced by Meteor
2025-07-12 05:40:18 +00:00
# define FX_MODE_COPY 77
2018-12-02 01:49:05 +00:00
# define FX_MODE_RAILWAY 78
2019-01-31 22:42:48 +00:00
# define FX_MODE_RIPPLE 79
2019-08-30 13:39:34 +00:00
# define FX_MODE_TWINKLEFOX 80
2019-10-01 23:17:26 +00:00
# define FX_MODE_TWINKLECAT 81
# define FX_MODE_HALLOWEEN_EYES 82
2019-11-18 11:29:36 +00:00
# define FX_MODE_STATIC_PATTERN 83
2019-11-29 17:53:01 +00:00
# define FX_MODE_TRI_STATIC_PATTERN 84
2019-12-04 11:15:12 +00:00
# define FX_MODE_SPOTS 85
# define FX_MODE_SPOTS_FADE 86
2019-12-06 00:44:45 +00:00
# define FX_MODE_GLITTER 87
# define FX_MODE_CANDLE 88
2019-12-28 14:43:55 +00:00
# define FX_MODE_STARBURST 89
2020-01-03 11:58:31 +00:00
# define FX_MODE_EXPLODING_FIREWORKS 90
2020-01-03 22:19:40 +00:00
# define FX_MODE_BOUNCINGBALLS 91
# define FX_MODE_SINELON 92
2025-04-22 20:37:18 +00:00
# define FX_MODE_SINELON_DUAL 93 // candidate for removal (use sinelon)
# define FX_MODE_SINELON_RAINBOW 94 // candidate for removal (use sinelon)
2020-01-03 22:19:40 +00:00
# define FX_MODE_POPCORN 95
2020-01-12 14:04:49 +00:00
# define FX_MODE_DRIP 96
2020-01-18 23:06:17 +00:00
# define FX_MODE_PLASMA 97
2020-01-19 12:51:49 +00:00
# define FX_MODE_PERCENT 98
2025-04-22 20:37:18 +00:00
# define FX_MODE_RIPPLE_RAINBOW 99 // candidate for removal (use ripple)
2020-02-17 10:01:05 +00:00
# define FX_MODE_HEARTBEAT 100
2020-03-25 10:17:45 +00:00
# define FX_MODE_PACIFICA 101
2025-04-22 20:37:18 +00:00
# define FX_MODE_CANDLE_MULTI 102 // candidate for removal (use candle with multi select)
2023-01-18 21:56:49 +00:00
# define FX_MODE_SOLID_GLITTER 103 // candidate for removal (use glitter)
2020-06-05 22:57:34 +00:00
# define FX_MODE_SUNRISE 104
# define FX_MODE_PHASED 105
# define FX_MODE_TWINKLEUP 106
# define FX_MODE_NOISEPAL 107
# define FX_MODE_SINEWAVE 108
# define FX_MODE_PHASEDNOISE 109
# define FX_MODE_FLOW 110
2020-06-22 10:30:31 +00:00
# define FX_MODE_CHUNCHUN 111
2020-08-22 18:54:59 +00:00
# define FX_MODE_DANCING_SHADOWS 112
2020-09-26 23:58:21 +00:00
# define FX_MODE_WASHING_MACHINE 113
2024-01-28 14:09:40 +00:00
# define FX_MODE_2DPLASMAROTOZOOM 114 // was Candy Cane prior to 0.14 (use Chase 2)
2020-12-15 12:35:50 +00:00
# define FX_MODE_BLENDS 115
2020-12-22 12:15:57 +00:00
# define FX_MODE_TV_SIMULATOR 116
2023-01-18 21:56:49 +00:00
# define FX_MODE_DYNAMIC_SMOOTH 117 // candidate for removal (check3 in dynamic)
2022-06-21 20:49:45 +00:00
2022-11-14 01:29:59 +00:00
// new 0.14 2D effects
# define FX_MODE_2DSPACESHIPS 118 //gap fill
# define FX_MODE_2DCRAZYBEES 119 //gap fill
# define FX_MODE_2DGHOSTRIDER 120 //gap fill
# define FX_MODE_2DBLOBS 121 //gap fill
# define FX_MODE_2DSCROLLTEXT 122 //gap fill
# define FX_MODE_2DDRIFTROSE 123 //gap fill
2023-04-27 15:31:55 +00:00
# define FX_MODE_2DDISTORTIONWAVES 124 //gap fill
# define FX_MODE_2DSOAP 125 //gap fill
2023-04-28 20:00:35 +00:00
# define FX_MODE_2DOCTOPUS 126 //gap fill
2023-04-29 15:04:16 +00:00
# define FX_MODE_2DWAVINGCELL 127 //gap fill
2022-11-14 01:29:59 +00:00
// WLED-SR effects (SR compatible IDs !!!)
# define FX_MODE_PIXELS 128
# define FX_MODE_PIXELWAVE 129
# define FX_MODE_JUGGLES 130
# define FX_MODE_MATRIPIX 131
# define FX_MODE_GRAVIMETER 132
# define FX_MODE_PLASMOID 133
# define FX_MODE_PUDDLES 134
# define FX_MODE_MIDNOISE 135
# define FX_MODE_NOISEMETER 136
# define FX_MODE_FREQWAVE 137
# define FX_MODE_FREQMATRIX 138
# define FX_MODE_2DGEQ 139
# define FX_MODE_WATERFALL 140
# define FX_MODE_FREQPIXELS 141
# define FX_MODE_BINMAP 142
# define FX_MODE_NOISEFIRE 143
# define FX_MODE_PUDDLEPEAK 144
# define FX_MODE_NOISEMOVE 145
# define FX_MODE_2DNOISE 146
# define FX_MODE_PERLINMOVE 147
# define FX_MODE_RIPPLEPEAK 148
# define FX_MODE_2DFIRENOISE 149
# define FX_MODE_2DSQUAREDSWIRL 150
2024-01-06 16:04:56 +00:00
// #define FX_MODE_2DFIRE2012 151
2022-11-14 01:29:59 +00:00
# define FX_MODE_2DDNA 152
# define FX_MODE_2DMATRIX 153
# define FX_MODE_2DMETABALLS 154
# define FX_MODE_FREQMAP 155
# define FX_MODE_GRAVCENTER 156
# define FX_MODE_GRAVCENTRIC 157
# define FX_MODE_GRAVFREQ 158
# define FX_MODE_DJLIGHT 159
# define FX_MODE_2DFUNKYPLANK 160
2024-01-06 16:04:56 +00:00
//#define FX_MODE_2DCENTERBARS 161
2022-11-14 01:29:59 +00:00
# define FX_MODE_2DPULSER 162
# define FX_MODE_BLURZ 163
# define FX_MODE_2DDRIFT 164
# define FX_MODE_2DWAVERLY 165
# define FX_MODE_2DSUNRADIATION 166
# define FX_MODE_2DCOLOREDBURSTS 167
# define FX_MODE_2DJULIA 168
// #define FX_MODE_2DPOOLNOISE 169 //have been removed in WLED SR in the past because of low mem but should be added back
// #define FX_MODE_2DTWISTER 170 //have been removed in WLED SR in the past because of low mem but should be added back
// #define FX_MODE_2DCAELEMENTATY 171 //have been removed in WLED SR in the past because of low mem but should be added back
# define FX_MODE_2DGAMEOFLIFE 172
# define FX_MODE_2DTARTAN 173
# define FX_MODE_2DPOLARLIGHTS 174
# define FX_MODE_2DSWIRL 175
# define FX_MODE_2DLISSAJOUS 176
# define FX_MODE_2DFRIZZLES 177
# define FX_MODE_2DPLASMABALL 178
# define FX_MODE_FLOWSTRIPE 179
# define FX_MODE_2DHIPHOTIC 180
# define FX_MODE_2DSINDOTS 181
# define FX_MODE_2DDNASPIRAL 182
# define FX_MODE_2DBLACKHOLE 183
# define FX_MODE_WAVESINS 184
# define FX_MODE_ROCKTAVES 185
# define FX_MODE_2DAKEMI 186
2025-04-22 20:37:18 +00:00
Adding Particle System with many new FX (#4506)
* cleanup
* added collision handling back in
update from another commit that got lost
* reformat
* added latest version of functions
this somehow also got lost from an earlier commit
* Update platformio.ini
* updated particle box and firework effects
particle box now is more random in random mode (still a work in progress)
firework is now more configurable by sliders
* added preliminary functions and FX
* added particle attractor, added two new FX but still buggy
particle attractor animation does not work, somthing wrong with pointer allocation, it worked with static variables
* bugfixes, attracot now works
still unknown, why more than 256 particles are needed in memory allocation to not make it crash, but it works for now
* added angle emitter, added fireworks effect using it
* Added saturation to be set for each particle individually
at the expense of more ram usage, animations now have more options for color control (already used in fireworks now)
* bugfixes in impact animation
* added option to use fast color add, may improve performance a little
also fixed a bug in fire animation
* collision detection is now a function plus some improvements & fixes
* improved collision efficiency
improved efficiency for stackup (pushback), added code to correctly determine direction if particles meed (probably overkill but now its there)
* added fix for piling oscillations
untested, need to verify it works
* Improved collision handling (faster, less oscillations), changed variables to 32bit for faster calculation
32bit variables are faster on ESP32, so use them whenever a variable is used a lot, it saves one instruction per access.
* removed option for fastcolor add
it made very little difference in performance, but for ESP8266 it may matter so it is set permanently there. graphically the difference is also very small (sometimes a particle gets brighter or less saturated)
* Fixed some bugs in particle system, runs much smoother now
also tweaked some of the FX
* Bugfix in particle push, now piling is working again
particle pile-up did not work correctly, now fixed
* changed particle pile demo into waterfall plus some tweaks
* lots of bugfixes
* updated particle attractor animation parameters and added more user options to perlin noise
* removed TODOs
* added particle WrapUpdate function, added spray FX, some bugfixes
* fixed touch buttons for ESP32 S2 and S3
touch is implemented differently on S2 and S3, these changes make touch buttons work on S2 and S3
* some tuning for touch buttons on S2/S3
now better fits the default threshold value of 32
* updated rotating particle spray with more user options
* chaned rotating spray default parameters
* add todo
* Revert "some tuning for touch buttons on S2/S3"
This reverts commit d21ad8e7d1651a96f879d43ef1146a72a6ed8271.
* Revert "fixed touch buttons for ESP32 S2 and S3"
This reverts commit 09041551862361cd8c7444ca25403f5f96a9077b.
* removed comments, added comments
* cleanup
-removed wrap_update function, now integrated into move_update
-added more 'out of bounds' checking in fire functions, may speed it up a little
* cleanup session
-removed particle box 'rocking boat' (buggy) and replaced with random sloshing.
-removed comments
-changed some variables into 32bit for speed boost on ESP32
-added link to KB at the top of FX.cpp
* cleanup
removed / added comments
* added particle GEQ effect (untested)
* Particle GEQ fixes, it now actually works
* GEQ FX parameter tuning
* added rotating GEQ, work in progress
-animation works but sliders are too sensitive. need to adjust the ranges
* FX update
- changed firework exhaust to low saturation
- updated rotating particle spray animation
* Cleanup & Bugfixes plus major improvements for ESP8266
-added particle reductions for ESP8266 for all FX
-Removed collisions from Particle Perlin Noise FX, slows things down and does not contribute to a better effect experience
-lots of optimizations for ESP8266, all FX now work (at least on 160MHz but still slow)
-Some bugfixes
-removed unused variables to make compiler happy
* Particle FX Rename, default parameter tuning, bugfix
-Now shorter names, 'PS' in front to filter the list
-Tuned default parameters to make them look better by default
-Bugfix in particle system (removed duplicate application of velocity)
-reduced PS fire RAM usage (less particles, less base flames, no noticeable difference)
-some variable renaming
* slight speed improvements in fire, like 1-2FPS
* Big update: lots of little fixes and big speed boost on fire animation
-fixed fire burning more on the left side
-fixed crash in particle attractor
-added many improvements for ESP8266
-improved particle rendering efficiency
-efficiency improvements in general
-changed the way fire is rendered, now more than 2x faster
-re-tuned fire to new rendering, also seperately tuned it for ESP8266
-changed all random8() to random16() as it runs faster on ESPs
-some reformating
-some renaming of effect stuff
-fine tuning on falling particle effect
-improvements to collision handling (faster and better)
-added a (temporary) function for speed tests, will be removed again
* bugfix
* updated PS Fireworks with many changes and fine-tuning of parameters
-removed spiral explosions
-added more versatility to circular explosions
-removed user selectable amount of rockets
-tuned explosion size of circular explosions to match random explosions (more or less, may need improvement)
-changed order of sliders in volcano animation
* put particle system in a class. work in progress.
another huge update to the particle system.
went through the whole code, rewrote many of the functions. many improvements over the previous code. fixed many bugs (and even an ancient one in rendering function). spent many hours optimizing the code for speed and usability.
still a work in progress, debugging is ongoing. more updates to come.
* many (many!) bugfixes, added fire FX back in (and improved it a lot) added local renderbuffer for huge speed boost
-lots of bugfixes in Particle system
-added local rendering buffer (renders to buffer in heap)
-added fast and accurate color-add function
-bugfixes in render function
-added improved 'sticky' particles in collision (unfinished business)
-added ballpit animation back
-lots of tweaks to fire FX and fire rendering functions, looks even better now (still unfinished)
-added palette render option to fire
still many debug print outputs around, needs cleanup at one point
* More Bugfixes, more converted FX
* more bugfixes, some animation tuning, added volcano back in
- fixed animation transitions with proper pointer setting in each FX call
- added color by age setting to particle system
- maybe fixed collision having a tendency to go to the left
- fixed bugs in fireworks FX
- added fire spread width as a slider
- changed max number of particles and sprays based on some ram calculations
- some other random fixes
* updated fire, added some functions to PS, ported attractor FX
- added turbulance to fire (after hours of fine-tuning) it now looks even more awesome
- added attractor animation back in and improved it with more functionality
- fixed the attractor function in the PS
- renamed FX: 'candy' is now called 'vortex'
- added new force function to apply a force immediately (and handle the timing in the FX)
- added update function to PS for size update to handle dynamic segment size change
- made waterfall width dynamic on segment width
- removed some debug stuff
- added #defines for maximum number of particles/sprays
- updated fire parameter to make it look better on ESP8266
- some little bugfixes
* another huge update, many improvements, fine-tune collision, fire and some other FX
-removed classic fire render as palette now looks much better
-tweaked fire parameters to more awesome
-added (optional) turbulence to fire using perlin-noise
-ported spray FX to use PS-class
-now definitely fixed asymmetrical collision issue: do not use bitshifts on negative numbers!
-changed piling behaviour of particles, full rework. looks way more natural now and works much better
-changed bouncing behavour: they now bounce at full diameter, making them stay fully in frame when laying on the floor
-replaced all relevant bitshifts with divisions for higher accuracy throughout the PS
-added new modes to particle box FX
-changed a lot of FX parameters (finetuning)
-changed all config strings to proper settings (matrix only)
-fixed newly introduced bugs
-added speedup/slowdown to vortex FX (aka candy, aka rotating sprays)
-some renaming
-fixed bugs… lots of bugs
-merged rendering functions, removed obsolete stuff
* Fixed Speed limit
limiting speed was incorrect, leading to overflows. fixed this.
also fixed bugs in GEQ, removed some debug stuff, added FPS limit to fire (just en experiment)
* work in progress, added motion blur and line attracto (non working)
* work in progress, added test function to increase particle size, also added wobbling test
* added more tests, non compiling at the moment
* in the middle of fixing FX to use new PS functions
* debugging going on
* bugfix in wrap function and firwork FX
* added local render blurring, boosting FPS, work in progress
- changed fast-add function to use pointers
- added fast-scaling function
- added simple (but fast) 2D blurring function
test shows that local blurring of full frame is almost double the speed (40FPS now is 80FPS).
lots of comments still there
* Bugfixes, improvements and added wall roughness setting
- fixed bug in PS fuzzy noise which made it asymmetric for some reason, seems to work better now
- added particle size option to attractor but had to remove speed setting (now fixed emit speed)
- some parameter tuning of FX
- improvements to code size in render function
- added smear option to blurring (not tested much, may be buggy without smear)
- speed improvement to caldForce_dv, added zero checking.
* removed zero inits
- removed zero initialisations in FX, segment.data is set to zero by alloc function
* added individual size particle rendering plus some fixes
- advanced particles can now be rendered to individual sizes. It is computationally intensive but it works well for up to 15 very large particles and more smaller ones
- added collision handling for individual sizes (walls and collisions)
- fixed bugs in particlebox
- fixed fire not transitioning properly (flickering) when frame skip is active
- removed 'wraparound' function as it can easily be done by casting to an unsigned and then modulo
- fixed ballpit particles wandering left and right very fast if wrapX is set
* Fixed some nasty memory bugs, fixed some FX parameters
- fixed memory alignment bug in PS pointer assignment by making sure only multiples of 4 are allowed for particles and sources
- added saturation back to particle struct, as it was aligned to 10 bytes anyway.
- fixed a bug where a null pointer could be accessed
- fixed rendering out of frame particles if buffer allocation failed
- improvements on ESP8266
* Replaced Ghost Rider FX with PS version
- new FX is kept close to original animation but added more user settings
* added walls to ghostride, fixed some bugs
* added 'perpetual' flag to particles
* Fixed another memory / pointer bug, but there is still one left...
-also some minor fixes
* Found and fixed crashes, it was wrongly assigned pointers
* Added advanced particle size control and new Blob FX
- advanced size control allows for growing, shrinking, wobbling
- render function updated to support asymmetric rendering
- various code improvements and bugfixes
- some FX parameter tuning
- bugfix: removed sli() sei() calls in render function that caused random flickering on S3/C3 (may add that back in but only for ESP8266 to reduce fragmentation)
- removed some debug / test stuff
* code cleanup, removed some unused stuff
* bugfix, sprayEmit() would not return and get stuck
- forgot default return value...
* remove esp_random() as it is not supported on ESP8266
* small bugfix for ESP32, cleanup / reformatting
* added WLED_DISABLE_PARTICLESYSTEM option, fixed volcano movement
use '-D WLED_DISABLE_PARTICLESYSTEM' to disable compiling
* a line got lost in the last commit
* - added WLED_DISABLE_PARTICLESYSTEM option & cleanup & bugfixes
- cleanup / reformatting
- fixed volcano movement
- small bugfix for ESP32 (random() does not work, using random16() )
* Added PS source option to emit more than one particle, addes AR to Blobs and Spray
* added center GEQ back in, changed AR behaviour of spray a little
center GEQ is a mix between the PS equalizer and vortex, tuned for AR. some more tuning may be needed, it can probably be extended and improved a little.
* Bugfix and minor improvements
- fixed bug in center GEQ
- added '2D washing machine' mode for particle box
- improved color-change rate in ghostrider
- added AR to attractor (experimental, may remove again)
* hacked in a 1D port of the 2D PS, untested code
* fixed first bugs in 1D system, added test FX
* fixed bug in wrapping (also was wrong for 2D system)
* fixed collisions, added bouncing ball replacement (work in progress)
* replaced more FX, some tweaks to 1D PS
- changed virtual particle size from 64 to 32, making them able to move faster
- added 'rolling balls' option to bouncing balls (i.e. no gravity plus some tweaks)
- added dancing shadows with PS (work in progress)
- temporarily removed native FX: bouncing balls, rolling balls, popcorn, dancing shadows
-and of course some bugfixes
* updated dancing shadows to more closely mimic original
* added drip FX, added #ifdefs, removed some common functions
#ifdefs to individually disable 1D and 2D system.
* fixed compile issue, removed replaced FX (again)
* added Fireworks1D replacement (unfinished)
also fixed a bug in `applyForce()` using uninitialized variable.
* added sparkler and hourglass (both work in progress) tried fixing 1D collisions
* many improvements in 1D collisions (fine tuned), hour glass FX is almost done
spent A LOT of time in fine-tuning collisions for best stacking without collipsing, ringing, oscillations or particle flips. still not perfect but probably as good as it can be with the limited time-resolution
* many bugfixes in PS and FX
* minor FX adjustments
* Improved 1D collisions, added 2 new 1D FX (work in progress)
* bugfixes
* added 'color by position' as a PS setting
-made settings struct for 1D and 2D version to be different
-added setting 'color by position' as that is used by multiple FX now
* added large size rendering to 1D PS, work in progress
* bugfix (forgot to free memory)
also: made random size a permanent option in 1D fireworks as it looks kind of cool
* Added PS based Chase, fixed some bugs
* minor update
* two new FX: Starburst and 1D GEQ
* Added more advanced (and proper) size handling in collisions, work in progress
- copied and adapted some stuff from 2D system (out of bounds size rendering, dynamic collision detection distance, dynamic wall bounce distance)
* fixed some parameters in 1D FX
* added #ifndef to disable FX replaced by PS
- define DISABLE_1D_PS_REPLACEMENTS or DISABLE_2D_PS_REPLACEMENTS
* bugfixes
* default parameter change
* explicit cast to fix compile error
* Bugfixes
* added color-waves to PS chase, some parameter tuning plus bugfixes
* FX update and bugfixes
- fixed wall collisions on larger particle sizes
- update to bouncing balls:
- added size setting
- added proper updating on parameter change
- bugfixes
added support for 'colorwaves' and 'pride' to PS Chase to save on code size. currently broken...
* minor update to rolling balls, fixed stuff in Chase, pride option still not working
* update on 'pride' now working again but needs finetuning
* SEGMENT -> SEGENV on data, aux0, aux1, step
also removed debug outputs
* added pride and colorwaves to 1D replacement list
* removed unused variables
* added variable to set number of particles if not all are required (saves ram) also fixed a nasty render bug
* added preliminary 1D fire function, unfinished
* added fractal FX test, fixed bugs in emit function
* tweaked 1D fire a little, still work in progress
* minor tuning on 1D fire to avoid 'oscillation' at start
* improved 1D particle fire, much more natural now.
* updated 2D fire, fixed init bug
- source init was wrong making fire init weirdly
- changed parameters on 2D fire making it look better and improving flame height for larger setups
* fixed 'nervours' fire
* slight improvements and some cleanup
* removed douplicate code for fire emit (tradeoff for some speed), removed unfinished fractal FX
- with the duplicate code removed, the fire particle emits are a bit slower but it saves on code. it is not really noticeable, its slower by about 1FPS
* Re-license from MIT to EUPL
* Started cleanup, speed improvement to rendering, renamed class
- removed 'smar' parameter in blur functions as smear is always used
- improved particle rendering (passing by reference, passing wrap parameters for faster access)
- renamed class to ParticleSystem2D
- removed some whitespaces
- some reformating, removed some comments
- minor tweaks
- removed non-working line-attractor function
* Optimization and bugfixes
- added out of bounds checking function
- fixed rendering at boundaries
- various small changes and cleanup
- bugfixes with comparing ints of different signeness
- fixed bounce radius
* Cleanup, bugfixes, speed improvements, refactoring
- lots of code refactoring / reformating
- fixed bug in fire particle update and improved speed a bit
- refactoring of pixel rendering
- removed 2D buffers, replaced with 1D buffer for faster access
- bugfix in blur2D
- many small improvements to 2D system
* Refactoring and cleanup of 1D PS, removed debug printouts
- code reformating for consistency and readability
- replaced "'?" operator with min / max (produces the same code, more readable)
- minor changes for speed (random16 used, can later be replaced with hardware random function)
- renamed PS Equalizer to PS 2D GEQ
* Cleanup and some refactoring of particle FX
- moved 2D / length check to PS initi
- code reformating
- removed some comments
* missed a spot
* minor tweaks to fast_color_add()
* Work in progress: update to fireworks, needs more testing & finetuning
also bugs fixed and some minor cleanup
* Work in Progress: added particle memory manager for transitions
- uses only one, persistant buffer to render all present particle systems
- Buffer for particles is shared for one segment (may allow interacitng systems in the future)
- updated some of the FX to handle the new transfer, 1D FX still not done
- updated parameters for particle impact FX
* work in progress: lots of changes & fixes, transitions now work correctly in 2D
- still fragile code with lots of cleanup to do
* added transitions for big-size rendering
- transitions now work with FX that use global large size rendering. this is done by handling the buffer correctly. to avoid creating a second buffer, it is transferred back and forth to the segment. this is a bit slow but a compromise solution.
- multiple segment handling is still untested
* speed improvement to fast_color_add, added preliminary buffer transfer function
* merge fixes
* bugfix in setCurrentPalette, corrected order of 2D memory allocation, increased max particles/sources
- fixed timing for vortex
* fixed particle buffer handover, added 2D blur option, increased particle limits, various fixes
- fixed bug in memory watchdog, now works and also works when freezing segments
- fixed PS Box to work again with particle handover
- added smear blurring to waterfall
- added smear blurring to vortex, fixed color distribution, removed random color distribution option
- replaced all random() calls with hw_random()
- transitions now work but only if FX transitions are enabled and not when chaning segment size
* implemented correct 1D<->2D buffer handover+bugfixes
work in progress
* added smear to fuzzy noise, some cleanup
* added blurring option to PS 2D fireworks, work in progress in finding that nasty bug that crashes all
* BUGFIX: finally found and squased the memory bug, no more random crashes
also: removed debug outputs and minor cleanup
* minor cleanup and fixed a bug
1D system had a lot of crashes, some out of bounds memory issue. fixed it but I have no idea which change did that, maybe the order in 1D initialization
* BUGFIX: out of bounds checking was wrong, leading to crashes
* better handling of used particles in transitions
for FX that do not use all particles, transitions were constantly shifting the pointer, resulting in newly generated particles and weird particle flickering, this is not fixed by keeping the pointer constant once the number of used particles is reached.
* improved particle transition for low-count FX, updated 1D FX
now most 1D FX work again, still needs some fine-tuning
* Rework on Fireworks 1D, some minor fixes
- fireworks 1D now matches as closely as possible to the old FX
still not identical but as good as it gets.
* bugfix in PS Chase, increased brightness of 1D fireworks
* replaced sin16/cos16 with new versions
* bugfixes
* fixed hourglass init, rearranged PS FX init
* speed optimization
- moved out of bounds calculation to proper spot
- removed repeated allocation attempts if initial buffer alloc fails
* Added Sonic Stream FX, some cleanup, bugfix in emitter
* changed TTL to brightness calculation, added collision binning
- brightness is now doubled as some FX were really dim due to low TTL
- added binning in x-direction giving a huge speed advantage on larger matrix sizes
* collision binning bugfix, made particles less sticky, update to waterfall
- updated waterfall intensity and blurring
* WIP: fixed 1D system for over 1000 pixels, added collision binning for 1D
- making x coordinate 32bit allows for larger strips but uses a lot of ram due to struct memory alignment (12bytes instead of 8 bytes), this needs some more work to properly fix.
- adding collision binning significantly speeds things up, about a factor of 2 on most FX using collision
- there are still some bugs in FX or 1D memory handling (or both) on large setups
* moved particle flags to seperate array to save on RAM, refactoring
- moving the flags optimizes ram alignment, saving memory for each particle
- changed lots of parameters to `const`
- moved fire intensity to a variable instead of passing it to every render() call
- changed passing pointers to passing reference where possible
- saves a total of 340 bytes of flash
* removed todos after some checks, minor improvements
* inverted y axis in 2D render, 1D collision improvements, cleanup and fixes
- inverting the y-axis in the buffer instead of in buffer transfer fixes the FX flipping when transitiononing 1D<->2D
- improved particle binning for collisions
- added hard-pushing also when not using gravity so piles close to an edge dont collapse
- some improvments to "balance" FX
- renaming and cleanup
* FX fixes and minor tweaks
* increased min rockets
* fixed #ifdefs
* another fix
* revert unnecessary changes to base code
* merge fix
* minor tweak
* tweaked sparkler FX, some cleanup
* Fix in volcano FX, changed blurring of volcano and waterfall
* added ifdefs
* minor tweaks, increased 1D minsurfacehardness
* improved sparkler FX, made overlay possible (1D not yet), cleanup
* cleanup, now using new hsv2rgb/rgb2hsv, add overlay rendering to 1D
- new hsv2rgb is a tiny bit faster
- removed redundant code (using transferBuffer instead)
- tweked parameters in vortex, removed unneeded slider defaults
* fix for non or partially overlapping segments
- can not use overlay rendering if no segment clears the buffer, it will all add up to white eventually
- now additive transfer i.e. overlay mode is only activated if the segment is fully overlapping an underlying segment
* change got lost...
* increased sparkler intensity, some cleanup
* replaced #ifdefs, removed 1D replacements that have 2D version, removed notes
* cleanup, improvements to PS bouncing ball, replaced multicomet
- bouncing balls is now named pinball and has settings/parameters updated to be a replacement for multicomet
* cleanup, improvements, bugfixes
- large size rendering now works without framebuffer
- background adding is now done on buffer (if avilable) instead of segment
- fixed overflow bug in 2D large particle rendering (it worked only for powers of 2 size)
* potential bugfix, compiler warning fix
* removed colorwaves and pride option from chase (not worthy replacements)
* updated #defines, removed PS from 1M and 2M builds
* Adding Particle System and PS FX
Adding all 187 commits from particle system dev branch
* reverted some accidental changes
* reverted some accidental changes
* merge fixes
* changed replacement: multicomet instead of comet (lighthouse)
* changed replacement: multicomet instead of comet (lighthouse)
* disable 2D PS for ESP8266, some cleanup, improved pinball FX parameters, bugfixes
* Improved collision binning for large particles, improved pinball FX
* improved speed handling in pinball FX - rolling
* disable 2D PS for ESP8266, some cleanup, improved pinball FX parameters, bugfixes
* improved hourglass: millis instead of frame timing, better stacking. and cleanup.
* revert whitespaces
* simplified 1D collisions, improved binning for larger particles
- ran a lot of experiments with collisions in 1D, the new much simpler approach seems to be a good compromise with regards to stacking and normal collisions.
* Improved collision binning for large particles, improved pinball FX
* improved speed handling in pinball FX - rolling
* improved hourglass: millis instead of frame timing, better stacking. and cleanup.
* revert whitespaces
* prohibit use of 1D and 2D system simultaneously on ESP8266
* prohibit use of 1D and 2D system simultaneously on ESP8266
* update to handle blending styles
* fixed bugs, improved new transition handling
* updated 1D system to work with new transitions, replaced NULL with nullptr
* merge fixes
* added single pixel particle rendering for 2D system, adjusted FX to work with it
* improved collisions in 1D and 2D, some bugfixes in radius calculation, minor tweaks
- collisions are now also velocity based in 1D, there was a bug that prevented that from working well (wrong collision distance calculation)
- improvement and bugfix in 2D collision distance calculation
- added distance based pushing in 2D (instead of only using the dotproduct)
the combination of improved distance calculation and proper pushing make collisions a lot better in all tested FX
* minor fix
* fixed overlay detection, checking for partial overlay
if a PS FX is partially overlapping, it will render in overlay mode
* better blur range in PS Firworks
* minor code consolidation
* updated 1D collisions (yet again), improved 2D collision speed
- slight improvement to 2D collision code efficiency
- added faster "division" to C3/ESP8266 by using a right shift trick (biasing towards 0 also for negative numbers by applying proper rounding)
* minor tweak in PS balance
2025-02-17 17:32:12 +00:00
# define FX_MODE_PARTICLEVOLCANO 187
# define FX_MODE_PARTICLEFIRE 188
# define FX_MODE_PARTICLEFIREWORKS 189
# define FX_MODE_PARTICLEVORTEX 190
# define FX_MODE_PARTICLEPERLIN 191
# define FX_MODE_PARTICLEPIT 192
# define FX_MODE_PARTICLEBOX 193
# define FX_MODE_PARTICLEATTRACTOR 194
# define FX_MODE_PARTICLEIMPACT 195
# define FX_MODE_PARTICLEWATERFALL 196
# define FX_MODE_PARTICLESPRAY 197
# define FX_MODE_PARTICLESGEQ 198
# define FX_MODE_PARTICLECENTERGEQ 199
# define FX_MODE_PARTICLEGHOSTRIDER 200
# define FX_MODE_PARTICLEBLOBS 201
# define FX_MODE_PSDRIP 202
# define FX_MODE_PSPINBALL 203
# define FX_MODE_PSDANCINGSHADOWS 204
# define FX_MODE_PSFIREWORKS1D 205
# define FX_MODE_PSSPARKLER 206
# define FX_MODE_PSHOURGLASS 207
# define FX_MODE_PS1DSPRAY 208
# define FX_MODE_PSBALANCE 209
# define FX_MODE_PSCHASE 210
# define FX_MODE_PSSTARBURST 211
# define FX_MODE_PS1DGEQ 212
# define FX_MODE_PSFIRE1D 213
# define FX_MODE_PS1DSONICSTREAM 214
2025-04-15 17:07:21 +00:00
# define FX_MODE_PS1DSONICBOOM 215
# define FX_MODE_PS1DSPRINGY 216
2025-05-09 16:53:16 +00:00
# define FX_MODE_PARTICLEGALAXY 217
# define MODE_COUNT 218
2018-01-09 22:13:29 +00:00
2024-04-03 16:38:06 +00:00
2025-01-14 21:39:20 +00:00
# define BLEND_STYLE_FADE 0x00 // universal
# define BLEND_STYLE_FAIRY_DUST 0x01 // universal
# define BLEND_STYLE_SWIPE_RIGHT 0x02 // 1D or 2D
# define BLEND_STYLE_SWIPE_LEFT 0x03 // 1D or 2D
2025-04-22 20:37:18 +00:00
# define BLEND_STYLE_OUTSIDE_IN 0x04 // 1D or 2D
2025-01-14 21:39:20 +00:00
# define BLEND_STYLE_INSIDE_OUT 0x05 // 1D or 2D
# define BLEND_STYLE_SWIPE_UP 0x06 // 2D
# define BLEND_STYLE_SWIPE_DOWN 0x07 // 2D
# define BLEND_STYLE_OPEN_H 0x08 // 2D
# define BLEND_STYLE_OPEN_V 0x09 // 2D
2025-04-22 20:37:18 +00:00
# define BLEND_STYLE_SWIPE_TL 0x0A // 2D
# define BLEND_STYLE_SWIPE_TR 0x0B // 2D
# define BLEND_STYLE_SWIPE_BR 0x0C // 2D
# define BLEND_STYLE_SWIPE_BL 0x0D // 2D
# define BLEND_STYLE_CIRCULAR_OUT 0x0E // 2D
# define BLEND_STYLE_CIRCULAR_IN 0x0F // 2D
2025-01-14 21:39:20 +00:00
// as there are many push variants to optimise if statements they are groupped together
# define BLEND_STYLE_PUSH_RIGHT 0x10 // 1D or 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_LEFT 0x11 // 1D or 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_UP 0x12 // 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_DOWN 0x13 // 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_TL 0x14 // 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_TR 0x15 // 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_BR 0x16 // 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_BL 0x17 // 2D (& 0b00010000)
# define BLEND_STYLE_PUSH_MASK 0x10
2024-07-30 15:26:50 +00:00
# define BLEND_STYLE_COUNT 18
2024-04-03 16:38:06 +00:00
2022-07-14 11:22:34 +00:00
typedef enum mapping1D2D {
M12_Pixels = 0 ,
2022-08-25 19:57:43 +00:00
M12_pBar = 1 ,
M12_pArc = 2 ,
2024-05-07 22:04:29 +00:00
M12_pCorner = 3 ,
M12_sPinwheel = 4
2022-07-14 11:22:34 +00:00
} mapping1D2D_t ;
2025-04-22 20:37:18 +00:00
class WS2812FX ;
// segment, 76 bytes
class Segment {
2022-07-17 13:58:41 +00:00
public :
2025-04-22 20:37:18 +00:00
uint32_t colors [ NUM_COLORS ] ;
uint16_t start ; // start index / start X coordinate 2D (left)
uint16_t stop ; // stop index / stop X coordinate 2D (right); segment is invalid if stop == 0
uint16_t startY ; // start Y coodrinate 2D (top); there should be no more than 255 rows
uint16_t stopY ; // stop Y coordinate 2D (bottom); there should be no more than 255 rows
uint16_t offset ; // offset for 1D effects (effect will wrap around)
2022-07-17 13:58:41 +00:00
union {
2025-04-22 20:37:18 +00:00
mutable uint16_t options ; //bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
2022-07-17 13:58:41 +00:00
struct {
2025-04-22 20:37:18 +00:00
mutable bool selected : 1 ; // 0 : selected
bool reverse : 1 ; // 1 : reversed
mutable bool on : 1 ; // 2 : is On
bool mirror : 1 ; // 3 : mirrored
mutable bool freeze : 1 ; // 4 : paused/frozen
mutable bool reset : 1 ; // 5 : indicates that Segment runtime requires reset
bool reverse_y : 1 ; // 6 : reversed Y (2D)
bool mirror_y : 1 ; // 7 : mirrored Y (2D)
bool transpose : 1 ; // 8 : transposed (2D, swapped X & Y)
uint8_t map1D2D : 3 ; // 9-11 : mapping for 1D effect on 2D (0-use as strip, 1-expand vertically, 2-circular/arc, 3-rectangular/corner, ...)
uint8_t soundSim : 2 ; // 12-13 : 0-3 sound simulation types ("soft" & "hard" or "on"/"off")
mutable uint8_t set : 2 ; // 14-15 : 0-3 UI segment sets/groups
2022-07-17 13:58:41 +00:00
} ;
} ;
uint8_t grouping , spacing ;
2025-04-22 20:37:18 +00:00
uint8_t opacity , cct ; // 0==1900K, 255==10091K
// effect data
uint8_t mode ;
uint8_t palette ;
uint8_t speed ;
uint8_t intensity ;
uint8_t custom1 , custom2 ; // custom FX parameters/sliders
2022-08-12 15:58:20 +00:00
struct {
2022-08-19 19:14:49 +00:00
uint8_t custom3 : 5 ; // reduced range slider (0-31)
bool check1 : 1 ; // checkmark 1
bool check2 : 1 ; // checkmark 2
bool check3 : 1 ; // checkmark 3
2025-04-22 20:37:18 +00:00
//uint8_t blendMode : 4; // segment blending modes: top, bottom, add, subtract, difference, multiply, divide, lighten, darken, screen, overlay, hardlight, softlight, dodge, burn
2022-08-12 15:58:20 +00:00
} ;
2025-04-22 20:37:18 +00:00
uint8_t blendMode ; // segment blending modes: top, bottom, add, subtract, difference, multiply, divide, lighten, darken, screen, overlay, hardlight, softlight, dodge, burn
char * name ; // segment name
2022-07-17 13:58:41 +00:00
// runtime data
2025-04-22 20:37:18 +00:00
mutable unsigned long next_time ; // millis() of next update
mutable uint32_t step ; // custom "step" var
mutable uint32_t call ; // call counter
mutable uint16_t aux0 ; // custom var
mutable uint16_t aux1 ; // custom var
2023-07-12 18:52:34 +00:00
byte * data ; // effect data pointer
2022-07-17 13:58:41 +00:00
2025-04-22 20:37:18 +00:00
static uint16_t maxWidth , maxHeight ; // these define matrix width & height (max. segment dimensions)
2023-08-05 11:50:08 +00:00
2022-07-12 16:10:07 +00:00
private :
2025-04-22 20:37:18 +00:00
uint32_t * pixels ; // pixel data
unsigned _dataLen ;
uint8_t _default_palette ; // palette number that gets assigned to pal0
2022-07-28 21:19:58 +00:00
union {
2025-04-22 20:37:18 +00:00
mutable uint8_t _capabilities ; // determines segment capabilities in terms of what is available: RGB, W, CCT, manual W, etc.
2022-07-28 21:19:58 +00:00
struct {
bool _isRGB : 1 ;
bool _hasW : 1 ;
bool _isCCT : 1 ;
bool _manualW : 1 ;
} ;
} ;
2025-04-22 20:37:18 +00:00
// static variables are use to speed up effect calculations by stashing common pre-calculated values
static unsigned _usedSegmentData ; // amount of data used by all segments
static unsigned _vLength ; // 1D dimension used for current effect
static unsigned _vWidth , _vHeight ; // 2D dimensions used for current effect
static uint32_t _currentColors [ NUM_COLORS ] ; // colors used for current effect (faster access from effect functions)
2024-05-15 13:34:53 +00:00
static CRGBPalette16 _currentPalette ; // palette used for current effect (includes transition, used in color_from_palette())
2023-08-05 19:01:06 +00:00
static CRGBPalette16 _randomPalette ; // actual random palette
static CRGBPalette16 _newRandomPalette ; // target random palette
2025-04-22 20:37:18 +00:00
static uint16_t _lastPaletteChange ; // last random palette change time (in seconds)
static uint16_t _nextPaletteBlend ; // next due time for random palette morph (in millis())
2023-08-05 19:01:06 +00:00
static bool _modeBlend ; // mode/effect blending semaphore
2025-04-22 20:37:18 +00:00
// clipping rectangle used for blending
static uint16_t _clipStart , _clipStop ;
static uint8_t _clipStartY , _clipStopY ;
2023-08-03 20:28:53 +00:00
2025-04-22 20:37:18 +00:00
// transition data, holds values during transition (76 bytes/28 bytes)
2022-07-30 12:50:11 +00:00
struct Transition {
2025-04-22 20:37:18 +00:00
Segment * _oldSegment ; // previous segment environment (may be nullptr if effect did not change)
unsigned long _start ; // must accommodate millis()
uint32_t _colors [ NUM_COLORS ] ; // current colors
# ifndef WLED_SAVE_RAM
CRGBPalette16 _palT ; // temporary palette (slowly being morphed from old to new)
2023-09-02 18:20:51 +00:00
# endif
2025-04-22 20:37:18 +00:00
uint16_t _dur ; // duration of transition in ms
uint16_t _progress ; // transition progress (0-65535); pre-calculated from _start & _dur in updateTransitionProgress()
uint8_t _prevPaletteBlends ; // number of previous palette blends (there are max 255 blends possible)
uint8_t _palette , _bri , _cct ; // palette ID, brightness and CCT at the start of transition (brightness will be 0 if segment was off)
2022-09-06 19:47:50 +00:00
Transition ( uint16_t dur = 750 )
2025-04-22 20:37:18 +00:00
: _oldSegment ( nullptr )
, _start ( millis ( ) )
, _colors { 0 , 0 , 0 }
# ifndef WLED_SAVE_RAM
, _palT ( CRGBPalette16 ( CRGB : : Black ) )
# endif
, _dur ( dur )
, _progress ( 0 )
, _prevPaletteBlends ( 0 )
, _palette ( 0 )
, _bri ( 0 )
, _cct ( 0 )
2022-09-06 19:47:50 +00:00
{ }
2025-04-22 20:37:18 +00:00
~ Transition ( ) {
//DEBUGFX_PRINTF_P(PSTR("-- Destroying transition: %p\n"), this);
if ( _oldSegment ) delete _oldSegment ;
}
2022-08-31 12:24:02 +00:00
} * _t ;
2022-07-17 13:58:41 +00:00
2025-04-22 20:37:18 +00:00
protected :
2024-10-03 19:19:34 +00:00
2025-04-22 20:37:18 +00:00
inline static unsigned getUsedSegmentData ( ) { return Segment : : _usedSegmentData ; }
inline static void addUsedSegmentData ( int len ) { Segment : : _usedSegmentData + = len ; }
2022-07-17 13:58:41 +00:00
2025-04-22 20:37:18 +00:00
inline uint32_t * getPixels ( ) const { return pixels ; }
inline void setPixelColorRaw ( unsigned i , uint32_t c ) const { pixels [ i ] = c ; }
inline uint32_t getPixelColorRaw ( unsigned i ) const { return pixels [ i ] ; } ;
# ifndef WLED_DISABLE_2D
inline void setPixelColorXYRaw ( unsigned x , unsigned y , uint32_t c ) const { auto XY = [ ] ( unsigned X , unsigned Y ) { return X + Y * Segment : : vWidth ( ) ; } ; pixels [ XY ( x , y ) ] = c ; }
inline uint32_t getPixelColorXYRaw ( unsigned x , unsigned y ) const { auto XY = [ ] ( unsigned X , unsigned Y ) { return X + Y * Segment : : vWidth ( ) ; } ; return pixels [ XY ( x , y ) ] ; } ;
# endif
void resetIfRequired ( ) ; // sets all SEGENV variables to 0 and clears data buffer
CRGBPalette16 & loadPalette ( CRGBPalette16 & tgt , uint8_t pal ) ;
// transition functions
void stopTransition ( ) ; // ends transition mode by destroying transition structure (does nothing if not in transition)
void updateTransitionProgress ( ) const ; // sets transition progress (0-65535) based on time passed since transition start
inline void handleTransition ( ) {
updateTransitionProgress ( ) ;
if ( isInTransition ( ) & & progress ( ) = = 0xFFFFU ) stopTransition ( ) ;
2022-07-19 20:14:46 +00:00
}
2025-04-22 20:37:18 +00:00
inline uint16_t progress ( ) const { return isInTransition ( ) ? _t - > _progress : 0xFFFFU ; } // relies on handleTransition()/updateTransitionProgress() to update progression variable
inline Segment * getOldSegment ( ) const { return isInTransition ( ) ? _t - > _oldSegment : nullptr ; }
inline static void modeBlend ( bool blend ) { Segment : : _modeBlend = blend ; }
inline static void setClippingRect ( int startX , int stopX , int startY = 0 , int stopY = 1 ) { _clipStart = startX ; _clipStop = stopX ; _clipStartY = startY ; _clipStopY = stopY ; } ;
inline static bool isPreviousMode ( ) { return Segment : : _modeBlend ; } // needed for determining CCT/opacity during non-BLEND_STYLE_FADE transition
2022-07-19 14:16:43 +00:00
2025-04-22 20:37:18 +00:00
static void handleRandomPalette ( ) ;
public :
Segment ( uint16_t sStart = 0 , uint16_t sStop = 30 , uint16_t sStartY = 0 , uint16_t sStopY = 1 )
: colors { DEFAULT_COLOR , BLACK , BLACK }
, start ( sStart )
, stop ( sStop > sStart ? sStop : sStart + 1 ) // minimum length is 1
, startY ( sStartY )
, stopY ( sStopY > sStartY ? sStopY : sStartY + 1 ) // minimum height is 1
, offset ( 0 )
, options ( SELECTED | SEGMENT_ON )
, grouping ( 1 )
, spacing ( 0 )
, opacity ( 255 )
, cct ( 127 )
, mode ( DEFAULT_MODE )
, palette ( 0 )
, speed ( DEFAULT_SPEED )
, intensity ( DEFAULT_INTENSITY )
, custom1 ( DEFAULT_C1 )
, custom2 ( DEFAULT_C2 )
, custom3 ( DEFAULT_C3 )
, check1 ( false )
, check2 ( false )
, check3 ( false )
, blendMode ( 0 )
, name ( nullptr )
, next_time ( 0 )
, step ( 0 )
, call ( 0 )
, aux0 ( 0 )
, aux1 ( 0 )
, data ( nullptr )
, _dataLen ( 0 )
, _default_palette ( 6 )
, _capabilities ( 0 )
, _t ( nullptr )
{
DEBUGFX_PRINTF_P ( PSTR ( " -- Creating segment: %p [%d,%d:%d,%d] \n " ) , this , ( int ) start , ( int ) stop , ( int ) startY , ( int ) stopY ) ;
// allocate render buffer (always entire segment)
pixels = static_cast < uint32_t * > ( d_calloc ( sizeof ( uint32_t ) , length ( ) ) ) ; // error handling is also done in isActive()
if ( ! pixels ) {
DEBUGFX_PRINTLN ( F ( " !!! Not enough RAM for pixel buffer !!! " ) ) ;
extern byte errorFlag ;
errorFlag = ERR_NORAM_PX ;
stop = 0 ; // mark segment as inactive/invalid
}
2022-07-17 13:58:41 +00:00
}
Segment ( const Segment & orig ) ; // copy constructor
Segment ( Segment & & orig ) noexcept ; // move constructor
2022-07-06 11:13:54 +00:00
2022-07-17 13:58:41 +00:00
~ Segment ( ) {
2023-08-07 14:50:18 +00:00
# ifdef WLED_DEBUG
2025-04-22 20:37:18 +00:00
DEBUGFX_PRINTF_P ( PSTR ( " -- Destroying segment: %p [%d,%d:%d,%d] " ) , this , ( int ) start , ( int ) stop , ( int ) startY , ( int ) stopY ) ;
if ( name ) DEBUGFX_PRINTF_P ( PSTR ( " %s (%p) " ) , name , name ) ;
if ( data ) DEBUGFX_PRINTF_P ( PSTR ( " %u->(%p) " ) , _dataLen , data ) ;
DEBUGFX_PRINTF_P ( PSTR ( " T[%p] " ) , _t ) ;
DEBUGFX_PRINTLN ( ) ;
2023-08-07 14:50:18 +00:00
# endif
2025-04-22 20:37:18 +00:00
clearName ( ) ;
2022-07-17 13:58:41 +00:00
deallocateData ( ) ;
2025-04-22 20:37:18 +00:00
d_free ( pixels ) ;
2022-07-17 13:58:41 +00:00
}
Segment & operator = ( const Segment & orig ) ; // copy assignment
Segment & operator = ( Segment & & orig ) noexcept ; // move assignment
2022-08-03 19:36:47 +00:00
# ifdef WLED_DEBUG
2025-04-22 20:37:18 +00:00
size_t getSize ( ) const { return sizeof ( Segment ) + ( data ? _dataLen : 0 ) + ( name ? strlen ( name ) : 0 ) + ( _t ? sizeof ( Transition ) : 0 ) + ( pixels ? length ( ) * sizeof ( uint32_t ) : 0 ) ; }
2022-08-03 19:36:47 +00:00
# endif
2025-04-22 20:37:18 +00:00
inline bool getOption ( uint8_t n ) const { return ( ( options > > n ) & 0x01 ) ; }
inline bool isSelected ( ) const { return selected ; }
inline bool isInTransition ( ) const { return _t ! = nullptr ; }
inline bool isActive ( ) const { return stop > start & & pixels ; }
inline bool hasRGB ( ) const { return _isRGB ; }
inline bool hasWhite ( ) const { return _hasW ; }
inline bool isCCT ( ) const { return _isCCT ; }
inline uint16_t width ( ) const { return stop > start ? ( stop - start ) : 0 ; } // segment width in physical pixels (length if 1D)
inline uint16_t height ( ) const { return stopY - startY ; } // segment height (if 2D) in physical pixels (it *is* always >=1)
inline uint16_t length ( ) const { return width ( ) * height ( ) ; } // segment length (count) in physical pixels
inline uint16_t groupLength ( ) const { return grouping + spacing ; }
2024-09-11 15:14:59 +00:00
inline uint8_t getLightCapabilities ( ) const { return _capabilities ; }
2025-04-22 20:37:18 +00:00
inline void deactivate ( ) { setGeometry ( 0 , 0 ) ; }
inline Segment & clearName ( ) { d_free ( name ) ; name = nullptr ; return * this ; }
inline Segment & setName ( const String & name ) { return setName ( name . c_str ( ) ) ; }
2024-09-11 15:14:59 +00:00
2024-09-28 16:14:43 +00:00
inline static unsigned vLength ( ) { return Segment : : _vLength ; }
inline static unsigned vWidth ( ) { return Segment : : _vWidth ; }
inline static unsigned vHeight ( ) { return Segment : : _vHeight ; }
2025-04-22 20:37:18 +00:00
inline static uint32_t getCurrentColor ( unsigned i ) { return Segment : : _currentColors [ i < NUM_COLORS ? i : 0 ] ; }
2024-09-11 15:14:59 +00:00
inline static const CRGBPalette16 & getCurrentPalette ( ) { return Segment : : _currentPalette ; }
2024-09-28 16:14:43 +00:00
2025-04-22 20:37:18 +00:00
inline void setDrawDimensions ( ) const { Segment : : _vWidth = virtualWidth ( ) ; Segment : : _vHeight = virtualHeight ( ) ; Segment : : _vLength = virtualLength ( ) ; }
void beginDraw ( uint16_t prog = 0xFFFFU ) ; // set up parameters for current effect
2024-11-09 09:42:49 +00:00
void setGeometry ( uint16_t i1 , uint16_t i2 , uint8_t grp = 1 , uint8_t spc = 0 , uint16_t ofs = UINT16_MAX , uint16_t i1Y = 0 , uint16_t i2Y = 1 , uint8_t m12 = 0 ) ;
2024-10-26 13:16:11 +00:00
Segment & setColor ( uint8_t slot , uint32_t c ) ;
Segment & setCCT ( uint16_t k ) ;
Segment & setOpacity ( uint8_t o ) ;
Segment & setOption ( uint8_t n , bool val ) ;
Segment & setMode ( uint8_t fx , bool loadDefaults = false ) ;
Segment & setPalette ( uint8_t pal ) ;
2025-01-19 10:37:57 +00:00
Segment & setName ( const char * name ) ;
2025-04-22 20:37:18 +00:00
void refreshLightCapabilities ( ) const ;
2022-07-17 13:58:41 +00:00
// runtime data functions
2024-09-11 15:14:59 +00:00
inline uint16_t dataSize ( ) const { return _dataLen ; }
2023-12-27 18:36:25 +00:00
bool allocateData ( size_t len ) ; // allocates effect data buffer in heap and clears it
2024-09-11 15:14:59 +00:00
void deallocateData ( ) ; // deallocates (frees) effect data buffer from heap
2023-01-06 08:10:39 +00:00
/**
2022-07-17 13:58:41 +00:00
* Flags that before the next effect is calculated ,
2023-01-06 08:10:39 +00:00
* the internal segment state should be reset .
2022-07-17 13:58:41 +00:00
* Call resetIfRequired before calling the next effect function .
* Safe to call from interrupts and network requests .
*/
2024-10-26 13:16:11 +00:00
inline Segment & markForReset ( ) { reset = true ; return * this ; } // setOption(SEG_OPTION_RESET, true)
2022-07-17 13:58:41 +00:00
2025-04-22 20:37:18 +00:00
void startTransition ( uint16_t dur , bool segmentCopy = true ) ; // transition has to start before actual segment values change
uint8_t currentCCT ( ) const ; // current segment's CCT (blended while in transition)
uint8_t currentBri ( ) const ; // current segment's opacity/brightness (blended while in transition)
2022-07-17 13:58:41 +00:00
// 1D strip
2025-04-22 20:37:18 +00:00
uint16_t virtualLength ( ) const ;
2025-07-22 20:26:13 +00:00
uint16_t maxMappingLength ( ) const ;
2025-04-22 20:37:18 +00:00
[ [ gnu : : hot ] ] void setPixelColor ( int n , uint32_t c ) const ; // set relative pixel within segment with color
2025-01-09 12:29:06 +00:00
inline void setPixelColor ( unsigned n , uint32_t c ) const { setPixelColor ( int ( n ) , c ) ; }
inline void setPixelColor ( int n , byte r , byte g , byte b , byte w = 0 ) const { setPixelColor ( n , RGBW32 ( r , g , b , w ) ) ; }
inline void setPixelColor ( int n , CRGB c ) const { setPixelColor ( n , RGBW32 ( c . r , c . g , c . b , 0 ) ) ; }
2025-04-22 20:37:18 +00:00
void setRawPixelColor ( int i , uint32_t col ) const { if ( i > = 0 & & i < length ( ) ) setPixelColorRaw ( i , col ) ; }
2024-04-13 16:25:25 +00:00
# ifdef WLED_USE_AA_PIXELS
2025-01-09 12:29:06 +00:00
void setPixelColor ( float i , uint32_t c , bool aa = true ) const ;
inline void setPixelColor ( float i , uint8_t r , uint8_t g , uint8_t b , uint8_t w = 0 , bool aa = true ) const { setPixelColor ( i , RGBW32 ( r , g , b , w ) , aa ) ; }
inline void setPixelColor ( float i , CRGB c , bool aa = true ) const { setPixelColor ( i , RGBW32 ( c . r , c . g , c . b , 0 ) , aa ) ; }
2024-04-13 16:25:25 +00:00
# endif
2025-04-22 20:37:18 +00:00
[ [ gnu : : hot ] ] bool isPixelClipped ( int i ) const ;
2024-09-11 15:14:59 +00:00
[ [ gnu : : hot ] ] uint32_t getPixelColor ( int i ) const ;
2022-07-17 13:58:41 +00:00
// 1D support functions (some implement 2D as well)
2025-04-22 20:37:18 +00:00
void blur ( uint8_t , bool smear = false ) const ;
void clear ( ) const { fill ( BLACK ) ; } // clear segment
void fill ( uint32_t c ) const ;
void fade_out ( uint8_t r ) const ;
void fadeToSecondaryBy ( uint8_t fadeBy ) const ;
void fadeToBlackBy ( uint8_t fadeBy ) const ;
inline void blendPixelColor ( int n , uint32_t color , uint8_t blend ) const { setPixelColor ( n , color_blend ( getPixelColor ( n ) , color , blend ) ) ; }
inline void blendPixelColor ( int n , CRGB c , uint8_t blend ) const { blendPixelColor ( n , RGBW32 ( c . r , c . g , c . b , 0 ) , blend ) ; }
inline void addPixelColor ( int n , uint32_t color , bool preserveCR = true ) const { setPixelColor ( n , color_add ( getPixelColor ( n ) , color , preserveCR ) ) ; }
inline void addPixelColor ( int n , byte r , byte g , byte b , byte w = 0 , bool preserveCR = true ) const
{ addPixelColor ( n , RGBW32 ( r , g , b , w ) , preserveCR ) ; }
inline void addPixelColor ( int n , CRGB c , bool preserveCR = true ) const { addPixelColor ( n , RGBW32 ( c . r , c . g , c . b , 0 ) , preserveCR ) ; }
inline void fadePixelColor ( uint16_t n , uint8_t fade ) const { setPixelColor ( n , color_fade ( getPixelColor ( n ) , fade , true ) ) ; }
[ [ gnu : : hot ] ] uint32_t color_from_palette ( uint16_t , bool mapping , bool moving , uint8_t mcol , uint8_t pbri = 255 ) const ;
2024-09-11 15:14:59 +00:00
[ [ gnu : : hot ] ] uint32_t color_wheel ( uint8_t pos ) const ;
2022-07-17 13:58:41 +00:00
// 2D matrix
2025-04-22 20:37:18 +00:00
unsigned virtualWidth ( ) const ; // segment width in virtual pixels (accounts for groupping and spacing)
unsigned virtualHeight ( ) const ; // segment height in virtual pixels (accounts for groupping and spacing)
inline unsigned nrOfVStrips ( ) const { // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
2024-10-26 13:16:11 +00:00
# ifndef WLED_DISABLE_2D
return ( is2D ( ) & & map1D2D = = M12_pBar ) ? virtualWidth ( ) : 1 ;
# else
return 1 ;
# endif
}
2025-06-09 16:15:36 +00:00
inline unsigned rawLength ( ) const { // returns length of used raw pixel buffer (eg. get/setPixelColorRaw())
# ifndef WLED_DISABLE_2D
if ( is2D ( ) ) return virtualWidth ( ) * virtualHeight ( ) ;
# endif
return virtualLength ( ) ;
}
2022-08-03 12:23:24 +00:00
# ifndef WLED_DISABLE_2D
2025-01-09 12:29:06 +00:00
inline bool is2D ( ) const { return ( width ( ) > 1 & & height ( ) > 1 ) ; }
2025-01-07 19:33:10 +00:00
[ [ gnu : : hot ] ] void setPixelColorXY ( int x , int y , uint32_t c ) const ; // set relative pixel within segment with color
inline void setPixelColorXY ( unsigned x , unsigned y , uint32_t c ) const { setPixelColorXY ( int ( x ) , int ( y ) , c ) ; }
inline void setPixelColorXY ( int x , int y , byte r , byte g , byte b , byte w = 0 ) const { setPixelColorXY ( x , y , RGBW32 ( r , g , b , w ) ) ; }
inline void setPixelColorXY ( int x , int y , CRGB c ) const { setPixelColorXY ( x , y , RGBW32 ( c . r , c . g , c . b , 0 ) ) ; }
inline void setPixelColorXY ( unsigned x , unsigned y , CRGB c ) const { setPixelColorXY ( int ( x ) , int ( y ) , RGBW32 ( c . r , c . g , c . b , 0 ) ) ; }
2024-04-13 16:25:25 +00:00
# ifdef WLED_USE_AA_PIXELS
2025-01-09 12:29:06 +00:00
void setPixelColorXY ( float x , float y , uint32_t c , bool aa = true ) const ;
inline void setPixelColorXY ( float x , float y , byte r , byte g , byte b , byte w = 0 , bool aa = true ) const { setPixelColorXY ( x , y , RGBW32 ( r , g , b , w ) , aa ) ; }
inline void setPixelColorXY ( float x , float y , CRGB c , bool aa = true ) const { setPixelColorXY ( x , y , RGBW32 ( c . r , c . g , c . b , 0 ) , aa ) ; }
2024-04-13 16:25:25 +00:00
# endif
2024-09-11 15:28:48 +00:00
[ [ gnu : : hot ] ] bool isPixelXYClipped ( int x , int y ) const ;
2024-09-11 15:14:59 +00:00
[ [ gnu : : hot ] ] uint32_t getPixelColorXY ( int x , int y ) const ;
2022-07-17 13:58:41 +00:00
// 2D support functions
2025-04-22 20:37:18 +00:00
inline void blendPixelColorXY ( uint16_t x , uint16_t y , uint32_t color , uint8_t blend ) const { setPixelColorXY ( x , y , color_blend ( getPixelColorXY ( x , y ) , color , blend ) ) ; }
inline void blendPixelColorXY ( uint16_t x , uint16_t y , CRGB c , uint8_t blend ) const { blendPixelColorXY ( x , y , RGBW32 ( c . r , c . g , c . b , 0 ) , blend ) ; }
inline void addPixelColorXY ( int x , int y , uint32_t color , bool preserveCR = true ) const { setPixelColorXY ( x , y , color_add ( getPixelColorXY ( x , y ) , color , preserveCR ) ) ; }
inline void addPixelColorXY ( int x , int y , byte r , byte g , byte b , byte w = 0 , bool preserveCR = true )
{ addPixelColorXY ( x , y , RGBW32 ( r , g , b , w ) , preserveCR ) ; }
inline void addPixelColorXY ( int x , int y , CRGB c , bool preserveCR = true ) const { addPixelColorXY ( x , y , RGBW32 ( c . r , c . g , c . b , 0 ) , preserveCR ) ; }
inline void fadePixelColorXY ( uint16_t x , uint16_t y , uint8_t fade ) const { setPixelColorXY ( x , y , color_fade ( getPixelColorXY ( x , y ) , fade , true ) ) ; }
inline void blurCols ( fract8 blur_amount , bool smear = false ) const { blur2D ( 0 , blur_amount , smear ) ; } // blur all columns (50% faster than full 2D blur)
inline void blurRows ( fract8 blur_amount , bool smear = false ) const { blur2D ( blur_amount , 0 , smear ) ; } // blur all rows (50% faster than full 2D blur)
2024-10-03 19:19:34 +00:00
//void box_blur(unsigned r = 1U, bool smear = false); // 2D box blur
2025-04-22 20:37:18 +00:00
void blur2D ( uint8_t blur_x , uint8_t blur_y , bool smear = false ) const ;
void moveX ( int delta , bool wrap = false ) const ;
void moveY ( int delta , bool wrap = false ) const ;
void move ( unsigned dir , unsigned delta , bool wrap = false ) const ;
void drawCircle ( uint16_t cx , uint16_t cy , uint8_t radius , uint32_t c , bool soft = false ) const ;
void fillCircle ( uint16_t cx , uint16_t cy , uint8_t radius , uint32_t c , bool soft = false ) const ;
void drawLine ( uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 , uint32_t c , bool soft = false ) const ;
void drawCharacter ( unsigned char chr , int16_t x , int16_t y , uint8_t w , uint8_t h , uint32_t color , uint32_t col2 = 0 , int8_t rotate = 0 ) const ;
void wu_pixel ( uint32_t x , uint32_t y , CRGB c ) const ;
inline void drawCircle ( uint16_t cx , uint16_t cy , uint8_t radius , CRGB c , bool soft = false ) const { drawCircle ( cx , cy , radius , RGBW32 ( c . r , c . g , c . b , 0 ) , soft ) ; }
inline void fillCircle ( uint16_t cx , uint16_t cy , uint8_t radius , CRGB c , bool soft = false ) const { fillCircle ( cx , cy , radius , RGBW32 ( c . r , c . g , c . b , 0 ) , soft ) ; }
inline void drawLine ( uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 , CRGB c , bool soft = false ) const { drawLine ( x0 , y0 , x1 , y1 , RGBW32 ( c . r , c . g , c . b , 0 ) , soft ) ; } // automatic inline
inline void drawCharacter ( unsigned char chr , int16_t x , int16_t y , uint8_t w , uint8_t h , CRGB c , CRGB c2 = CRGB : : Black , int8_t rotate = 0 ) const { drawCharacter ( chr , x , y , w , h , RGBW32 ( c . r , c . g , c . b , 0 ) , RGBW32 ( c2 . r , c2 . g , c2 . b , 0 ) , rotate ) ; } // automatic inline
inline void fill_solid ( CRGB c ) const { fill ( RGBW32 ( c . r , c . g , c . b , 0 ) ) ; }
2022-08-03 12:23:24 +00:00
# else
2025-06-20 13:42:23 +00:00
inline bool is2D ( ) const { return false ; }
2025-04-22 20:37:18 +00:00
inline void setPixelColorXY ( int x , int y , uint32_t c ) const { setPixelColor ( x , c ) ; }
inline void setPixelColorXY ( unsigned x , unsigned y , uint32_t c ) const { setPixelColor ( int ( x ) , c ) ; }
inline void setPixelColorXY ( int x , int y , byte r , byte g , byte b , byte w = 0 ) const { setPixelColor ( x , RGBW32 ( r , g , b , w ) ) ; }
inline void setPixelColorXY ( int x , int y , CRGB c ) const { setPixelColor ( x , RGBW32 ( c . r , c . g , c . b , 0 ) ) ; }
inline void setPixelColorXY ( unsigned x , unsigned y , CRGB c ) const { setPixelColor ( int ( x ) , RGBW32 ( c . r , c . g , c . b , 0 ) ) ; }
2024-04-13 16:25:25 +00:00
# ifdef WLED_USE_AA_PIXELS
2025-04-22 20:37:18 +00:00
inline void setPixelColorXY ( float x , float y , uint32_t c , bool aa = true ) const { setPixelColor ( x , c , aa ) ; }
2023-10-15 11:06:40 +00:00
inline void setPixelColorXY ( float x , float y , byte r , byte g , byte b , byte w = 0 , bool aa = true ) { setPixelColor ( x , RGBW32 ( r , g , b , w ) , aa ) ; }
2025-04-22 20:37:18 +00:00
inline void setPixelColorXY ( float x , float y , CRGB c , bool aa = true ) const { setPixelColor ( x , RGBW32 ( c . r , c . g , c . b , 0 ) , aa ) ; }
2024-04-13 16:25:25 +00:00
# endif
2025-04-22 20:37:18 +00:00
inline bool isPixelXYClipped ( int x , int y ) const { return isPixelClipped ( x ) ; }
inline uint32_t getPixelColorXY ( int x , int y ) const { return getPixelColor ( x ) ; }
inline void blendPixelColorXY ( uint16_t x , uint16_t y , uint32_t c , uint8_t blend ) const { blendPixelColor ( x , c , blend ) ; }
inline void blendPixelColorXY ( uint16_t x , uint16_t y , CRGB c , uint8_t blend ) const { blendPixelColor ( x , RGBW32 ( c . r , c . g , c . b , 0 ) , blend ) ; }
inline void addPixelColorXY ( int x , int y , uint32_t color , bool saturate = false ) const { addPixelColor ( x , color , saturate ) ; }
inline void addPixelColorXY ( int x , int y , byte r , byte g , byte b , byte w = 0 , bool saturate = false ) const { addPixelColor ( x , RGBW32 ( r , g , b , w ) , saturate ) ; }
inline void addPixelColorXY ( int x , int y , CRGB c , bool saturate = false ) const { addPixelColor ( x , RGBW32 ( c . r , c . g , c . b , 0 ) , saturate ) ; }
inline void fadePixelColorXY ( uint16_t x , uint16_t y , uint8_t fade ) const { fadePixelColor ( x , fade ) ; }
2024-10-03 19:19:34 +00:00
//inline void box_blur(unsigned i, bool vertical, fract8 blur_amount) {}
inline void blur2D ( uint8_t blur_x , uint8_t blur_y , bool smear = false ) { }
2025-04-22 20:37:18 +00:00
inline void blurCols ( fract8 blur_amount , bool smear = false ) { blur ( blur_amount , smear ) ; } // blur all columns (50% faster than full 2D blur)
inline void blurRows ( fract8 blur_amount , bool smear = false ) { }
2024-09-29 11:55:00 +00:00
inline void moveX ( int delta , bool wrap = false ) { }
inline void moveY ( int delta , bool wrap = false ) { }
2023-10-15 11:06:40 +00:00
inline void move ( uint8_t dir , uint8_t delta , bool wrap = false ) { }
2024-05-09 22:02:28 +00:00
inline void drawCircle ( uint16_t cx , uint16_t cy , uint8_t radius , uint32_t c , bool soft = false ) { }
inline void drawCircle ( uint16_t cx , uint16_t cy , uint8_t radius , CRGB c , bool soft = false ) { }
inline void fillCircle ( uint16_t cx , uint16_t cy , uint8_t radius , uint32_t c , bool soft = false ) { }
inline void fillCircle ( uint16_t cx , uint16_t cy , uint8_t radius , CRGB c , bool soft = false ) { }
inline void drawLine ( uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 , uint32_t c , bool soft = false ) { }
inline void drawLine ( uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 , CRGB c , bool soft = false ) { }
2025-04-22 20:37:18 +00:00
inline void drawCharacter ( unsigned char chr , int16_t x , int16_t y , uint8_t w , uint8_t h , uint32_t color , uint32_t = 0 , int8_t = 0 ) { }
inline void drawCharacter ( unsigned char chr , int16_t x , int16_t y , uint8_t w , uint8_t h , CRGB c , CRGB c2 , int8_t rotate = 0 ) { }
2023-10-15 11:06:40 +00:00
inline void wu_pixel ( uint32_t x , uint32_t y , CRGB c ) { }
2022-08-03 12:23:24 +00:00
# endif
2025-04-22 20:37:18 +00:00
friend class WS2812FX ;
2025-07-22 20:26:13 +00:00
friend class ParticleSystem2D ;
friend class ParticleSystem1D ;
2025-04-22 20:37:18 +00:00
} ;
2022-07-06 11:13:54 +00:00
2025-06-18 20:16:58 +00:00
// main "strip" class (108 bytes)
2025-04-22 20:37:18 +00:00
class WS2812FX {
2024-09-11 15:14:59 +00:00
typedef uint16_t ( * mode_ptr ) ( ) ; // pointer to mode function
typedef void ( * show_callback ) ( ) ; // pre show callback
2022-07-17 13:58:41 +00:00
typedef struct ModeData {
2022-07-29 10:15:56 +00:00
uint8_t _id ; // mode (effect) id
2022-07-17 13:58:41 +00:00
mode_ptr _fcn ; // mode (effect) function
2022-07-29 10:15:56 +00:00
const char * _data ; // mode (effect) name and its UI control data
ModeData ( uint8_t id , uint16_t ( * fcn ) ( void ) , const char * data ) : _id ( id ) , _fcn ( fcn ) , _data ( data ) { }
2022-07-17 13:58:41 +00:00
} mode_data_t ;
2021-01-08 23:35:48 +00:00
2016-12-17 22:43:07 +00:00
public :
2022-05-08 08:50:48 +00:00
2022-07-19 14:16:43 +00:00
WS2812FX ( ) :
paletteBlend ( 0 ) ,
now ( millis ( ) ) ,
timebase ( 0 ) ,
isMatrix ( false ) ,
2024-10-07 08:39:45 +00:00
# ifdef WLED_AUTOSEGMENTS
2024-10-06 20:56:30 +00:00
autoSegments ( true ) ,
# else
2024-08-17 13:09:41 +00:00
autoSegments ( false ) ,
2024-10-06 20:56:30 +00:00
# endif
2024-08-17 13:09:41 +00:00
correctWB ( false ) ,
cctFromRgb ( false ) ,
2022-07-29 10:15:56 +00:00
// true private variables
2025-04-22 20:37:18 +00:00
_pixels ( nullptr ) ,
2025-06-18 20:16:58 +00:00
_pixelCCT ( nullptr ) ,
2023-12-22 14:39:07 +00:00
_suspend ( false ) ,
2022-07-19 14:16:43 +00:00
_brightness ( DEFAULT_BRIGHTNESS ) ,
2025-04-22 20:37:18 +00:00
_length ( DEFAULT_LED_COUNT ) ,
2022-07-19 14:16:43 +00:00
_transitionDur ( 750 ) ,
2022-08-24 21:04:51 +00:00
_frametime ( FRAMETIME_FIXED ) ,
2025-04-26 18:08:15 +00:00
_cumulativeFps ( WLED_FPS < < FPS_CALC_SHIFT ) ,
2025-04-22 20:37:18 +00:00
_targetFps ( WLED_FPS ) ,
2022-07-19 14:16:43 +00:00
_isServicing ( false ) ,
_isOffRefreshRequired ( false ) ,
_hasWhiteChannel ( false ) ,
_triggered ( false ) ,
2025-04-22 20:37:18 +00:00
_segment_index ( 0 ) ,
_mainSegment ( 0 ) ,
2022-07-19 14:16:43 +00:00
_modeCount ( MODE_COUNT ) ,
_callback ( nullptr ) ,
customMappingTable ( nullptr ) ,
customMappingSize ( 0 ) ,
_lastShow ( 0 ) ,
2025-04-26 18:08:15 +00:00
_lastServiceShow ( 0 )
2022-07-19 14:16:43 +00:00
{
2022-08-08 08:21:11 +00:00
_mode . reserve ( _modeCount ) ; // allocate memory to prevent initial fragmentation (does not increase size())
_modeData . reserve ( _modeCount ) ; // allocate memory to prevent initial fragmentation (does not increase size())
if ( _mode . capacity ( ) < = 1 | | _modeData . capacity ( ) < = 1 ) _modeCount = 1 ; // memory allocation failed only show Solid
2022-07-17 13:58:41 +00:00
else setupEffectData ( ) ;
2016-12-17 22:43:07 +00:00
}
2022-07-10 20:23:25 +00:00
~ WS2812FX ( ) {
2025-04-22 20:37:18 +00:00
d_free ( _pixels ) ;
2025-06-18 20:16:58 +00:00
d_free ( _pixelCCT ) ; // just in case
2025-04-22 20:37:18 +00:00
d_free ( customMappingTable ) ;
2022-07-17 13:58:41 +00:00
_mode . clear ( ) ;
_modeData . clear ( ) ;
2022-07-19 14:16:43 +00:00
_segments . clear ( ) ;
2023-01-02 20:24:02 +00:00
# ifndef WLED_DISABLE_2D
2023-01-02 19:56:00 +00:00
panel . clear ( ) ;
2023-01-02 20:24:02 +00:00
# endif
2022-07-10 20:23:25 +00:00
}
2016-12-17 22:43:07 +00:00
void
2022-08-03 19:36:47 +00:00
# ifdef WLED_DEBUG
2024-01-04 16:40:23 +00:00
printSize ( ) , // prints memory usage for strip components
2022-08-03 19:36:47 +00:00
# endif
2024-01-04 16:40:23 +00:00
finalizeInit ( ) , // initialises strip components
2024-09-11 15:14:59 +00:00
service ( ) , // executes effect functions when due and calls strip.show()
2024-01-04 16:40:23 +00:00
setCCT ( uint16_t k ) , // sets global CCT (either in relative 0-255 value or in K)
setBrightness ( uint8_t b , bool direct = false ) , // sets strip brightness
setRange ( uint16_t i , uint16_t i2 , uint32_t col ) , // used for clock overlay
2024-09-11 15:14:59 +00:00
purgeSegments ( ) , // removes inactive segments from RAM (may incure penalty and memory fragmentation but reduces vector footprint)
2024-10-02 18:14:25 +00:00
setMainSegmentId ( unsigned n = 0 ) ,
2024-01-04 16:40:23 +00:00
resetSegments ( ) , // marks all segments for reset
makeAutoSegments ( bool forceReset = false ) , // will create segments based on configured outputs
fixInvalidSegments ( ) , // fixes incorrect segment configuration
2025-04-22 20:37:18 +00:00
blendSegment ( const Segment & topSegment ) const , // blends topSegment into pixels
2024-09-11 15:14:59 +00:00
show ( ) , // initiates LED output
2024-10-02 18:14:25 +00:00
setTargetFps ( unsigned fps ) ,
2025-04-22 20:37:18 +00:00
setupEffectData ( ) , // add default effects to the list; defined in FX.cpp
waitForIt ( ) ; // wait until frame is over (service() has finished or time for 1 frame has passed)
void setRealtimePixelColor ( unsigned i , uint32_t c ) ;
inline void setPixelColor ( unsigned n , uint32_t c ) const { if ( n < getLengthTotal ( ) ) _pixels [ n ] = c ; } // paints absolute strip pixel with index n and color c
inline void resetTimebase ( ) { timebase = 0UL - millis ( ) ; }
inline void setPixelColor ( unsigned n , uint8_t r , uint8_t g , uint8_t b , uint8_t w = 0 ) const
{ setPixelColor ( n , RGBW32 ( r , g , b , w ) ) ; }
inline void setPixelColor ( unsigned n , CRGB c ) const { setPixelColor ( n , c . red , c . green , c . blue ) ; }
inline void fill ( uint32_t c ) const { for ( size_t i = 0 ; i < getLengthTotal ( ) ; i + + ) setPixelColor ( i , c ) ; } // fill whole strip with color (inline)
2024-09-11 15:14:59 +00:00
inline void trigger ( ) { _triggered = true ; } // Forces the next frame to be computed on all active segments.
2024-01-04 16:40:23 +00:00
inline void setShowCallback ( show_callback cb ) { _callback = cb ; }
inline void setTransition ( uint16_t t ) { _transitionDur = t ; } // sets transition time (in ms)
2025-04-22 20:37:18 +00:00
inline void appendSegment ( uint16_t sStart = 0 , uint16_t sStop = 30 , uint16_t sStartY = 0 , uint16_t sStopY = 1 )
{ if ( _segments . size ( ) < getMaxSegments ( ) ) _segments . emplace_back ( sStart , sStop , sStartY , sStopY ) ; }
2024-09-11 15:14:59 +00:00
inline void suspend ( ) { _suspend = true ; } // will suspend (and canacel) strip.service() execution
inline void resume ( ) { _suspend = false ; } // will resume strip.service() execution
2022-03-25 15:36:05 +00:00
2025-04-22 20:37:18 +00:00
void restartRuntime ( ) ;
void setTransitionMode ( bool t ) ;
bool checkSegmentAlignment ( ) const ;
bool hasRGBWBus ( ) const ;
bool hasCCTBus ( ) const ;
bool deserializeMap ( unsigned n = 0 ) ;
2018-11-24 10:52:23 +00:00
2024-10-02 18:14:25 +00:00
inline bool isUpdating ( ) const { return ! BusManager : : canAllShow ( ) ; } // return true if the strip is being sent pixel updates
2024-09-11 15:14:59 +00:00
inline bool isServicing ( ) const { return _isServicing ; } // returns true if strip.service() is executing
inline bool hasWhiteChannel ( ) const { return _hasWhiteChannel ; } // returns true if strip contains separate white chanel
inline bool isOffRefreshRequired ( ) const { return _isOffRefreshRequired ; } // returns true if strip requires regular updates (i.e. TM1814 chipset)
inline bool isSuspended ( ) const { return _suspend ; } // returns true if strip.service() execution is suspended
inline bool needsUpdate ( ) const { return _triggered ; } // returns true if strip received a trigger() request
2022-07-06 11:13:54 +00:00
2025-04-22 20:37:18 +00:00
uint8_t paletteBlend ;
uint8_t getActiveSegmentsNum ( ) const ;
uint8_t getFirstSelectedSegId ( ) const ;
uint8_t getLastActiveSegmentId ( ) const ;
uint8_t getActiveSegsLightCapabilities ( bool selectedOnly = false ) const ;
uint8_t addEffect ( uint8_t id , mode_ptr mode_fn , const char * mode_name ) ; // add effect to the list; defined in FX.cpp;
2024-08-14 20:15:48 +00:00
2024-09-11 15:14:59 +00:00
inline uint8_t getBrightness ( ) const { return _brightness ; } // returns current strip brightness
2024-09-28 16:48:43 +00:00
inline static constexpr unsigned getMaxSegments ( ) { return MAX_NUM_SEGMENTS ; } // returns maximum number of supported segments (fixed value)
2024-09-11 15:14:59 +00:00
inline uint8_t getSegmentsNum ( ) const { return _segments . size ( ) ; } // returns currently present segments
inline uint8_t getCurrSegmentId ( ) const { return _segment_index ; } // returns current segment index (only valid while strip.isServicing())
inline uint8_t getMainSegmentId ( ) const { return _mainSegment ; } // returns main segment index
inline uint8_t getTargetFps ( ) const { return _targetFps ; } // returns rough FPS value for las 2s interval
inline uint8_t getModeCount ( ) const { return _modeCount ; } // returns number of registered modes/effects
2020-09-27 12:42:14 +00:00
2025-04-22 20:37:18 +00:00
uint16_t getLengthPhysical ( ) const ;
uint16_t getLengthTotal ( ) const ; // will include virtual/nonexistent pixels in matrix
2019-08-30 13:39:34 +00:00
2024-11-09 09:53:27 +00:00
inline uint16_t getFps ( ) const { return ( millis ( ) - _lastShow > 2000 ) ? 0 : ( FPS_MULTIPLIER * _cumulativeFps ) > > FPS_CALC_SHIFT ; } // Returns the refresh rate of the LED strip (_cumulativeFps is stored in fixed point)
2024-09-11 15:14:59 +00:00
inline uint16_t getFrameTime ( ) const { return _frametime ; } // returns amount of time a frame should take (in ms)
2024-11-07 22:15:39 +00:00
inline uint16_t getMinShowDelay ( ) const { return MIN_FRAME_DELAY ; } // returns minimum amount of time strip.service() can be delayed (constant)
2024-09-11 15:14:59 +00:00
inline uint16_t getLength ( ) const { return _length ; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H)
inline uint16_t getTransition ( ) const { return _transitionDur ; } // returns currently set transition time (in ms)
2024-09-23 16:03:17 +00:00
inline uint16_t getMappedPixelIndex ( uint16_t index ) const { // convert logical address to physical
if ( index < customMappingSize & & ( realtimeMode = = REALTIME_MODE_INACTIVE | | realtimeRespectLedMaps ) ) index = customMappingTable [ index ] ;
return index ;
} ;
2016-12-17 22:43:07 +00:00
2024-10-26 13:16:11 +00:00
unsigned long now , timebase ;
2025-04-22 20:37:18 +00:00
inline uint32_t getPixelColor ( unsigned n ) const { return ( n < getLengthTotal ( ) ) ? _pixels [ n ] : 0 ; } // returns color of pixel n
inline uint32_t getLastShow ( ) const { return _lastShow ; } // returns millis() timestamp of last strip.show() call
2022-06-21 20:49:45 +00:00
2025-04-22 20:37:18 +00:00
const char * getModeData ( unsigned id = 0 ) const { return ( id & & id < _modeCount ) ? _modeData [ id ] : PSTR ( " Solid " ) ; }
inline const char * * getModeDataSrc ( ) { return & ( _modeData [ 0 ] ) ; } // vectors use arrays for underlying data
2022-06-21 20:49:45 +00:00
2024-10-02 18:14:25 +00:00
Segment & getSegment ( unsigned id ) ;
2024-09-11 15:14:59 +00:00
inline Segment & getFirstSelectedSeg ( ) { return _segments [ getFirstSelectedSegId ( ) ] ; } // returns reference to first segment that is "selected"
inline Segment & getMainSegment ( ) { return _segments [ getMainSegmentId ( ) ] ; } // returns reference to main segment
inline Segment * getSegments ( ) { return & ( _segments [ 0 ] ) ; } // returns pointer to segment vector structure (warning: use carefully)
2018-09-04 13:51:38 +00:00
2022-07-06 11:13:54 +00:00
// 2D support (panels)
2022-05-08 08:50:48 +00:00
2022-07-10 20:23:25 +00:00
# ifndef WLED_DISABLE_2D
2025-04-22 20:37:18 +00:00
struct Panel {
2023-01-02 19:56:00 +00:00
uint16_t xOffset ; // x offset relative to the top left of matrix in LEDs
uint16_t yOffset ; // y offset relative to the top left of matrix in LEDs
uint8_t width ; // width of the panel
uint8_t height ; // height of the panel
union {
uint8_t options ;
struct {
bool bottomStart : 1 ; // starts at bottom?
bool rightStart : 1 ; // starts on right?
bool vertical : 1 ; // is vertical?
bool serpentine : 1 ; // is serpentine?
} ;
} ;
2025-04-22 20:37:18 +00:00
Panel ( )
: xOffset ( 0 )
, yOffset ( 0 )
, width ( 8 )
, height ( 8 )
, options ( 0 )
2023-03-05 21:56:14 +00:00
{ }
2025-04-22 20:37:18 +00:00
} ;
2023-01-02 19:56:00 +00:00
std : : vector < Panel > panel ;
2022-07-10 20:23:25 +00:00
# endif
2022-05-08 08:50:48 +00:00
2024-01-04 16:40:23 +00:00
void setUpMatrix ( ) ; // sets up automatic matrix ledmap from panel configuration
2022-05-08 08:50:48 +00:00
2025-04-22 20:37:18 +00:00
inline void setPixelColorXY ( unsigned x , unsigned y , uint32_t c ) const { setPixelColor ( y * Segment : : maxWidth + x , c ) ; }
inline void setPixelColorXY ( unsigned x , unsigned y , byte r , byte g , byte b , byte w = 0 ) const { setPixelColorXY ( x , y , RGBW32 ( r , g , b , w ) ) ; }
inline void setPixelColorXY ( unsigned x , unsigned y , CRGB c ) const { setPixelColorXY ( x , y , RGBW32 ( c . r , c . g , c . b , 0 ) ) ; }
inline uint32_t getPixelColorXY ( unsigned x , unsigned y ) const { return getPixelColor ( y * Segment : : maxWidth + x ) ; }
2022-05-08 08:50:48 +00:00
2022-07-06 11:13:54 +00:00
// end 2D support
2022-05-08 08:50:48 +00:00
2025-04-22 20:37:18 +00:00
bool isMatrix ;
2024-08-17 13:09:41 +00:00
struct {
bool autoSegments : 1 ;
bool correctWB : 1 ;
bool cctFromRgb : 1 ;
} ;
2022-07-10 20:23:25 +00:00
2025-04-22 20:37:18 +00:00
Segment * _currentSegment ;
2022-07-10 20:23:25 +00:00
2022-07-06 11:13:54 +00:00
private :
2025-04-22 20:37:18 +00:00
uint32_t * _pixels ;
2025-06-18 20:16:58 +00:00
uint8_t * _pixelCCT ;
2025-04-22 20:37:18 +00:00
std : : vector < Segment > _segments ;
2023-12-22 14:39:07 +00:00
volatile bool _suspend ;
2023-06-30 19:12:59 +00:00
uint8_t _brightness ;
2025-04-22 20:37:18 +00:00
uint16_t _length ;
2022-07-19 14:16:43 +00:00
uint16_t _transitionDur ;
2022-08-24 21:04:51 +00:00
uint16_t _frametime ;
2022-07-19 14:16:43 +00:00
uint16_t _cumulativeFps ;
2025-04-22 20:37:18 +00:00
uint8_t _targetFps ;
2022-07-19 14:16:43 +00:00
// will require only 1 byte
2022-07-28 21:19:58 +00:00
struct {
bool _isServicing : 1 ;
bool _isOffRefreshRequired : 1 ; //periodic refresh is required for the strip to remain off.
bool _hasWhiteChannel : 1 ;
bool _triggered : 1 ;
} ;
2022-07-29 10:15:56 +00:00
2025-04-22 20:37:18 +00:00
uint8_t _segment_index ;
uint8_t _mainSegment ;
2022-07-29 10:15:56 +00:00
uint8_t _modeCount ;
2022-07-17 13:58:41 +00:00
std : : vector < mode_ptr > _mode ; // SRAM footprint: 4 bytes per element
std : : vector < const char * > _modeData ; // mode (effect) name and its slider control data array
2022-07-19 14:16:43 +00:00
show_callback _callback ;
2016-12-17 22:43:07 +00:00
2022-07-19 14:16:43 +00:00
uint16_t * customMappingTable ;
uint16_t customMappingSize ;
2023-01-06 08:10:39 +00:00
2023-07-12 18:52:34 +00:00
unsigned long _lastShow ;
2024-11-01 22:19:38 +00:00
unsigned long _lastServiceShow ;
2023-01-06 08:10:39 +00:00
2025-04-22 20:37:18 +00:00
friend class Segment ;
2016-12-17 22:43:07 +00:00
} ;
2019-02-10 22:05:06 +00:00
2021-12-28 17:09:52 +00:00
extern const char JSON_mode_names [ ] ;
extern const char JSON_palette_names [ ] ;
2025-04-22 20:37:18 +00:00
# endif