Merge branch 'main' into gif-fix

This commit is contained in:
Will Tatam
2025-01-14 18:26:41 +00:00
212 changed files with 18708 additions and 9213 deletions

View File

@@ -2,24 +2,10 @@
WS2812FX.h - Library for WS2812 LED effects.
Harm Aldick - 2016
www.aldick.org
LICENSE
The MIT License (MIT)
Copyright (c) 2016 Harm Aldick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Licensed under the EUPL v. 1.2 or later
Adapted from code originally licensed under the MIT license
Modified for WLED
*/
@@ -30,6 +16,7 @@
#include <vector>
#include "const.h"
#include "bus_manager.h"
#define FASTLED_INTERNAL //remove annoying pragma messages
#define USE_GET_MILLISECOND_TIMER
@@ -56,16 +43,35 @@
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
#endif
extern bool realtimeRespectLedMaps; // used in getMappedPixelIndex()
extern byte realtimeMode; // used in getMappedPixelIndex()
/* Not used in all effects yet */
#define WLED_FPS 42
#define FRAMETIME_FIXED (1000/WLED_FPS)
//#define FRAMETIME _frametime
#define FRAMETIME strip.getFrameTime()
#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
#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
#else
#define MIN_FRAME_DELAY 8 // 8266 legacy MIN_SHOW_DELAY
#endif
#define FPS_UNLIMITED 0
// 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
#define FPS_CALC_SHIFT 7 // bit shift for fixed point math
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266
#define MAX_NUM_SEGMENTS 12
#define MAX_NUM_SEGMENTS 16
/* How much data bytes all segments combined may allocate */
#define MAX_SEGMENT_DATA 5120
#else
@@ -73,11 +79,7 @@
#define MAX_NUM_SEGMENTS 32
#endif
#if defined(ARDUINO_ARCH_ESP32S2)
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1024 // 32k by default
#else
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default
#endif
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default (S2 is short on free RAM)
#else
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1280 // 40k by default
#endif
@@ -87,16 +89,14 @@
assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */
#define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / strip.getMaxSegments())
#define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15)
#define NUM_COLORS 3 /* number of colors per segment */
#define SEGMENT strip._segments[strip.getCurrSegmentId()]
#define SEGENV strip._segments[strip.getCurrSegmentId()]
//#define SEGCOLOR(x) strip._segments[strip.getCurrSegmentId()].currentColor(x, strip._segments[strip.getCurrSegmentId()].colors[x])
//#define SEGLEN strip._segments[strip.getCurrSegmentId()].virtualLength()
#define SEGCOLOR(x) strip.segColor(x) /* saves us a few kbytes of code */
#define SEGPALETTE strip._currentPalette
#define SEGLEN strip._virtualSegmentLength /* saves us a few kbytes of code */
#define SEGCOLOR(x) Segment::getCurrentColor(x)
#define SEGPALETTE Segment::getCurrentPalette()
#define SEGLEN Segment::vLength()
#define SEG_W Segment::vWidth()
#define SEG_H Segment::vHeight()
#define SPEED_FORMULA_L (5U + (50U*(255U - SEGMENT.speed))/SEGLEN)
// some common colors
@@ -111,6 +111,10 @@
#define PURPLE (uint32_t)0x400080
#define ORANGE (uint32_t)0xFF3000
#define PINK (uint32_t)0xFF1493
#define GREY (uint32_t)0x808080
#define GRAY GREY
#define DARKGREY (uint32_t)0x333333
#define DARKGRAY DARKGREY
#define ULTRAWHITE (uint32_t)0xFFFFFFFF
#define DARKSLATEGRAY (uint32_t)0x2F4F4F
#define DARKSLATEGREY DARKSLATEGRAY
@@ -180,14 +184,14 @@
#define FX_MODE_TWO_DOTS 50
#define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity)
#define FX_MODE_RUNNING_DUAL 52
#define FX_MODE_IMAGE 53 // was Halloween before 0.14
#define FX_MODE_IMAGE 53
#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
#define FX_MODE_DUAL_LARSON_SCANNER 60
#define FX_MODE_DUAL_LARSON_SCANNER 60 // candidate for removal (use Scanner with with check 1)
#define FX_MODE_RANDOM_CHASE 61
#define FX_MODE_OSCILLATE 62
#define FX_MODE_PRIDE_2015 63
@@ -204,7 +208,7 @@
#define FX_MODE_COLORTWINKLE 74
#define FX_MODE_LAKE 75
#define FX_MODE_METEOR 76
#define FX_MODE_METEOR_SMOOTH 77
//#define FX_MODE_METEOR_SMOOTH 77 // merged with meteor
#define FX_MODE_RAILWAY 78
#define FX_MODE_RIPPLE 79
#define FX_MODE_TWINKLEFOX 80
@@ -325,7 +329,8 @@ typedef enum mapping1D2D {
M12_Pixels = 0,
M12_pBar = 1,
M12_pArc = 2,
M12_pCorner = 3
M12_pCorner = 3,
M12_sPinwheel = 4
} mapping1D2D_t;
// segment, 80 bytes
@@ -368,6 +373,7 @@ typedef struct Segment {
};
uint8_t startY; // start Y coodrinate 2D (top); there should be no more than 255 rows
uint8_t stopY; // stop Y coordinate 2D (bottom); there should be no more than 255 rows
// note: two bytes of padding are added here
char *name;
// runtime data
@@ -396,7 +402,7 @@ typedef struct Segment {
uint32_t _stepT;
uint32_t _callT;
uint8_t *_dataT;
uint16_t _dataLenT;
unsigned _dataLenT;
TemporarySegmentData()
: _dataT(nullptr) // just in case...
, _dataLenT(0)
@@ -414,14 +420,20 @@ typedef struct Segment {
uint8_t _reserved : 4;
};
};
uint16_t _dataLen;
static uint16_t _usedSegmentData;
// perhaps this should be per segment, not static
uint8_t _default_palette; // palette number that gets assigned to pal0
unsigned _dataLen;
static unsigned _usedSegmentData;
static uint8_t _segBri; // brightness of segment for current effect
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
static bool _colorScaled; // color has been scaled prior to setPixelColor() call
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
static CRGBPalette16 _randomPalette; // actual random palette
static CRGBPalette16 _newRandomPalette; // target random palette
static uint16_t _lastPaletteChange; // last random palette change time in millis()/1000
static uint16_t _lastPaletteBlend; // blend palette according to set Transition Delay in millis()%0xFFFF
static uint16_t _transitionprogress; // current transition progress 0 - 0xFFFF
#ifndef WLED_DISABLE_MODE_BLEND
static bool _modeBlend; // mode/effect blending semaphore
#endif
@@ -448,6 +460,8 @@ typedef struct Segment {
{}
} *_t;
[[gnu::hot]] void _setPixelColorXY_raw(int& x, int& y, uint32_t& col); // set pixel without mapping (internal use only)
public:
Segment(uint16_t sStart=0, uint16_t sStop=30) :
@@ -480,6 +494,7 @@ typedef struct Segment {
aux1(0),
data(nullptr),
_capabilities(0),
_default_palette(0),
_dataLen(0),
_t(nullptr)
{
@@ -516,154 +531,187 @@ typedef struct Segment {
#endif
inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); }
inline bool isSelected(void) const { return selected; }
inline bool isInTransition(void) const { return _t != nullptr; }
inline bool isActive(void) const { return stop > start; }
inline bool is2D(void) const { return (width()>1 && height()>1); }
inline bool hasRGB(void) const { return _isRGB; }
inline bool hasWhite(void) const { return _hasW; }
inline bool isCCT(void) const { return _isCCT; }
inline uint16_t width(void) const { return isActive() ? (stop - start) : 0; } // segment width in physical pixels (length if 1D)
inline uint16_t height(void) const { return stopY - startY; } // segment height (if 2D) in physical pixels (it *is* always >=1)
inline uint16_t length(void) const { return width() * height(); } // segment length (count) in physical pixels
inline uint16_t groupLength(void) const { return grouping + spacing; }
inline uint8_t getLightCapabilities(void) const { return _capabilities; }
inline bool isSelected() const { return selected; }
inline bool isInTransition() const { return _t != nullptr; }
inline bool isActive() const { return stop > start; }
inline bool is2D() const { return (width()>1 && height()>1); }
inline bool hasRGB() const { return _isRGB; }
inline bool hasWhite() const { return _hasW; }
inline bool isCCT() const { return _isCCT; }
inline uint16_t width() const { return isActive() ? (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; }
inline uint8_t getLightCapabilities() const { return _capabilities; }
inline void deactivate() { setGeometry(0,0); }
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
static void addUsedSegmentData(int len) { _usedSegmentData += len; }
inline static unsigned getUsedSegmentData() { return Segment::_usedSegmentData; }
inline static void addUsedSegmentData(int len) { Segment::_usedSegmentData += len; }
#ifndef WLED_DISABLE_MODE_BLEND
static void modeBlend(bool blend) { _modeBlend = blend; }
inline static void modeBlend(bool blend) { _modeBlend = blend; }
#endif
static void handleRandomPalette();
inline static unsigned vLength() { return Segment::_vLength; }
inline static unsigned vWidth() { return Segment::_vWidth; }
inline static unsigned vHeight() { return Segment::_vHeight; }
inline static uint32_t getCurrentColor(unsigned i) { return Segment::_currentColors[i]; } // { return i < 3 ? Segment::_currentColors[i] : 0; }
inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; }
inline static uint8_t getCurrentBrightness() { return Segment::_segBri; }
static void handleRandomPalette();
void setUp(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);
bool setColor(uint8_t slot, uint32_t c); //returns true if changed
void setCCT(uint16_t k);
void setOpacity(uint8_t o);
void setOption(uint8_t n, bool val);
void setMode(uint8_t fx, bool loadDefaults = false);
void setPalette(uint8_t pal);
uint8_t differs(Segment& b) const;
void refreshLightCapabilities(void);
void beginDraw(); // set up parameters for current effect
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);
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);
uint8_t differs(const Segment& b) const;
void refreshLightCapabilities();
// runtime data functions
inline uint16_t dataSize(void) const { return _dataLen; }
inline uint16_t dataSize() const { return _dataLen; }
bool allocateData(size_t len); // allocates effect data buffer in heap and clears it
void deallocateData(void); // deallocates (frees) effect data buffer from heap
void resetIfRequired(void); // sets all SEGENV variables to 0 and clears data buffer
void deallocateData(); // deallocates (frees) effect data buffer from heap
void resetIfRequired(); // sets all SEGENV variables to 0 and clears data buffer
/**
* Flags that before the next effect is calculated,
* the internal segment state should be reset.
* Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests.
*/
inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true)
inline Segment &markForReset() { reset = true; return *this; } // setOption(SEG_OPTION_RESET, true)
// transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change
void stopTransition(void); // ends transition mode by destroying transition structure
void handleTransition(void);
void stopTransition(); // ends transition mode by destroying transition structure (does nothing if not in transition)
inline void handleTransition() { updateTransitionProgress(); if (progress() == 0xFFFFU) stopTransition(); }
#ifndef WLED_DISABLE_MODE_BLEND
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
void restoreSegenv(tmpsegd_t &tmpSegD); // restores segment data from buffer, if buffer is not transition buffer, changed values are copied to transition buffer
#endif
uint16_t progress(void); // transition progression between 0-65535
uint8_t currentBri(bool useCct = false); // current segment brightness/CCT (blended while in transition)
uint8_t currentMode(void); // currently active effect/mode (while in transition)
uint32_t currentColor(uint8_t slot); // currently active segment color (blended while in transition)
[[gnu::hot]] void updateTransitionProgress(); // set current progression of transition
inline uint16_t progress() const { return _transitionprogress; }; // transition progression between 0-65535
[[gnu::hot]] uint8_t currentBri(bool useCct = false) const; // current segment brightness/CCT (blended while in transition)
uint8_t currentMode() const; // currently active effect/mode (while in transition)
[[gnu::hot]] uint32_t currentColor(uint8_t slot) const; // currently active segment color (blended while in transition)
CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
CRGBPalette16 &currentPalette(CRGBPalette16 &tgt, uint8_t paletteID);
// 1D strip
uint16_t virtualLength(void) const;
void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
[[gnu::hot]] uint16_t virtualLength() const;
[[gnu::hot]] void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
inline void setPixelColor(unsigned n, uint32_t c) { setPixelColor(int(n), c); }
inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
inline void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); }
#ifdef WLED_USE_AA_PIXELS
void setPixelColor(float i, uint32_t c, bool aa = true);
inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
uint32_t getPixelColor(int i);
#endif
[[gnu::hot]] uint32_t getPixelColor(int i) const;
// 1D support functions (some implement 2D as well)
void blur(uint8_t);
void blur(uint8_t, bool smear = false);
void fill(uint32_t c);
void fade_out(uint8_t r);
void fadeToBlackBy(uint8_t fadeBy);
inline void blendPixelColor(int n, uint32_t color, uint8_t blend) { setPixelColor(n, color_blend(getPixelColor(n), color, blend)); }
inline void blendPixelColor(int n, CRGB c, uint8_t blend) { blendPixelColor(n, RGBW32(c.r,c.g,c.b,0), blend); }
inline void addPixelColor(int n, uint32_t color, bool fast = false) { setPixelColor(n, color_add(getPixelColor(n), color, fast)); }
inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); }
inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); }
inline void addPixelColor(int n, uint32_t color, bool preserveCR = true) { 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) { addPixelColor(n, RGBW32(r,g,b,w), preserveCR); }
inline void addPixelColor(int n, CRGB c, bool preserveCR = true) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), preserveCR); }
inline void fadePixelColor(uint16_t n, uint8_t fade) { setPixelColor(n, color_fade(getPixelColor(n), fade, true)); }
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
uint32_t color_wheel(uint8_t pos);
[[gnu::hot]] uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255) const;
[[gnu::hot]] uint32_t color_wheel(uint8_t pos) const;
// 2D Blur: shortcuts for bluring columns or rows only (50% faster than full 2D blur)
inline void blurCols(fract8 blur_amount, bool smear = false) { // blur all columns
blur2D(0, blur_amount, smear);
}
inline void blurRows(fract8 blur_amount, bool smear = false) { // blur all rows
blur2D(blur_amount, 0, smear);
}
// 2D matrix
uint16_t virtualWidth(void) const; // segment width in virtual pixels (accounts for groupping and spacing)
uint16_t virtualHeight(void) const; // segment height in virtual pixels (accounts for groupping and spacing)
uint16_t nrOfVStrips(void) const; // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
[[gnu::hot]] unsigned virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing)
[[gnu::hot]] 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)
#ifndef WLED_DISABLE_2D
return (is2D() && map1D2D == M12_pBar) ? virtualWidth() : 1;
#else
return 1;
#endif
}
#ifndef WLED_DISABLE_2D
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
[[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColorXY(int(x), int(y), RGBW32(c.r,c.g,c.b,0)); }
#ifdef WLED_USE_AA_PIXELS
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true);
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
uint32_t getPixelColorXY(uint16_t x, uint16_t y);
#endif
[[gnu::hot]] uint32_t getPixelColorXY(int x, int y) const;
// 2D support functions
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)); }
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); }
inline void addPixelColorXY(int x, int y, uint32_t color, bool fast = false) { setPixelColorXY(x, y, color_add(getPixelColorXY(x,y), color, fast)); }
inline void addPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColorXY(x, y, RGBW32(r,g,b,w), fast); }
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), fast); }
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true)); }
void box_blur(uint16_t i, bool vertical, fract8 blur_amount); // 1D box blur (with weight)
void blurRow(uint16_t row, fract8 blur_amount);
void blurCol(uint16_t col, fract8 blur_amount);
void moveX(int8_t delta, bool wrap = false);
void moveY(int8_t delta, bool wrap = false);
void move(uint8_t dir, uint8_t delta, bool wrap = false);
void draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
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);
inline void addPixelColorXY(int x, int y, uint32_t color, bool preserveCR = true) { 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) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), preserveCR); }
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true)); }
//void box_blur(unsigned r = 1U, bool smear = false); // 2D box blur
void blur2D(uint8_t blur_x, uint8_t blur_y, bool smear = false);
void moveX(int delta, bool wrap = false);
void moveY(int delta, bool wrap = false);
void move(unsigned dir, unsigned delta, bool wrap = false);
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) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
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) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
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) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft); } // automatic inline
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);
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
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) { 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 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
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
void blur1d(fract8 blur_amount); // blur all rows in 1 dimension
inline void blur2d(fract8 blur_amount) { blur(blur_amount); }
inline void fill_solid(CRGB c) { fill(RGBW32(c.r,c.g,c.b,0)); }
void nscale8(uint8_t scale);
#else
inline uint16_t XY(uint16_t x, uint16_t y) { return x; }
inline uint16_t XY(int x, int y) { return x; }
inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(x, c); }
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColor(int(x), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColor(x, RGBW32(r,g,b,w)); }
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0)); }
inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColor(int(x), RGBW32(c.r,c.g,c.b,0)); }
#ifdef WLED_USE_AA_PIXELS
inline void setPixelColorXY(float x, float y, uint32_t c, bool aa = true) { setPixelColor(x, c, aa); }
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); }
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0), aa); }
inline uint32_t getPixelColorXY(uint16_t x, uint16_t y) { return getPixelColor(x); }
#endif
inline uint32_t getPixelColorXY(int x, int y) { return getPixelColor(x); }
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t c, uint8_t blend) { blendPixelColor(x, c, blend); }
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); }
inline void addPixelColorXY(int x, int y, uint32_t color, bool fast = false) { addPixelColor(x, color, fast); }
inline void addPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(x, RGBW32(r,g,b,w), fast); }
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), fast); }
inline void addPixelColorXY(int x, int y, uint32_t color, bool saturate = false) { addPixelColor(x, color, saturate); }
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); }
inline void addPixelColorXY(int x, int y, CRGB c, bool saturate = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), saturate); }
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { fadePixelColor(x, fade); }
inline void box_blur(uint16_t i, bool vertical, fract8 blur_amount) {}
inline void blurRow(uint16_t row, fract8 blur_amount) {}
inline void blurCol(uint16_t col, fract8 blur_amount) {}
inline void moveX(int8_t delta, bool wrap = false) {}
inline void moveY(int8_t delta, bool wrap = false) {}
//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) {}
inline void blurRow(int row, fract8 blur_amount, bool smear = false) {}
inline void blurCol(int col, fract8 blur_amount, bool smear = false) {}
inline void moveX(int delta, bool wrap = false) {}
inline void moveY(int delta, bool wrap = false) {}
inline void move(uint8_t dir, uint8_t delta, bool wrap = false) {}
inline void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c) {}
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {}
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) {}
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 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) {}
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) {}
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color) {}
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) {}
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) {}
inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
#endif
} segment;
@@ -671,8 +719,8 @@ typedef struct Segment {
// main "strip" class
class WS2812FX { // 96 bytes
typedef uint16_t (*mode_ptr)(void); // pointer to mode function
typedef void (*show_callback)(void); // pre show callback
typedef uint16_t (*mode_ptr)(); // pointer to mode function
typedef void (*show_callback)(); // pre show callback
typedef struct ModeData {
uint8_t _id; // mode (effect) id
mode_ptr _fcn; // mode (effect) function
@@ -694,10 +742,13 @@ class WS2812FX { // 96 bytes
#ifndef WLED_DISABLE_2D
panels(1),
#endif
// semi-private (just obscured) used in effect functions through macros
_currentPalette(CRGBPalette16(CRGB::Black)),
_colors_t{0,0,0},
_virtualSegmentLength(0),
#ifdef WLED_AUTOSEGMENTS
autoSegments(true),
#else
autoSegments(false),
#endif
correctWB(false),
cctFromRgb(false),
// true private variables
_suspend(false),
_length(DEFAULT_LED_COUNT),
@@ -705,7 +756,7 @@ class WS2812FX { // 96 bytes
_transitionDur(750),
_targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED),
_cumulativeFps(2),
_cumulativeFps(50 << FPS_CALC_SHIFT),
_isServicing(false),
_isOffRefreshRequired(false),
_hasWhiteChannel(false),
@@ -715,16 +766,9 @@ class WS2812FX { // 96 bytes
customMappingTable(nullptr),
customMappingSize(0),
_lastShow(0),
_lastServiceShow(0),
_segment_index(0),
_mainSegment(0),
_queuedChangesSegId(255),
_qStart(0),
_qStop(0),
_qStartY(0),
_qStopY(0),
_qGrouping(0),
_qSpacing(0),
_qOffset(0)
_mainSegment(0)
{
WS2812FX::instance = this;
_mode.reserve(_modeCount); // allocate memory to prevent initial fragmentation (does not increase size())
@@ -744,112 +788,105 @@ class WS2812FX { // 96 bytes
customPalettes.clear();
}
static WS2812FX* getInstance(void) { return instance; }
static WS2812FX* getInstance() { return instance; }
void
#ifdef WLED_DEBUG
printSize(), // prints memory usage for strip components
#endif
finalizeInit(), // initialises strip components
service(void), // executes effect functions when due and calls strip.show()
setMode(uint8_t segid, uint8_t m), // sets effect/mode for given segment (high level API)
setColor(uint8_t slot, uint32_t c), // sets color (in slot) for given segment (high level API)
service(), // executes effect functions when due and calls strip.show()
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
purgeSegments(void), // removes inactive segments from RAM (may incure penalty and memory fragmentation but reduces vector footprint)
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 1, uint8_t spacing = 0, uint16_t offset = UINT16_MAX, uint16_t startY=0, uint16_t stopY=1),
setMainSegmentId(uint8_t n),
purgeSegments(), // removes inactive segments from RAM (may incure penalty and memory fragmentation but reduces vector footprint)
setMainSegmentId(unsigned n = 0),
resetSegments(), // marks all segments for reset
makeAutoSegments(bool forceReset = false), // will create segments based on configured outputs
fixInvalidSegments(), // fixes incorrect segment configuration
setPixelColor(unsigned n, uint32_t c), // paints absolute strip pixel with index n and color c
show(void), // initiates LED output
setTargetFps(uint8_t fps),
addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name), // add effect to the list; defined in FX.cpp
setupEffectData(void); // add default effects to the list; defined in FX.cpp
show(), // initiates LED output
setTargetFps(unsigned fps),
setupEffectData(); // add default effects to the list; defined in FX.cpp
inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); }
inline void resetTimebase() { timebase = 0UL - millis(); }
inline void restartRuntime() { for (Segment &seg : _segments) { seg.markForReset().resetIfRequired(); } }
inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); }
inline void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); }
inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
inline void setPixelColor(unsigned n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); }
inline void fill(uint32_t c) { for (unsigned i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline)
inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments.
inline void trigger() { _triggered = true; } // Forces the next frame to be computed on all active segments.
inline void setShowCallback(show_callback cb) { _callback = cb; }
inline void setTransition(uint16_t t) { _transitionDur = t; } // sets transition time (in ms)
inline void appendSegment(const Segment &seg = Segment()) { if (_segments.size() < getMaxSegments()) _segments.push_back(seg); }
inline void suspend(void) { _suspend = true; } // will suspend (and canacel) strip.service() execution
inline void resume(void) { _suspend = false; } // will resume strip.service() execution
inline void suspend() { _suspend = true; } // will suspend (and canacel) strip.service() execution
inline void resume() { _suspend = false; } // will resume strip.service() execution
bool
paletteFade,
checkSegmentAlignment(void),
hasRGBWBus(void),
hasCCTBus(void),
// return true if the strip is being sent pixel updates
isUpdating(void),
deserializeMap(uint8_t n=0);
checkSegmentAlignment(),
hasRGBWBus() const,
hasCCTBus() const,
deserializeMap(unsigned n = 0);
inline bool isServicing(void) { return _isServicing; } // returns true if strip.service() is executing
inline bool hasWhiteChannel(void) { return _hasWhiteChannel; } // returns true if strip contains separate white chanel
inline bool isOffRefreshRequired(void) { return _isOffRefreshRequired; } // returns true if strip requires regular updates (i.e. TM1814 chipset)
inline bool isSuspended(void) { return _suspend; } // returns true if strip.service() execution is suspended
inline bool needsUpdate(void) { return _triggered; } // returns true if strip received a trigger() request
inline bool isUpdating() const { return !BusManager::canAllShow(); } // return true if the strip is being sent pixel updates
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
uint8_t
paletteBlend,
cctBlending,
getActiveSegmentsNum(void),
getFirstSelectedSegId(void),
getLastActiveSegmentId(void),
getActiveSegsLightCapabilities(bool selectedOnly = false);
getActiveSegmentsNum() const,
getFirstSelectedSegId() const,
getLastActiveSegmentId() const,
getActiveSegsLightCapabilities(bool selectedOnly = false) const,
addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name); // add effect to the list; defined in FX.cpp;
inline uint8_t getBrightness(void) { return _brightness; } // returns current strip brightness
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
inline uint8_t getCurrSegmentId(void) { return _segment_index; } // returns current segment index (only valid while strip.isServicing())
inline uint8_t getMainSegmentId(void) { return _mainSegment; } // returns main segment index
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
inline uint8_t getTargetFps() { return _targetFps; } // returns rough FPS value for las 2s interval
inline uint8_t getModeCount() { return _modeCount; } // returns number of registered modes/effects
inline uint8_t getBrightness() const { return _brightness; } // returns current strip brightness
inline static constexpr unsigned getMaxSegments() { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
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 getPaletteCount() const { return 13 + GRADIENT_PALETTE_COUNT + customPalettes.size(); }
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
uint16_t
getLengthPhysical(void),
getLengthTotal(void), // will include virtual/nonexistent pixels in matrix
getFps(),
getMappedPixelIndex(uint16_t index);
getLengthPhysical() const,
getLengthTotal() const; // will include virtual/nonexistent pixels in matrix
inline uint16_t getFrameTime(void) { return _frametime; } // returns amount of time a frame should take (in ms)
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; } // returns minimum amount of time strip.service() can be delayed (constant)
inline uint16_t getLength(void) { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H)
inline uint16_t getTransition(void) { return _transitionDur; } // returns currently set transition time (in ms)
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)
inline uint16_t getFrameTime() const { return _frametime; } // returns amount of time a frame should take (in ms)
inline uint16_t getMinShowDelay() const { return MIN_FRAME_DELAY; } // returns minimum amount of time strip.service() can be delayed (constant)
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)
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;
};
uint32_t
now,
timebase,
getPixelColor(uint16_t);
unsigned long now, timebase;
uint32_t getPixelColor(unsigned) const;
inline uint32_t getLastShow(void) { return _lastShow; } // returns millis() timestamp of last strip.show() call
inline uint32_t segColor(uint8_t i) { return _colors_t[i]; } // returns currently valid color (for slot i) AKA SEGCOLOR(); may be blended between two colors while in transition
inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call
const char *
getModeData(uint8_t id = 0) { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
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
const char **
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data
Segment& getSegment(uint8_t id);
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; } // returns reference to first segment that is "selected"
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; } // returns reference to main segment
inline Segment* getSegments(void) { return &(_segments[0]); } // returns pointer to segment vector structure (warning: use carefully)
Segment& getSegment(unsigned id);
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)
// 2D support (panels)
bool
isMatrix;
#ifndef WLED_DISABLE_2D
#define WLED_MAX_PANELS 64
#define WLED_MAX_PANELS 18
uint8_t
panels;
@@ -885,18 +922,18 @@ class WS2812FX { // 96 bytes
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
inline uint32_t getPixelColorXY(uint16_t x, uint16_t y) { return getPixelColor(isMatrix ? y * Segment::maxWidth + x : x);}
inline uint32_t getPixelColorXY(int x, int y) const { return getPixelColor(isMatrix ? y * Segment::maxWidth + x : x); }
// end 2D support
void loadCustomPalettes(void); // loads custom palettes from JSON
CRGBPalette16 _currentPalette; // palette used for current effect (includes transition)
void loadCustomPalettes(); // loads custom palettes from JSON
std::vector<CRGBPalette16> customPalettes; // TODO: move custom palettes out of WS2812FX class
// using public variables to reduce code size increase due to inline function getSegment() (with bounds checking)
// and color transitions
uint32_t _colors_t[3]; // color used for effect (includes transition)
uint16_t _virtualSegmentLength;
struct {
bool autoSegments : 1;
bool correctWB : 1;
bool cctFromRgb : 1;
};
std::vector<segment> _segments;
friend class Segment;
@@ -930,17 +967,10 @@ class WS2812FX { // 96 bytes
uint16_t customMappingSize;
unsigned long _lastShow;
unsigned long _lastServiceShow;
uint8_t _segment_index;
uint8_t _mainSegment;
uint8_t _queuedChangesSegId;
uint16_t _qStart, _qStop, _qStartY, _qStopY;
uint8_t _qGrouping, _qSpacing;
uint16_t _qOffset;
/*
void
setUpSegmentFromQueuedChanges(void);
*/
};
extern const char JSON_mode_names[];