| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | /* | ||
| 3 | WS2812FX.h - Library for WS2812 LED effects. | ||
| 4 | Harm Aldick - 2016 | ||
| 5 | www.aldick.org | ||
| 6 | |||
| 7 | Copyright (c) 2016 Harm Aldick | ||
| 8 | Licensed under the EUPL v. 1.2 or later | ||
| 9 | Adapted from code originally licensed under the MIT license | ||
| 10 | |||
| 11 | Modified for WLED | ||
| 12 | |||
| 13 | Segment class/struct (c) 2022 Blaz Kristan (@blazoncek) | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef WS2812FX_h | ||
| 17 | #define WS2812FX_h | ||
| 18 | |||
| 19 | #include <vector> | ||
| 20 | #include "wled.h" | ||
| 21 | |||
| 22 | #include "const.h" | ||
| 23 | #include "bus_manager.h" | ||
| 24 | |||
| 25 | #define FASTLED_INTERNAL //remove annoying pragma messages | ||
| 26 | #define USE_GET_MILLISECOND_TIMER | ||
| 27 | #include "FastLED.h" | ||
| 28 | |||
| 29 | #define DEFAULT_BRIGHTNESS (uint8_t)127 | ||
| 30 | #define DEFAULT_MODE (uint8_t)0 | ||
| 31 | #define DEFAULT_SPEED (uint8_t)128 | ||
| 32 | #define DEFAULT_INTENSITY (uint8_t)128 | ||
| 33 | #define DEFAULT_COLOR (uint32_t)0xFFAA00 | ||
| 34 | #define DEFAULT_C1 (uint8_t)128 | ||
| 35 | #define DEFAULT_C2 (uint8_t)128 | ||
| 36 | #define DEFAULT_C3 (uint8_t)16 | ||
| 37 | |||
| 38 | #ifndef MIN | ||
| 39 | #define MIN(a,b) ((a)<(b)?(a):(b)) | ||
| 40 | #endif | ||
| 41 | #ifndef MAX | ||
| 42 | #define MAX(a,b) ((a)>(b)?(a):(b)) | ||
| 43 | #endif | ||
| 44 | |||
| 45 | //color mangling macros | ||
| 46 | #ifndef RGBW32 | ||
| 47 | #define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b)))) | ||
| 48 | #endif | ||
| 49 | |||
| 50 | extern bool realtimeRespectLedMaps; // used in getMappedPixelIndex() | ||
| 51 | extern byte realtimeMode; // used in getMappedPixelIndex() | ||
| 52 | |||
| 53 | /* Not used in all effects yet */ | ||
| 54 | #define WLED_FPS 40 | ||
| 55 | #define FRAMETIME_FIXED (1000/WLED_FPS) | ||
| 56 | #define FRAMETIME strip().getFrameTime() | ||
| 57 | #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) | ||
| 58 | #define MIN_FRAME_DELAY 2 // minimum wait between repaints, to keep other functions like WiFi alive | ||
| 59 | #elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) | ||
| 60 | #define MIN_FRAME_DELAY 3 // S2/C3 are slower than normal esp32, and only have one core | ||
| 61 | #else | ||
| 62 | #define MIN_FRAME_DELAY 8 // 8266 legacy MIN_SHOW_DELAY | ||
| 63 | #endif | ||
| 64 | #define FPS_UNLIMITED 0 | ||
| 65 | |||
| 66 | // FPS calculation (can be defined as compile flag for debugging) | ||
| 67 | #ifndef FPS_CALC_AVG | ||
| 68 | #define FPS_CALC_AVG 7 // average FPS calculation over this many frames (moving average) | ||
| 69 | #endif | ||
| 70 | #ifndef FPS_MULTIPLIER | ||
| 71 | #define FPS_MULTIPLIER 1 // dev option: multiplier to get sub-frame FPS without floats | ||
| 72 | #endif | ||
| 73 | #define FPS_CALC_SHIFT 7 // bit shift for fixed point math | ||
| 74 | |||
| 75 | /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of | ||
| 76 | insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ | ||
| 77 | #ifdef ESP8266 | ||
| 78 | #define MAX_NUM_SEGMENTS 16 | ||
| 79 | /* How much data bytes all segments combined may allocate */ | ||
| 80 | #define MAX_SEGMENT_DATA 5120 | ||
| 81 | #elif defined(CONFIG_IDF_TARGET_ESP32S2) | ||
| 82 | #define MAX_NUM_SEGMENTS 20 | ||
| 83 | #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*512) // 10k by default (S2 is short on free RAM) | ||
| 84 | #else | ||
| 85 | #define MAX_NUM_SEGMENTS 32 // warning: going beyond 32 may consume too much RAM for stable operation | ||
| 86 | #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1280) // 40k by default | ||
| 87 | #endif | ||
| 88 | |||
| 89 | /* How much data bytes each segment should max allocate to leave enough space for other segments, | ||
| 90 | assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */ | ||
| 91 | #define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / strip().getMaxSegments()) | ||
| 92 | |||
| 93 | #define NUM_COLORS 3 /* number of colors per segment */ | ||
| 94 | #define SEGMENT strip()._segments[strip().getCurrSegmentId()] | ||
| 95 | #define SEGENV strip()._segments[strip().getCurrSegmentId()] | ||
| 96 | #define SEGCOLOR(x) Segment::getCurrentColor(x) | ||
| 97 | #define SEGPALETTE Segment::getCurrentPalette() | ||
| 98 | #define SEGLEN Segment::vLength() | ||
| 99 | #define SEG_W Segment::vWidth() | ||
| 100 | #define SEG_H Segment::vHeight() | ||
| 101 | #define SPEED_FORMULA_L (5U + (50U*(255U - SEGMENT.speed))/SEGLEN) | ||
| 102 | |||
| 103 | // some common colors | ||
| 104 | #define RED (uint32_t)0xFF0000 | ||
| 105 | #define GREEN (uint32_t)0x00FF00 | ||
| 106 | #define BLUE (uint32_t)0x0000FF | ||
| 107 | #define WHITE (uint32_t)0xFFFFFF | ||
| 108 | #define BLACK (uint32_t)0x000000 | ||
| 109 | #define YELLOW (uint32_t)0xFFFF00 | ||
| 110 | #define CYAN (uint32_t)0x00FFFF | ||
| 111 | #define MAGENTA (uint32_t)0xFF00FF | ||
| 112 | #define PURPLE (uint32_t)0x400080 | ||
| 113 | #define ORANGE (uint32_t)0xFF3000 | ||
| 114 | #define PINK (uint32_t)0xFF1493 | ||
| 115 | #define GREY (uint32_t)0x808080 | ||
| 116 | #define GRAY GREY | ||
| 117 | #define DARKGREY (uint32_t)0x333333 | ||
| 118 | #define DARKGRAY DARKGREY | ||
| 119 | #define ULTRAWHITE (uint32_t)0xFFFFFFFF | ||
| 120 | #define DARKSLATEGRAY (uint32_t)0x2F4F4F | ||
| 121 | #define DARKSLATEGREY DARKSLATEGRAY | ||
| 122 | |||
| 123 | // segment options | ||
| 124 | #define NO_OPTIONS (uint16_t)0x0000 | ||
| 125 | #define TRANSPOSED (uint16_t)0x0100 // rotated 90deg & reversed | ||
| 126 | #define MIRROR_Y_2D (uint16_t)0x0080 | ||
| 127 | #define REVERSE_Y_2D (uint16_t)0x0040 | ||
| 128 | #define RESET_REQ (uint16_t)0x0020 | ||
| 129 | #define FROZEN (uint16_t)0x0010 | ||
| 130 | #define MIRROR (uint16_t)0x0008 | ||
| 131 | #define SEGMENT_ON (uint16_t)0x0004 | ||
| 132 | #define REVERSE (uint16_t)0x0002 | ||
| 133 | #define SELECTED (uint16_t)0x0001 | ||
| 134 | |||
| 135 | #define FX_MODE_STATIC 0 | ||
| 136 | #define FX_MODE_BLINK 1 | ||
| 137 | #define FX_MODE_BREATH 2 | ||
| 138 | #define FX_MODE_COLOR_WIPE 3 | ||
| 139 | #define FX_MODE_COLOR_WIPE_RANDOM 4 | ||
| 140 | #define FX_MODE_RANDOM_COLOR 5 | ||
| 141 | #define FX_MODE_COLOR_SWEEP 6 | ||
| 142 | #define FX_MODE_DYNAMIC 7 | ||
| 143 | #define FX_MODE_RAINBOW 8 | ||
| 144 | #define FX_MODE_RAINBOW_CYCLE 9 | ||
| 145 | #define FX_MODE_SCAN 10 | ||
| 146 | #define FX_MODE_DUAL_SCAN 11 | ||
| 147 | #define FX_MODE_FADE 12 | ||
| 148 | #define FX_MODE_THEATER_CHASE 13 | ||
| 149 | #define FX_MODE_THEATER_CHASE_RAINBOW 14 | ||
| 150 | #define FX_MODE_RUNNING_LIGHTS 15 | ||
| 151 | #define FX_MODE_SAW 16 | ||
| 152 | #define FX_MODE_TWINKLE 17 | ||
| 153 | #define FX_MODE_DISSOLVE 18 | ||
| 154 | #define FX_MODE_DISSOLVE_RANDOM 19 // candidate for removal (use Dissolve with with check 3) | ||
| 155 | #define FX_MODE_SPARKLE 20 | ||
| 156 | #define FX_MODE_FLASH_SPARKLE 21 | ||
| 157 | #define FX_MODE_HYPER_SPARKLE 22 | ||
| 158 | #define FX_MODE_STROBE 23 | ||
| 159 | #define FX_MODE_STROBE_RAINBOW 24 | ||
| 160 | #define FX_MODE_MULTI_STROBE 25 | ||
| 161 | #define FX_MODE_BLINK_RAINBOW 26 | ||
| 162 | #define FX_MODE_ANDROID 27 | ||
| 163 | #define FX_MODE_CHASE_COLOR 28 | ||
| 164 | #define FX_MODE_CHASE_RANDOM 29 | ||
| 165 | #define FX_MODE_CHASE_RAINBOW 30 | ||
| 166 | #define FX_MODE_CHASE_FLASH 31 | ||
| 167 | #define FX_MODE_CHASE_FLASH_RANDOM 32 | ||
| 168 | #define FX_MODE_CHASE_RAINBOW_WHITE 33 | ||
| 169 | #define FX_MODE_COLORFUL 34 | ||
| 170 | #define FX_MODE_TRAFFIC_LIGHT 35 | ||
| 171 | #define FX_MODE_COLOR_SWEEP_RANDOM 36 | ||
| 172 | #define FX_MODE_RUNNING_COLOR 37 | ||
| 173 | #define FX_MODE_AURORA 38 | ||
| 174 | #define FX_MODE_RUNNING_RANDOM 39 | ||
| 175 | #define FX_MODE_LARSON_SCANNER 40 | ||
| 176 | #define FX_MODE_COMET 41 | ||
| 177 | #define FX_MODE_FIREWORKS 42 | ||
| 178 | #define FX_MODE_RAIN 43 | ||
| 179 | #define FX_MODE_TETRIX 44 //was Merry Christmas prior to 0.12.0 (use "Chase 2" with Red/Green) | ||
| 180 | #define FX_MODE_FIRE_FLICKER 45 | ||
| 181 | #define FX_MODE_GRADIENT 46 | ||
| 182 | #define FX_MODE_LOADING 47 | ||
| 183 | #define FX_MODE_ROLLINGBALLS 48 //was Police before 0.14 | ||
| 184 | #define FX_MODE_FAIRY 49 //was Police All prior to 0.13.0-b6 (use "Two Dots" with Red/Blue and full intensity) | ||
| 185 | #define FX_MODE_TWO_DOTS 50 | ||
| 186 | #define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity) | ||
| 187 | #define FX_MODE_RUNNING_DUAL 52 | ||
| 188 | #define FX_MODE_IMAGE 53 | ||
| 189 | #define FX_MODE_TRICOLOR_CHASE 54 | ||
| 190 | #define FX_MODE_TRICOLOR_WIPE 55 | ||
| 191 | #define FX_MODE_TRICOLOR_FADE 56 | ||
| 192 | #define FX_MODE_LIGHTNING 57 | ||
| 193 | #define FX_MODE_ICU 58 | ||
| 194 | #define FX_MODE_MULTI_COMET 59 | ||
| 195 | #define FX_MODE_DUAL_LARSON_SCANNER 60 // candidate for removal (use Scanner with with check 1) | ||
| 196 | #define FX_MODE_RANDOM_CHASE 61 | ||
| 197 | #define FX_MODE_OSCILLATE 62 | ||
| 198 | #define FX_MODE_PRIDE_2015 63 | ||
| 199 | #define FX_MODE_JUGGLE 64 | ||
| 200 | #define FX_MODE_PALETTE 65 | ||
| 201 | #define FX_MODE_FIRE_2012 66 | ||
| 202 | #define FX_MODE_COLORWAVES 67 | ||
| 203 | #define FX_MODE_BPM 68 | ||
| 204 | #define FX_MODE_FILLNOISE8 69 | ||
| 205 | #define FX_MODE_NOISE16_1 70 | ||
| 206 | #define FX_MODE_NOISE16_2 71 | ||
| 207 | #define FX_MODE_NOISE16_3 72 | ||
| 208 | #define FX_MODE_NOISE16_4 73 | ||
| 209 | #define FX_MODE_COLORTWINKLE 74 | ||
| 210 | #define FX_MODE_LAKE 75 | ||
| 211 | #define FX_MODE_METEOR 76 | ||
| 212 | #define FX_MODE_COPY 77 // was METEOR_SMOOTH (merged with meteor); reused upstream for Copy Segment | ||
| 213 | #define FX_MODE_RAILWAY 78 | ||
| 214 | #define FX_MODE_RIPPLE 79 | ||
| 215 | #define FX_MODE_TWINKLEFOX 80 | ||
| 216 | #define FX_MODE_TWINKLECAT 81 | ||
| 217 | #define FX_MODE_HALLOWEEN_EYES 82 | ||
| 218 | #define FX_MODE_STATIC_PATTERN 83 | ||
| 219 | #define FX_MODE_TRI_STATIC_PATTERN 84 | ||
| 220 | #define FX_MODE_SPOTS 85 | ||
| 221 | #define FX_MODE_SPOTS_FADE 86 | ||
| 222 | #define FX_MODE_GLITTER 87 | ||
| 223 | #define FX_MODE_CANDLE 88 | ||
| 224 | #define FX_MODE_STARBURST 89 | ||
| 225 | #define FX_MODE_EXPLODING_FIREWORKS 90 | ||
| 226 | #define FX_MODE_BOUNCINGBALLS 91 | ||
| 227 | #define FX_MODE_SINELON 92 | ||
| 228 | #define FX_MODE_SINELON_DUAL 93 | ||
| 229 | #define FX_MODE_SINELON_RAINBOW 94 | ||
| 230 | #define FX_MODE_POPCORN 95 | ||
| 231 | #define FX_MODE_DRIP 96 | ||
| 232 | #define FX_MODE_PLASMA 97 | ||
| 233 | #define FX_MODE_PERCENT 98 | ||
| 234 | #define FX_MODE_RIPPLE_RAINBOW 99 | ||
| 235 | #define FX_MODE_HEARTBEAT 100 | ||
| 236 | #define FX_MODE_PACIFICA 101 | ||
| 237 | #define FX_MODE_CANDLE_MULTI 102 | ||
| 238 | #define FX_MODE_SOLID_GLITTER 103 // candidate for removal (use glitter) | ||
| 239 | #define FX_MODE_SUNRISE 104 | ||
| 240 | #define FX_MODE_PHASED 105 | ||
| 241 | #define FX_MODE_TWINKLEUP 106 | ||
| 242 | #define FX_MODE_NOISEPAL 107 | ||
| 243 | #define FX_MODE_SINEWAVE 108 | ||
| 244 | #define FX_MODE_PHASEDNOISE 109 | ||
| 245 | #define FX_MODE_FLOW 110 | ||
| 246 | #define FX_MODE_CHUNCHUN 111 | ||
| 247 | #define FX_MODE_DANCING_SHADOWS 112 | ||
| 248 | #define FX_MODE_WASHING_MACHINE 113 | ||
| 249 | #define FX_MODE_2DPLASMAROTOZOOM 114 // was Candy Cane prior to 0.14 (use Chase 2) | ||
| 250 | #define FX_MODE_BLENDS 115 | ||
| 251 | #define FX_MODE_TV_SIMULATOR 116 | ||
| 252 | #define FX_MODE_DYNAMIC_SMOOTH 117 // candidate for removal (check3 in dynamic) | ||
| 253 | |||
| 254 | // new 0.14 2D effects | ||
| 255 | #define FX_MODE_2DSPACESHIPS 118 //gap fill | ||
| 256 | #define FX_MODE_2DCRAZYBEES 119 //gap fill | ||
| 257 | #define FX_MODE_2DGHOSTRIDER 120 //gap fill | ||
| 258 | #define FX_MODE_2DBLOBS 121 //gap fill | ||
| 259 | #define FX_MODE_2DSCROLLTEXT 122 //gap fill | ||
| 260 | #define FX_MODE_2DDRIFTROSE 123 //gap fill | ||
| 261 | #define FX_MODE_2DDISTORTIONWAVES 124 //gap fill | ||
| 262 | #define FX_MODE_2DSOAP 125 //gap fill | ||
| 263 | #define FX_MODE_2DOCTOPUS 126 //gap fill | ||
| 264 | #define FX_MODE_2DWAVINGCELL 127 //gap fill | ||
| 265 | |||
| 266 | // WLED-SR effects (SR compatible IDs !!!) | ||
| 267 | #define FX_MODE_PIXELS 128 | ||
| 268 | #define FX_MODE_PIXELWAVE 129 | ||
| 269 | #define FX_MODE_JUGGLES 130 | ||
| 270 | #define FX_MODE_MATRIPIX 131 | ||
| 271 | #define FX_MODE_GRAVIMETER 132 | ||
| 272 | #define FX_MODE_PLASMOID 133 | ||
| 273 | #define FX_MODE_PUDDLES 134 | ||
| 274 | #define FX_MODE_MIDNOISE 135 | ||
| 275 | #define FX_MODE_NOISEMETER 136 | ||
| 276 | #define FX_MODE_FREQWAVE 137 | ||
| 277 | #define FX_MODE_FREQMATRIX 138 | ||
| 278 | #define FX_MODE_2DGEQ 139 | ||
| 279 | #define FX_MODE_WATERFALL 140 | ||
| 280 | #define FX_MODE_FREQPIXELS 141 | ||
| 281 | #define FX_MODE_BINMAP 142 | ||
| 282 | #define FX_MODE_NOISEFIRE 143 | ||
| 283 | #define FX_MODE_PUDDLEPEAK 144 | ||
| 284 | #define FX_MODE_NOISEMOVE 145 | ||
| 285 | #define FX_MODE_2DNOISE 146 | ||
| 286 | #define FX_MODE_PERLINMOVE 147 | ||
| 287 | #define FX_MODE_RIPPLEPEAK 148 | ||
| 288 | #define FX_MODE_2DFIRENOISE 149 | ||
| 289 | #define FX_MODE_2DSQUAREDSWIRL 150 | ||
| 290 | #define FX_MODE_PACMAN 151 // gap fill (was 2DFIRE2012). Do NOT renumber; SR-ID range must remain stable. | ||
| 291 | #define FX_MODE_2DDNA 152 | ||
| 292 | #define FX_MODE_2DMATRIX 153 | ||
| 293 | #define FX_MODE_2DMETABALLS 154 | ||
| 294 | #define FX_MODE_FREQMAP 155 | ||
| 295 | #define FX_MODE_GRAVCENTER 156 | ||
| 296 | #define FX_MODE_GRAVCENTRIC 157 | ||
| 297 | #define FX_MODE_GRAVFREQ 158 | ||
| 298 | #define FX_MODE_DJLIGHT 159 | ||
| 299 | #define FX_MODE_2DFUNKYPLANK 160 | ||
| 300 | #define FX_MODE_SHIMMER 161 // gap fill, non-SR 1D effect | ||
| 301 | #define FX_MODE_2DPULSER 162 | ||
| 302 | #define FX_MODE_BLURZ 163 | ||
| 303 | #define FX_MODE_2DDRIFT 164 | ||
| 304 | #define FX_MODE_2DWAVERLY 165 | ||
| 305 | #define FX_MODE_2DSUNRADIATION 166 | ||
| 306 | #define FX_MODE_2DCOLOREDBURSTS 167 | ||
| 307 | #define FX_MODE_2DJULIA 168 | ||
| 308 | // #define FX_MODE_2DPOOLNOISE 169 //have been removed in WLED SR in the past because of low mem but should be added back | ||
| 309 | // #define FX_MODE_2DTWISTER 170 //have been removed in WLED SR in the past because of low mem but should be added back | ||
| 310 | // #define FX_MODE_2DCAELEMENTATY 171 //have been removed in WLED SR in the past because of low mem but should be added back | ||
| 311 | #define FX_MODE_2DGAMEOFLIFE 172 | ||
| 312 | #define FX_MODE_2DTARTAN 173 | ||
| 313 | #define FX_MODE_2DPOLARLIGHTS 174 | ||
| 314 | #define FX_MODE_2DSWIRL 175 | ||
| 315 | #define FX_MODE_2DLISSAJOUS 176 | ||
| 316 | #define FX_MODE_2DFRIZZLES 177 | ||
| 317 | #define FX_MODE_2DPLASMABALL 178 | ||
| 318 | #define FX_MODE_FLOWSTRIPE 179 | ||
| 319 | #define FX_MODE_2DHIPHOTIC 180 | ||
| 320 | #define FX_MODE_2DSINDOTS 181 | ||
| 321 | #define FX_MODE_2DDNASPIRAL 182 | ||
| 322 | #define FX_MODE_2DBLACKHOLE 183 | ||
| 323 | #define FX_MODE_WAVESINS 184 | ||
| 324 | #define FX_MODE_ROCKTAVES 185 | ||
| 325 | #define FX_MODE_2DAKEMI 186 | ||
| 326 | #define FX_MODE_PARTICLEVOLCANO 187 | ||
| 327 | #define FX_MODE_PARTICLEFIRE 188 | ||
| 328 | #define FX_MODE_PARTICLEFIREWORKS 189 | ||
| 329 | #define FX_MODE_PARTICLEVORTEX 190 | ||
| 330 | #define FX_MODE_PARTICLEPERLIN 191 | ||
| 331 | #define FX_MODE_PARTICLEPIT 192 | ||
| 332 | #define FX_MODE_PARTICLEBOX 193 | ||
| 333 | #define FX_MODE_PARTICLEATTRACTOR 194 | ||
| 334 | #define FX_MODE_PARTICLEIMPACT 195 | ||
| 335 | #define FX_MODE_PARTICLEWATERFALL 196 | ||
| 336 | #define FX_MODE_PARTICLESPRAY 197 | ||
| 337 | #define FX_MODE_PARTICLESGEQ 198 | ||
| 338 | #define FX_MODE_PARTICLECENTERGEQ 199 | ||
| 339 | #define FX_MODE_PARTICLEGHOSTRIDER 200 | ||
| 340 | #define FX_MODE_PARTICLEBLOBS 201 | ||
| 341 | #define FX_MODE_PSDRIP 202 | ||
| 342 | #define FX_MODE_PSPINBALL 203 | ||
| 343 | #define FX_MODE_PSDANCINGSHADOWS 204 | ||
| 344 | #define FX_MODE_PSFIREWORKS1D 205 | ||
| 345 | #define FX_MODE_PSSPARKLER 206 | ||
| 346 | #define FX_MODE_PSHOURGLASS 207 | ||
| 347 | #define FX_MODE_PS1DSPRAY 208 | ||
| 348 | #define FX_MODE_PSBALANCE 209 | ||
| 349 | #define FX_MODE_PSCHASE 210 | ||
| 350 | #define FX_MODE_PSSTARBURST 211 | ||
| 351 | #define FX_MODE_PS1DGEQ 212 | ||
| 352 | #define FX_MODE_PSFIRE1D 213 | ||
| 353 | #define FX_MODE_PS1DSONICSTREAM 214 | ||
| 354 | #define FX_MODE_PS1DSONICBOOM 215 | ||
| 355 | #define FX_MODE_PS1DSPRINGY 216 | ||
| 356 | #define FX_MODE_PARTICLEGALAXY 217 | ||
| 357 | #define FX_MODE_COLORCLOUDS 218 | ||
| 358 | #define FX_MODE_SLOW_TRANSITION 219 | ||
| 359 | #define MODE_COUNT 220 | ||
| 360 | |||
| 361 | |||
| 362 | #define BLEND_STYLE_FADE 0x00 // universal | ||
| 363 | #define BLEND_STYLE_FAIRY_DUST 0x01 // universal | ||
| 364 | #define BLEND_STYLE_SWIPE_RIGHT 0x02 // 1D or 2D | ||
| 365 | #define BLEND_STYLE_SWIPE_LEFT 0x03 // 1D or 2D | ||
| 366 | #define BLEND_STYLE_PINCH_OUT 0x04 // 1D or 2D | ||
| 367 | #define BLEND_STYLE_INSIDE_OUT 0x05 // 1D or 2D | ||
| 368 | #define BLEND_STYLE_SWIPE_UP 0x06 // 2D | ||
| 369 | #define BLEND_STYLE_SWIPE_DOWN 0x07 // 2D | ||
| 370 | #define BLEND_STYLE_OPEN_H 0x08 // 2D | ||
| 371 | #define BLEND_STYLE_OPEN_V 0x09 // 2D | ||
| 372 | // as there are many push variants to optimise if statements they are groupped together | ||
| 373 | #define BLEND_STYLE_PUSH_RIGHT 0x10 // 1D or 2D (& 0b00010000) | ||
| 374 | #define BLEND_STYLE_PUSH_LEFT 0x11 // 1D or 2D (& 0b00010000) | ||
| 375 | #define BLEND_STYLE_PUSH_UP 0x12 // 2D (& 0b00010000) | ||
| 376 | #define BLEND_STYLE_PUSH_DOWN 0x13 // 2D (& 0b00010000) | ||
| 377 | #define BLEND_STYLE_PUSH_TL 0x14 // 2D (& 0b00010000) | ||
| 378 | #define BLEND_STYLE_PUSH_TR 0x15 // 2D (& 0b00010000) | ||
| 379 | #define BLEND_STYLE_PUSH_BR 0x16 // 2D (& 0b00010000) | ||
| 380 | #define BLEND_STYLE_PUSH_BL 0x17 // 2D (& 0b00010000) | ||
| 381 | #define BLEND_STYLE_PUSH_MASK 0x10 | ||
| 382 | #define BLEND_STYLE_COUNT 18 | ||
| 383 | |||
| 384 | |||
| 385 | typedef enum mapping1D2D { | ||
| 386 | M12_Pixels = 0, | ||
| 387 | M12_pBar = 1, | ||
| 388 | M12_pArc = 2, | ||
| 389 | M12_pCorner = 3, | ||
| 390 | M12_sPinwheel = 4 | ||
| 391 | } mapping1D2D_t; | ||
| 392 | |||
| 393 | // segment, 68 bytes | ||
| 394 | typedef struct Segment { | ||
| 395 | public: | ||
| 396 | uint16_t start; // start index / start X coordinate 2D (left) | ||
| 397 | uint16_t stop; // stop index / stop X coordinate 2D (right); segment is invalid if stop == 0 | ||
| 398 | uint16_t offset; | ||
| 399 | uint8_t speed; | ||
| 400 | uint8_t intensity; | ||
| 401 | uint8_t palette; | ||
| 402 | uint8_t mode; | ||
| 403 | union { | ||
| 404 | uint16_t options; //bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected | ||
| 405 | struct { | ||
| 406 | bool selected : 1; // 0 : selected | ||
| 407 | bool reverse : 1; // 1 : reversed | ||
| 408 | bool on : 1; // 2 : is On | ||
| 409 | bool mirror : 1; // 3 : mirrored | ||
| 410 | bool freeze : 1; // 4 : paused/frozen | ||
| 411 | bool reset : 1; // 5 : indicates that Segment runtime requires reset | ||
| 412 | bool reverse_y : 1; // 6 : reversed Y (2D) | ||
| 413 | bool mirror_y : 1; // 7 : mirrored Y (2D) | ||
| 414 | bool transpose : 1; // 8 : transposed (2D, swapped X & Y) | ||
| 415 | 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, ...) | ||
| 416 | uint8_t soundSim : 2; // 12-13 : 0-3 sound simulation types ("soft" & "hard" or "on"/"off") | ||
| 417 | uint8_t set : 2; // 14-15 : 0-3 UI segment sets/groups | ||
| 418 | }; | ||
| 419 | }; | ||
| 420 | uint8_t grouping, spacing; | ||
| 421 | uint8_t opacity; | ||
| 422 | uint32_t colors[NUM_COLORS]; | ||
| 423 | uint8_t cct; //0==1900K, 255==10091K | ||
| 424 | uint8_t custom1, custom2; // custom FX parameters/sliders | ||
| 425 | struct { | ||
| 426 | uint8_t custom3 : 5; // reduced range slider (0-31) | ||
| 427 | bool check1 : 1; // checkmark 1 | ||
| 428 | bool check2 : 1; // checkmark 2 | ||
| 429 | bool check3 : 1; // checkmark 3 | ||
| 430 | }; | ||
| 431 | uint8_t startY; // start Y coodrinate 2D (top); there should be no more than 255 rows | ||
| 432 | uint8_t stopY; // stop Y coordinate 2D (bottom); there should be no more than 255 rows | ||
| 433 | // note: two bytes of padding are added here | ||
| 434 | char *name; | ||
| 435 | |||
| 436 | // runtime data | ||
| 437 | unsigned long next_time; // millis() of next update | ||
| 438 | uint32_t step; // custom "step" var | ||
| 439 | uint32_t call; // call counter | ||
| 440 | uint16_t aux0; // custom var | ||
| 441 | uint16_t aux1; // custom var | ||
| 442 | byte *data; // effect data pointer | ||
| 443 | static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions) | ||
| 444 | |||
| 445 | typedef struct TemporarySegmentData { | ||
| 446 | uint16_t _optionsT; | ||
| 447 | uint32_t _colorT[NUM_COLORS]; | ||
| 448 | uint8_t _speedT; | ||
| 449 | uint8_t _intensityT; | ||
| 450 | uint8_t _custom1T, _custom2T; // custom FX parameters/sliders | ||
| 451 | struct { | ||
| 452 | uint8_t _custom3T : 5; // reduced range slider (0-31) | ||
| 453 | bool _check1T : 1; // checkmark 1 | ||
| 454 | bool _check2T : 1; // checkmark 2 | ||
| 455 | bool _check3T : 1; // checkmark 3 | ||
| 456 | }; | ||
| 457 | uint16_t _aux0T; | ||
| 458 | uint16_t _aux1T; | ||
| 459 | uint32_t _stepT; | ||
| 460 | uint32_t _callT; | ||
| 461 | uint8_t *_dataT; | ||
| 462 | unsigned _dataLenT; | ||
| 463 | TemporarySegmentData() | ||
| 464 | : _dataT(nullptr) // just in case... | ||
| 465 | , _dataLenT(0) | ||
| 466 | {} | ||
| 467 | } tmpsegd_t; | ||
| 468 | |||
| 469 | private: | ||
| 470 | union { | ||
| 471 | uint8_t _capabilities; | ||
| 472 | struct { | ||
| 473 | bool _isRGB : 1; | ||
| 474 | bool _hasW : 1; | ||
| 475 | bool _isCCT : 1; | ||
| 476 | bool _manualW : 1; | ||
| 477 | uint8_t _reserved : 4; | ||
| 478 | }; | ||
| 479 | }; | ||
| 480 | uint8_t _default_palette; // palette number that gets assigned to pal0 | ||
| 481 | unsigned _dataLen; | ||
| 482 | static unsigned _usedSegmentData; | ||
| 483 | static uint8_t _segBri; // brightness of segment for current effect | ||
| 484 | static unsigned _vLength; // 1D dimension used for current effect | ||
| 485 | static unsigned _vWidth, _vHeight; // 2D dimensions used for current effect | ||
| 486 | static uint32_t _currentColors[NUM_COLORS]; // colors used for current effect | ||
| 487 | static bool _colorScaled; // color has been scaled prior to setPixelColor() call | ||
| 488 | static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette()) | ||
| 489 | static CRGBPalette16 _randomPalette; // actual random palette | ||
| 490 | static CRGBPalette16 _newRandomPalette; // target random palette | ||
| 491 | static uint16_t _lastPaletteChange; // last random palette change time in millis()/1000 | ||
| 492 | static uint16_t _lastPaletteBlend; // blend palette according to set Transition Delay in millis()%0xFFFF | ||
| 493 | static uint16_t _transitionprogress; // current transition progress 0 - 0xFFFF | ||
| 494 | #ifndef WLED_DISABLE_MODE_BLEND | ||
| 495 | static bool _modeBlend; // mode/effect blending semaphore | ||
| 496 | // clipping | ||
| 497 | static uint16_t _clipStart, _clipStop; | ||
| 498 | static uint8_t _clipStartY, _clipStopY; | ||
| 499 | #endif | ||
| 500 | |||
| 501 | // transition data, valid only if transitional==true, holds values during transition (72 bytes) | ||
| 502 | struct Transition { | ||
| 503 | #ifndef WLED_DISABLE_MODE_BLEND | ||
| 504 | tmpsegd_t _segT; // previous segment environment | ||
| 505 | uint8_t _modeT; // previous mode/effect | ||
| 506 | #else | ||
| 507 | uint32_t _colorT[NUM_COLORS]; | ||
| 508 | #endif | ||
| 509 | uint8_t _palTid; // previous palette | ||
| 510 | uint8_t _briT; // temporary brightness | ||
| 511 | uint8_t _cctT; // temporary CCT | ||
| 512 | CRGBPalette16 _palT; // temporary palette | ||
| 513 | uint8_t _prevPaletteBlends; // number of previous palette blends (there are max 255 blends possible) | ||
| 514 | unsigned long _start; // must accommodate millis() | ||
| 515 | uint16_t _dur; | ||
| 516 | // -> here is one byte of padding | ||
| 517 | 1196 | Transition(uint16_t dur=750) | |
| 518 |
1/2✓ Branch 0 taken 1196 times.
✗ Branch 1 not taken.
|
1196 | : _palT(CRGBPalette16(CRGB::Black)) |
| 519 | 1196 | , _prevPaletteBlends(0) | |
| 520 | 1196 | , _start(millis()) | |
| 521 | 1196 | , _dur(dur) | |
| 522 | 1196 | {} | |
| 523 | } *_t; | ||
| 524 | |||
| 525 | [[gnu::hot]] void _setPixelColorXY_raw(const int& x, const int& y, uint32_t& col) const; // set pixel without mapping (internal use only) | ||
| 526 | |||
| 527 | public: | ||
| 528 | |||
| 529 | 1196 | Segment(uint16_t sStart=0, uint16_t sStop=30) : | |
| 530 | 1196 | start(sStart), | |
| 531 | 1196 | stop(sStop), | |
| 532 | 1196 | offset(0), | |
| 533 | 1196 | speed(DEFAULT_SPEED), | |
| 534 | 1196 | intensity(DEFAULT_INTENSITY), | |
| 535 | 1196 | palette(0), | |
| 536 | 1196 | mode(DEFAULT_MODE), | |
| 537 | 1196 | options(SELECTED | SEGMENT_ON), | |
| 538 | 1196 | grouping(1), | |
| 539 | 1196 | spacing(0), | |
| 540 | 1196 | opacity(255), | |
| 541 | 1196 | colors{DEFAULT_COLOR,BLACK,BLACK}, | |
| 542 | 1196 | cct(127), | |
| 543 | 1196 | custom1(DEFAULT_C1), | |
| 544 | 1196 | custom2(DEFAULT_C2), | |
| 545 | 1196 | custom3(DEFAULT_C3), | |
| 546 | 1196 | check1(false), | |
| 547 | 1196 | check2(false), | |
| 548 | 1196 | check3(false), | |
| 549 | 1196 | startY(0), | |
| 550 | 1196 | stopY(1), | |
| 551 | 1196 | name(nullptr), | |
| 552 | 1196 | next_time(0), | |
| 553 | 1196 | step(0), | |
| 554 | 1196 | call(0), | |
| 555 | 1196 | aux0(0), | |
| 556 | 1196 | aux1(0), | |
| 557 | 1196 | data(nullptr), | |
| 558 | 1196 | _capabilities(0), | |
| 559 | 1196 | _default_palette(0), | |
| 560 | 1196 | _dataLen(0), | |
| 561 | 1196 | _t(nullptr) | |
| 562 | { | ||
| 563 | #ifdef WLED_DEBUG | ||
| 564 | //Serial.printf("-- Creating segment: %p\n", this); | ||
| 565 | #endif | ||
| 566 | 1196 | } | |
| 567 | |||
| 568 | 1196 | Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) : Segment(sStartX, sStopX) { | |
| 569 | 1196 | startY = sStartY; | |
| 570 | 1196 | stopY = sStopY; | |
| 571 | 1196 | } | |
| 572 | |||
| 573 | Segment(const Segment &orig); // copy constructor | ||
| 574 | Segment(Segment &&orig) noexcept; // move constructor | ||
| 575 | |||
| 576 | 2366 | ~Segment() { | |
| 577 | #ifdef WLED_DEBUG | ||
| 578 | //Serial.printf("-- Destroying segment: %p", this); | ||
| 579 | //if (name) Serial.printf(" %s (%p)", name, name); | ||
| 580 | //if (data) Serial.printf(" %d->(%p)", (int)_dataLen, data); | ||
| 581 | //Serial.println(); | ||
| 582 | #endif | ||
| 583 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2364 times.
|
2366 | if (name) { free(name); name = nullptr; } |
| 584 | 2366 | stopTransition(); | |
| 585 | 2366 | deallocateData(); | |
| 586 | 2366 | } | |
| 587 | |||
| 588 | Segment& operator= (const Segment &orig); // copy assignment | ||
| 589 | Segment& operator= (Segment &&orig) noexcept; // move assignment | ||
| 590 | |||
| 591 | #ifdef WLED_DEBUG | ||
| 592 | size_t getSize() const { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0); } | ||
| 593 | #endif | ||
| 594 | |||
| 595 | inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); } | ||
| 596 | ✗ | inline bool isSelected() const { return selected; } | |
| 597 | 76465 | inline bool isInTransition() const { return _t != nullptr; } | |
| 598 | 7326894 | inline bool isActive() const { return stop > start; } | |
| 599 | inline bool hasRGB() const { return _isRGB; } | ||
| 600 | inline bool hasWhite() const { return _hasW; } | ||
| 601 | inline bool isCCT() const { return _isCCT; } | ||
| 602 |
1/2✓ Branch 0 taken 3154236 times.
✗ Branch 1 not taken.
|
3154236 | inline uint16_t width() const { return isActive() ? (stop - start) : 0; } // segment width in physical pixels (length if 1D) |
| 603 | 3154525 | inline uint16_t height() const { return stopY - startY; } // segment height (if 2D) in physical pixels (it *is* always >=1) | |
| 604 | 236033 | inline uint16_t length() const { return width() * height(); } // segment length (count) in physical pixels | |
| 605 | 3957145 | inline uint16_t groupLength() const { return grouping + spacing; } | |
| 606 | ✗ | inline uint8_t getLightCapabilities() const { return _capabilities; } | |
| 607 | inline void deactivate() { setGeometry(0,0); } | ||
| 608 | ✗ | inline Segment &clearName() { if (name) free(name); name = nullptr; return *this; } | |
| 609 | inline Segment &setName(const String &name) { return setName(name.c_str()); } | ||
| 610 | |||
| 611 | 1161 | inline static unsigned getUsedSegmentData() { return Segment::_usedSegmentData; } | |
| 612 | 775 | inline static void addUsedSegmentData(int len) { Segment::_usedSegmentData += len; } | |
| 613 | #ifndef WLED_DISABLE_MODE_BLEND | ||
| 614 | inline static void modeBlend(bool blend) { _modeBlend = blend; } | ||
| 615 | inline static bool getmodeBlend(void) { return _modeBlend; } | ||
| 616 | #endif | ||
| 617 | // point the static draw dimensions at this segment, so the pixel accessors address it | ||
| 618 | ✗ | inline void setDrawDimensions() const { Segment::_vWidth = virtualWidth(); Segment::_vHeight = virtualHeight(); Segment::_vLength = virtualLength(); } | |
| 619 | 2323231 | inline static unsigned vLength() { return Segment::_vLength; } | |
| 620 | 4615250 | inline static unsigned vWidth() { return Segment::_vWidth; } | |
| 621 | 3889493 | inline static unsigned vHeight() { return Segment::_vHeight; } | |
| 622 | 940459 | inline static uint32_t getCurrentColor(unsigned i) { return Segment::_currentColors[i]; } // { return i < 3 ? Segment::_currentColors[i] : 0; } | |
| 623 | 149394 | inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; } | |
| 624 | inline static uint8_t getCurrentBrightness() { return Segment::_segBri; } | ||
| 625 | static void handleRandomPalette(); | ||
| 626 | |||
| 627 | void beginDraw(); // set up parameters for current effect | ||
| 628 | 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); | ||
| 629 | Segment &setColor(uint8_t slot, uint32_t c); | ||
| 630 | Segment &setCCT(uint16_t k); | ||
| 631 | Segment &setOpacity(uint8_t o); | ||
| 632 | Segment &setOption(uint8_t n, bool val); | ||
| 633 | Segment &setMode(uint8_t fx, bool loadDefaults = false); | ||
| 634 | Segment &setPalette(uint8_t pal); | ||
| 635 | Segment &setName(const char* name); | ||
| 636 | uint8_t differs(const Segment& b) const; | ||
| 637 | void refreshLightCapabilities(); | ||
| 638 | |||
| 639 | // runtime data functions | ||
| 640 | inline uint16_t dataSize() const { return _dataLen; } | ||
| 641 | bool allocateData(size_t len); // allocates effect data buffer in heap and clears it | ||
| 642 | void deallocateData(); // deallocates (frees) effect data buffer from heap | ||
| 643 | void resetIfRequired(); // sets all SEGENV variables to 0 and clears data buffer | ||
| 644 | /** | ||
| 645 | * Flags that before the next effect is calculated, | ||
| 646 | * the internal segment state should be reset. | ||
| 647 | * Call resetIfRequired before calling the next effect function. | ||
| 648 | * Safe to call from interrupts and network requests. | ||
| 649 | */ | ||
| 650 | 2392 | inline Segment &markForReset() { reset = true; return *this; } // setOption(SEG_OPTION_RESET, true) | |
| 651 | |||
| 652 | // transition functions | ||
| 653 | void startTransition(uint16_t dur); // transition has to start before actual segment values change | ||
| 654 | void stopTransition(); // ends transition mode by destroying transition structure (does nothing if not in transition) | ||
| 655 |
2/2✓ Branch 0 taken 2649 times.
✓ Branch 1 taken 5902 times.
|
8551 | inline void handleTransition() { updateTransitionProgress(); if (progress() == 0xFFFFU) stopTransition(); } |
| 656 | #ifndef WLED_DISABLE_MODE_BLEND | ||
| 657 | void swapSegenv(tmpsegd_t &tmpSegD); // copies segment data into specifed buffer, if buffer is not a transition buffer, segment data is overwritten from transition buffer | ||
| 658 | void restoreSegenv(const tmpsegd_t &tmpSegD); // restores segment data from buffer, if buffer is not transition buffer, changed values are copied to transition buffer | ||
| 659 | #endif | ||
| 660 | [[gnu::hot]] void updateTransitionProgress(); // set current progression of transition | ||
| 661 | 26257 | inline uint16_t progress() const { return Segment::_transitionprogress; } // transition progression between 0-65535 | |
| 662 | [[gnu::hot]] uint8_t currentBri(bool useCct = false) const; // current segment brightness/CCT (blended while in transition) | ||
| 663 | uint8_t currentMode() const; // currently active effect/mode (while in transition) | ||
| 664 | [[gnu::hot]] uint32_t currentColor(uint8_t slot) const; // currently active segment color (blended while in transition) | ||
| 665 | CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal); | ||
| 666 | void loadOldPalette(); // loads old FX palette into _currentPalette | ||
| 667 | |||
| 668 | // 1D strip | ||
| 669 | [[gnu::hot]] uint16_t virtualLength() const; | ||
| 670 | [[gnu::hot]] void setPixelColor(int i, uint32_t c) const; // set relative pixel within segment with color | ||
| 671 | 632457 | inline void setPixelColor(unsigned n, uint32_t c) const { setPixelColor(int(n), c); } | |
| 672 | 19665 | inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) const { setPixelColor(n, RGBW32(r,g,b,w)); } | |
| 673 | 181962 | inline void setPixelColor(int n, CRGB c) const { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); } | |
| 674 | #ifdef WLED_USE_AA_PIXELS | ||
| 675 | void setPixelColor(float i, uint32_t c, bool aa = true) const; | ||
| 676 | 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); } | ||
| 677 | inline void setPixelColor(float i, CRGB c, bool aa = true) const { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); } | ||
| 678 | #endif | ||
| 679 | #ifndef WLED_DISABLE_MODE_BLEND | ||
| 680 | static inline void setClippingRect(int startX, int stopX, int startY = 0, int stopY = 1) { _clipStart = startX; _clipStop = stopX; _clipStartY = startY; _clipStopY = stopY; }; | ||
| 681 | #endif | ||
| 682 | bool isPixelClipped(int i) const; | ||
| 683 | [[gnu::hot]] uint32_t getPixelColor(int i) const; | ||
| 684 | // 1D support functions (some implement 2D as well) | ||
| 685 | void blur(uint8_t, bool smear = false); | ||
| 686 | void clear(); | ||
| 687 | void fill(uint32_t c); | ||
| 688 | void fade_out(uint8_t r); | ||
| 689 | void fadeToSecondaryBy(uint8_t fadeBy); | ||
| 690 | void fadeToBlackBy(uint8_t fadeBy); | ||
| 691 | 31968 | inline void blendPixelColor(int n, uint32_t color, uint8_t blend) { setPixelColor(n, color_blend(getPixelColor(n), color, blend)); } | |
| 692 | 7511 | inline void blendPixelColor(int n, CRGB c, uint8_t blend) { blendPixelColor(n, RGBW32(c.r,c.g,c.b,0), blend); } | |
| 693 | 7594 | inline void addPixelColor(int n, uint32_t color, bool preserveCR = true) { setPixelColor(n, color_add(getPixelColor(n), color, preserveCR)); } | |
| 694 | inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool preserveCR = true) { addPixelColor(n, RGBW32(r,g,b,w), preserveCR); } | ||
| 695 | inline void addPixelColor(int n, CRGB c, bool preserveCR = true) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), preserveCR); } | ||
| 696 | inline void fadePixelColor(uint16_t n, uint8_t fade) { setPixelColor(n, color_fade(getPixelColor(n), fade, true)); } | ||
| 697 | [[gnu::hot]] uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255) const; | ||
| 698 | [[gnu::hot]] uint32_t color_wheel(uint8_t pos) const; | ||
| 699 | |||
| 700 | // 2D Blur: shortcuts for bluring columns or rows only (50% faster than full 2D blur) | ||
| 701 | 4 | inline void blurCols(fract8 blur_amount, bool smear = false) { // blur all columns | |
| 702 | 4 | blur2D(0, blur_amount, smear); | |
| 703 | 4 | } | |
| 704 | inline void blurRows(fract8 blur_amount, bool smear = false) { // blur all rows | ||
| 705 | blur2D(blur_amount, 0, smear); | ||
| 706 | } | ||
| 707 | |||
| 708 | // 2D matrix | ||
| 709 | [[gnu::hot]] unsigned virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing) | ||
| 710 | [[gnu::hot]] unsigned virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing) | ||
| 711 | 115 | inline unsigned nrOfVStrips() const { // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D) | |
| 712 | #ifndef WLED_DISABLE_2D | ||
| 713 |
3/4✓ Branch 0 taken 90 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
|
115 | return (is2D() && map1D2D == M12_pBar) ? virtualWidth() : 1; |
| 714 | #else | ||
| 715 | return 1; | ||
| 716 | #endif | ||
| 717 | } | ||
| 718 | #ifndef WLED_DISABLE_2D | ||
| 719 |
3/4✓ Branch 0 taken 2144643 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1768640 times.
✓ Branch 3 taken 376003 times.
|
2144643 | inline bool is2D() const { return (width()>1 && height()>1); } |
| 720 | [[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c) const; // set relative pixel within segment with color | ||
| 721 | 128075 | inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) const { setPixelColorXY(int(x), int(y), c); } | |
| 722 | 18 | 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)); } | |
| 723 | 139585 | inline void setPixelColorXY(int x, int y, CRGB c) const { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } | |
| 724 | inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) const { setPixelColorXY(int(x), int(y), RGBW32(c.r,c.g,c.b,0)); } | ||
| 725 | #ifdef WLED_USE_AA_PIXELS | ||
| 726 | void setPixelColorXY(float x, float y, uint32_t c, bool aa = true) const; | ||
| 727 | 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); } | ||
| 728 | 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); } | ||
| 729 | #endif | ||
| 730 | [[gnu::hot]] bool isPixelXYClipped(int x, int y) const; | ||
| 731 | [[gnu::hot]] uint32_t getPixelColorXY(int x, int y) const; | ||
| 732 | // 2D support functions | ||
| 733 | inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); } | ||
| 734 | inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); } | ||
| 735 | 68448 | inline void addPixelColorXY(int x, int y, uint32_t color, bool preserveCR = true) { setPixelColorXY(x, y, color_add(getPixelColorXY(x,y), color, preserveCR)); } | |
| 736 | 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); } | ||
| 737 | inline void addPixelColorXY(int x, int y, CRGB c, bool preserveCR = true) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), preserveCR); } | ||
| 738 | 2832 | inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true)); } | |
| 739 | //void box_blur(unsigned r = 1U, bool smear = false); // 2D box blur | ||
| 740 | void blur2D(uint8_t blur_x, uint8_t blur_y, bool smear = false); | ||
| 741 | void moveX(int delta, bool wrap = false); | ||
| 742 | void moveY(int delta, bool wrap = false); | ||
| 743 | void move(unsigned dir, unsigned delta, bool wrap = false); | ||
| 744 | void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false); | ||
| 745 | inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } | ||
| 746 | void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false); | ||
| 747 | inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } | ||
| 748 | void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false); | ||
| 749 | inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft); } // automatic inline | ||
| 750 | 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, bool usePalGrad = false); | ||
| 751 | inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline | ||
| 752 | 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, bool usePalGrad = false) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0), rotate, usePalGrad); } // automatic inline | ||
| 753 | void wu_pixel(uint32_t x, uint32_t y, CRGB c); | ||
| 754 | inline void fill_solid(CRGB c) { fill(RGBW32(c.r,c.g,c.b,0)); } | ||
| 755 | #else | ||
| 756 | inline bool is2D() const { return false; } | ||
| 757 | inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(x, c); } | ||
| 758 | inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColor(int(x), c); } | ||
| 759 | inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColor(x, RGBW32(r,g,b,w)); } | ||
| 760 | inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0)); } | ||
| 761 | inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColor(int(x), RGBW32(c.r,c.g,c.b,0)); } | ||
| 762 | #ifdef WLED_USE_AA_PIXELS | ||
| 763 | inline void setPixelColorXY(float x, float y, uint32_t c, bool aa = true) { setPixelColor(x, c, aa); } | ||
| 764 | 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); } | ||
| 765 | inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0), aa); } | ||
| 766 | #endif | ||
| 767 | inline bool isPixelXYClipped(int x, int y) { return isPixelClipped(x); } | ||
| 768 | inline uint32_t getPixelColorXY(int x, int y) { return getPixelColor(x); } | ||
| 769 | inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t c, uint8_t blend) { blendPixelColor(x, c, blend); } | ||
| 770 | inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColor(x, RGBW32(c.r,c.g,c.b,0), blend); } | ||
| 771 | inline void addPixelColorXY(int x, int y, uint32_t color, bool saturate = false) { addPixelColor(x, color, saturate); } | ||
| 772 | inline void addPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0, bool saturate = false) { addPixelColor(x, RGBW32(r,g,b,w), saturate); } | ||
| 773 | inline void addPixelColorXY(int x, int y, CRGB c, bool saturate = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), saturate); } | ||
| 774 | inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { fadePixelColor(x, fade); } | ||
| 775 | //inline void box_blur(unsigned i, bool vertical, fract8 blur_amount) {} | ||
| 776 | inline void blur2D(uint8_t blur_x, uint8_t blur_y, bool smear = false) {} | ||
| 777 | inline void blurRow(int row, fract8 blur_amount, bool smear = false) {} | ||
| 778 | inline void blurCol(int col, fract8 blur_amount, bool smear = false) {} | ||
| 779 | inline void moveX(int delta, bool wrap = false) {} | ||
| 780 | inline void moveY(int delta, bool wrap = false) {} | ||
| 781 | inline void move(uint8_t dir, uint8_t delta, bool wrap = false) {} | ||
| 782 | inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false) {} | ||
| 783 | inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) {} | ||
| 784 | inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false) {} | ||
| 785 | inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) {} | ||
| 786 | inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false) {} | ||
| 787 | inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false) {} | ||
| 788 | 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, bool = false) {} | ||
| 789 | inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color) {} | ||
| 790 | 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, bool usePalGrad = false) {} | ||
| 791 | inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {} | ||
| 792 | #endif | ||
| 793 | } segment; | ||
| 794 | //static int segSize = sizeof(Segment); | ||
| 795 | |||
| 796 | // main "strip" class | ||
| 797 | class WS2812FX { // 96 bytes | ||
| 798 | typedef uint16_t (*mode_ptr)(); // pointer to mode function | ||
| 799 | typedef void (*show_callback)(); // pre show callback | ||
| 800 | typedef struct ModeData { | ||
| 801 | uint8_t _id; // mode (effect) id | ||
| 802 | mode_ptr _fcn; // mode (effect) function | ||
| 803 | const char *_data; // mode (effect) name and its UI control data | ||
| 804 | ModeData(uint8_t id, uint16_t (*fcn)(void), const char *data) : _id(id), _fcn(fcn), _data(data) {} | ||
| 805 | } mode_data_t; | ||
| 806 | |||
| 807 | public: | ||
| 808 | |||
| 809 | 3542 | WS2812FX() : | |
| 810 | 3542 | paletteBlend(0), | |
| 811 | 3542 | now(millis()), | |
| 812 | 3542 | timebase(0), | |
| 813 | 3542 | isMatrix(false), | |
| 814 | #ifndef WLED_DISABLE_2D | ||
| 815 | 3542 | panels(1), | |
| 816 | #endif | ||
| 817 | #ifdef WLED_AUTOSEGMENTS | ||
| 818 | autoSegments(true), | ||
| 819 | #else | ||
| 820 | 3542 | autoSegments(false), | |
| 821 | #endif | ||
| 822 | 3542 | correctWB(false), | |
| 823 | 3542 | cctFromRgb(false), | |
| 824 | // true private variables | ||
| 825 | 3542 | _suspend(false), | |
| 826 | 3542 | _length(DEFAULT_LED_COUNT), | |
| 827 | 3542 | _brightness(DEFAULT_BRIGHTNESS), | |
| 828 | 3542 | _transitionDur(750), | |
| 829 | 3542 | _targetFps(WLED_FPS), | |
| 830 | 3542 | _frametime(FRAMETIME_FIXED), | |
| 831 | 3542 | _cumulativeFps(50 << FPS_CALC_SHIFT), | |
| 832 | 3542 | _isServicing(false), | |
| 833 | 3542 | _isOffRefreshRequired(false), | |
| 834 | 3542 | _hasWhiteChannel(false), | |
| 835 | 3542 | _triggered(false), | |
| 836 | 3542 | _modeCount(MODE_COUNT), | |
| 837 | 3542 | _callback(nullptr), | |
| 838 | 3542 | customMappingTable(nullptr), | |
| 839 | 3542 | customMappingSize(0), | |
| 840 | 3542 | _lastShow(0), | |
| 841 | 3542 | _lastServiceShow(0), | |
| 842 | 3542 | _segment_index(0), | |
| 843 | 3542 | _mainSegment(0) | |
| 844 | { | ||
| 845 |
1/2✓ Branch 0 taken 3542 times.
✗ Branch 1 not taken.
|
3542 | _mode.reserve(_modeCount); // allocate memory to prevent initial fragmentation (does not increase size()) |
| 846 |
1/2✓ Branch 0 taken 3542 times.
✗ Branch 1 not taken.
|
3542 | _modeData.reserve(_modeCount); // allocate memory to prevent initial fragmentation (does not increase size()) |
| 847 |
3/6✓ Branch 0 taken 3542 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3542 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3542 times.
|
3542 | if (_mode.capacity() <= 1 || _modeData.capacity() <= 1) _modeCount = 1; // memory allocation failed only show Solid |
| 848 |
1/2✓ Branch 0 taken 3542 times.
✗ Branch 1 not taken.
|
3542 | else setupEffectData(); |
| 849 | 3542 | } | |
| 850 | |||
| 851 | 1628 | ~WS2812FX() { | |
| 852 |
2/2✓ Branch 0 taken 941 times.
✓ Branch 1 taken 687 times.
|
1628 | if (customMappingTable) free(customMappingTable); |
| 853 | 1628 | _mode.clear(); | |
| 854 | 1628 | _modeData.clear(); | |
| 855 | 1628 | _segments.clear(); | |
| 856 | #ifndef WLED_DISABLE_2D | ||
| 857 | 1628 | panel.clear(); | |
| 858 | #endif | ||
| 859 | 1628 | customPalettes.clear(); | |
| 860 | 1628 | } | |
| 861 | |||
| 862 | |||
| 863 | void | ||
| 864 | #ifdef WLED_DEBUG | ||
| 865 | printSize(), // prints memory usage for strip components | ||
| 866 | #endif | ||
| 867 | finalizeInit(), // initialises strip components | ||
| 868 | service(), // executes effect functions when due and calls strip.show() | ||
| 869 | setCCT(uint16_t k), // sets global CCT (either in relative 0-255 value or in K) | ||
| 870 | setBrightness(uint8_t b, bool direct = false), // sets strip brightness | ||
| 871 | setRange(uint16_t i, uint16_t i2, uint32_t col), // used for clock overlay | ||
| 872 | purgeSegments(), // removes inactive segments from RAM (may incure penalty and memory fragmentation but reduces vector footprint) | ||
| 873 | setMainSegmentId(unsigned n = 0), | ||
| 874 | resetSegments(), // marks all segments for reset | ||
| 875 | makeAutoSegments(bool forceReset = false), // will create segments based on configured outputs | ||
| 876 | fixInvalidSegments(), // fixes incorrect segment configuration | ||
| 877 | setPixelColor(unsigned i, uint32_t c) const, // paints absolute strip pixel with index n and color c | ||
| 878 | show(), // initiates LED output | ||
| 879 | setTargetFps(unsigned fps), | ||
| 880 | setupEffectData(); // add default effects to the list; defined in FX.cpp | ||
| 881 | |||
| 882 | inline void resetTimebase() { timebase = 0UL - millis(); } | ||
| 883 |
3/4✓ Branch 0 taken 1196 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1196 times.
✓ Branch 3 taken 3542 times.
|
4738 | inline void restartRuntime() { for (Segment &seg : _segments) { seg.markForReset().resetIfRequired(); } } |
| 884 | inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); } | ||
| 885 | 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)); } | ||
| 886 | inline void setPixelColor(unsigned n, CRGB c) const { setPixelColor(n, c.red, c.green, c.blue); } | ||
| 887 | inline void fill(uint32_t c) const { for (unsigned i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline) | ||
| 888 | ✗ | inline void trigger() { _triggered = true; } // Forces the next frame to be computed on all active segments. | |
| 889 | inline void setShowCallback(show_callback cb) { _callback = cb; } | ||
| 890 | inline void setTransition(uint16_t t) { _transitionDur = t; } // sets transition time (in ms) | ||
| 891 | inline void appendSegment(const Segment &seg = Segment()) { if (_segments.size() < getMaxSegments()) _segments.push_back(seg); } | ||
| 892 | inline void suspend() { _suspend = true; } // will suspend (and canacel) strip.service() execution | ||
| 893 | 3542 | inline void resume() { _suspend = false; } // will resume strip.service() execution | |
| 894 | |||
| 895 | bool | ||
| 896 | checkSegmentAlignment() const, | ||
| 897 | hasRGBWBus() const, | ||
| 898 | hasCCTBus() const, | ||
| 899 | deserializeMap(unsigned n = 0); | ||
| 900 | |||
| 901 | inline bool isUpdating() const { return !BusManager::canAllShow(); } // return true if the strip is being sent pixel updates | ||
| 902 | inline bool isServicing() const { return _isServicing; } // returns true if strip.service() is executing | ||
| 903 | inline bool hasWhiteChannel() const { return _hasWhiteChannel; } // returns true if strip contains separate white chanel | ||
| 904 | 282 | inline bool isOffRefreshRequired() const { return _isOffRefreshRequired; } // returns true if strip requires regular updates (i.e. TM1814 chipset) | |
| 905 | inline bool isSuspended() const { return _suspend; } // returns true if strip.service() execution is suspended | ||
| 906 | inline bool needsUpdate() const { return _triggered; } // returns true if strip received a trigger() request | ||
| 907 | |||
| 908 | uint8_t | ||
| 909 | paletteBlend, | ||
| 910 | getActiveSegmentsNum() const, | ||
| 911 | getFirstSelectedSegId() const, | ||
| 912 | getLastActiveSegmentId() const, | ||
| 913 | getActiveSegsLightCapabilities(bool selectedOnly = false) const, | ||
| 914 | addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name); // add effect to the list; defined in FX.cpp; | ||
| 915 | |||
| 916 | 46 | inline uint8_t getBrightness() const { return _brightness; } // returns current strip brightness | |
| 917 | 179 | inline static constexpr unsigned getMaxSegments() { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value) | |
| 918 | ✗ | inline uint8_t getSegmentsNum() const { return _segments.size(); } // returns currently present segments | |
| 919 | 3419346 | inline uint8_t getCurrSegmentId() const { return _segment_index; } // returns current segment index (only valid while strip.isServicing()) | |
| 920 | ✗ | inline uint8_t getMainSegmentId() const { return _mainSegment; } // returns main segment index | |
| 921 | inline uint8_t getPaletteCount() const { return 13 + GRADIENT_PALETTE_COUNT + customPalettes.size(); } | ||
| 922 | inline uint8_t getTargetFps() const { return _targetFps; } // returns rough FPS value for las 2s interval | ||
| 923 | 2116506 | inline uint8_t getModeCount() const { return _modeCount; } // returns number of registered modes/effects | |
| 924 | |||
| 925 | uint16_t | ||
| 926 | getLengthPhysical() const, | ||
| 927 | getLengthTotal() const; // will include virtual/nonexistent pixels in matrix | ||
| 928 | |||
| 929 | 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) | ||
| 930 | 23509 | inline uint16_t getFrameTime() const { return _frametime; } // returns amount of time a frame should take (in ms) | |
| 931 | inline uint16_t getMinShowDelay() const { return MIN_FRAME_DELAY; } // returns minimum amount of time strip.service() can be delayed (constant) | ||
| 932 | inline uint16_t getLength() const { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H) | ||
| 933 | 11719 | inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms) | |
| 934 | 3570471 | inline uint16_t getMappedPixelIndex(uint16_t index) const { // convert logical address to physical | |
| 935 |
3/6✓ Branch 0 taken 2900507 times.
✓ Branch 1 taken 669964 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2900507 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3570471 | if (index < customMappingSize && (realtimeMode == REALTIME_MODE_INACTIVE || realtimeRespectLedMaps)) index = customMappingTable[index]; |
| 936 | 3570471 | return index; | |
| 937 | }; | ||
| 938 | |||
| 939 | unsigned long now, timebase; | ||
| 940 | uint32_t getPixelColor(unsigned i) const; | ||
| 941 | |||
| 942 | inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call | ||
| 943 | |||
| 944 |
2/4✓ Branch 0 taken 2622046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2622046 times.
✗ Branch 3 not taken.
|
2622046 | const char *getModeData(unsigned id = 0) const { return (id && id < _modeCount) ? _modeData[id] : PSTR("Solid"); } |
| 945 | inline const char **getModeDataSrc() { return &(_modeData[0]); } // vectors use arrays for underlying data | ||
| 946 | |||
| 947 | Segment& getSegment(unsigned id); | ||
| 948 | inline Segment& getFirstSelectedSeg() { return _segments[getFirstSelectedSegId()]; } // returns reference to first segment that is "selected" | ||
| 949 | inline Segment& getMainSegment() { return _segments[getMainSegmentId()]; } // returns reference to main segment | ||
| 950 | inline Segment* getSegments() { return &(_segments[0]); } // returns pointer to segment vector structure (warning: use carefully) | ||
| 951 | |||
| 952 | // 2D support (panels) | ||
| 953 | bool | ||
| 954 | isMatrix; | ||
| 955 | |||
| 956 | #ifndef WLED_DISABLE_2D | ||
| 957 | #define WLED_MAX_PANELS 18 | ||
| 958 | uint8_t | ||
| 959 | panels; | ||
| 960 | |||
| 961 | typedef struct panel_t { | ||
| 962 | uint16_t xOffset; // x offset relative to the top left of matrix in LEDs | ||
| 963 | uint16_t yOffset; // y offset relative to the top left of matrix in LEDs | ||
| 964 | uint8_t width; // width of the panel | ||
| 965 | uint8_t height; // height of the panel | ||
| 966 | union { | ||
| 967 | uint8_t options; | ||
| 968 | struct { | ||
| 969 | bool bottomStart : 1; // starts at bottom? | ||
| 970 | bool rightStart : 1; // starts on right? | ||
| 971 | bool vertical : 1; // is vertical? | ||
| 972 | bool serpentine : 1; // is serpentine? | ||
| 973 | }; | ||
| 974 | }; | ||
| 975 | 1196 | panel_t() | |
| 976 | 1196 | : xOffset(0) | |
| 977 | 1196 | , yOffset(0) | |
| 978 | 1196 | , width(8) | |
| 979 | 1196 | , height(8) | |
| 980 | 1196 | , options(0) | |
| 981 | 1196 | {} | |
| 982 | } Panel; | ||
| 983 | std::vector<Panel> panel; | ||
| 984 | #endif | ||
| 985 | |||
| 986 | void setUpMatrix(); // sets up automatic matrix ledmap from panel configuration | ||
| 987 | |||
| 988 | // outsmart the compiler :) by correctly overloading | ||
| 989 | 2141600 | inline void setPixelColorXY(int x, int y, uint32_t c) const { setPixelColor((unsigned)(y * Segment::maxWidth + x), c); } | |
| 990 | 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)); } | ||
| 991 | inline void setPixelColorXY(int x, int y, CRGB c) const { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } | ||
| 992 | |||
| 993 |
1/2✓ Branch 0 taken 758907 times.
✗ Branch 1 not taken.
|
758907 | inline uint32_t getPixelColorXY(int x, int y) const { return getPixelColor(isMatrix ? y * Segment::maxWidth + x : x); } |
| 994 | |||
| 995 | // end 2D support | ||
| 996 | |||
| 997 | void loadCustomPalettes(); // loads custom palettes from JSON | ||
| 998 | std::vector<CRGBPalette16> customPalettes; // TODO: move custom palettes out of WS2812FX class | ||
| 999 | |||
| 1000 | struct { | ||
| 1001 | bool autoSegments : 1; | ||
| 1002 | bool correctWB : 1; | ||
| 1003 | bool cctFromRgb : 1; | ||
| 1004 | }; | ||
| 1005 | |||
| 1006 | std::vector<segment> _segments; | ||
| 1007 | friend struct Segment; | ||
| 1008 | |||
| 1009 | private: | ||
| 1010 | volatile bool _suspend; | ||
| 1011 | |||
| 1012 | uint16_t _length; | ||
| 1013 | uint8_t _brightness; | ||
| 1014 | uint16_t _transitionDur; | ||
| 1015 | |||
| 1016 | uint8_t _targetFps; | ||
| 1017 | uint16_t _frametime; | ||
| 1018 | uint16_t _cumulativeFps; | ||
| 1019 | |||
| 1020 | // will require only 1 byte | ||
| 1021 | struct { | ||
| 1022 | bool _isServicing : 1; | ||
| 1023 | bool _isOffRefreshRequired : 1; //periodic refresh is required for the strip to remain off. | ||
| 1024 | bool _hasWhiteChannel : 1; | ||
| 1025 | bool _triggered : 1; | ||
| 1026 | }; | ||
| 1027 | |||
| 1028 | uint8_t _modeCount; | ||
| 1029 | std::vector<mode_ptr> _mode; // SRAM footprint: 4 bytes per element | ||
| 1030 | std::vector<const char*> _modeData; // mode (effect) name and its slider control data array | ||
| 1031 | |||
| 1032 | show_callback _callback; | ||
| 1033 | |||
| 1034 | uint16_t* customMappingTable; | ||
| 1035 | uint16_t customMappingSize; | ||
| 1036 | |||
| 1037 | unsigned long _lastShow; | ||
| 1038 | unsigned long _lastServiceShow; | ||
| 1039 | |||
| 1040 | uint8_t _segment_index; | ||
| 1041 | uint8_t _mainSegment; | ||
| 1042 | }; | ||
| 1043 | |||
| 1044 | extern const char JSON_mode_names[]; | ||
| 1045 | extern const char JSON_palette_names[]; | ||
| 1046 | |||
| 1047 | #endif | ||
| 1048 |