color_fade bugfix

impure void remove
optimisations: hot
This commit is contained in:
Blaz Kristan 2024-09-11 17:14:59 +02:00
parent 81382a4bc0
commit eae5a74a11
5 changed files with 110 additions and 107 deletions

View File

@ -517,26 +517,26 @@ typedef struct Segment {
#endif #endif
inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); } inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); }
inline bool isSelected(void) const { return selected; } inline bool isSelected() const { return selected; }
inline bool isInTransition(void) const { return _t != nullptr; } inline bool isInTransition() const { return _t != nullptr; }
inline bool isActive(void) const { return stop > start; } inline bool isActive() const { return stop > start; }
inline bool is2D(void) const { return (width()>1 && height()>1); } inline bool is2D() const { return (width()>1 && height()>1); }
inline bool hasRGB(void) const { return _isRGB; } inline bool hasRGB() const { return _isRGB; }
inline bool hasWhite(void) const { return _hasW; } inline bool hasWhite() const { return _hasW; }
inline bool isCCT(void) const { return _isCCT; } inline bool isCCT() 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 width() 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 height() 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 length() const { return width() * height(); } // segment length (count) in physical pixels
inline uint16_t groupLength(void) const { return grouping + spacing; } inline uint16_t groupLength() const { return grouping + spacing; }
inline uint8_t getLightCapabilities(void) const { return _capabilities; } inline uint8_t getLightCapabilities() const { return _capabilities; }
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; } inline static uint16_t getUsedSegmentData() { return _usedSegmentData; }
static void addUsedSegmentData(int len) { _usedSegmentData += len; } inline static void addUsedSegmentData(int len) { _usedSegmentData += len; }
#ifndef WLED_DISABLE_MODE_BLEND #ifndef WLED_DISABLE_MODE_BLEND
static void modeBlend(bool blend) { _modeBlend = blend; } inline static void modeBlend(bool blend) { _modeBlend = blend; }
#endif #endif
static void handleRandomPalette(); static void handleRandomPalette();
inline static const CRGBPalette16 &getCurrentPalette(void) { return Segment::_currentPalette; } inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; }
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); 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 bool setColor(uint8_t slot, uint32_t c); //returns true if changed
@ -546,39 +546,39 @@ typedef struct Segment {
void setMode(uint8_t fx, bool loadDefaults = false); void setMode(uint8_t fx, bool loadDefaults = false);
void setPalette(uint8_t pal); void setPalette(uint8_t pal);
uint8_t differs(Segment& b) const; uint8_t differs(Segment& b) const;
void refreshLightCapabilities(void); void refreshLightCapabilities();
// runtime data functions // 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 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 deallocateData(); // deallocates (frees) effect data buffer from heap
void resetIfRequired(void); // sets all SEGENV variables to 0 and clears data buffer void resetIfRequired(); // sets all SEGENV variables to 0 and clears data buffer
/** /**
* Flags that before the next effect is calculated, * Flags that before the next effect is calculated,
* the internal segment state should be reset. * the internal segment state should be reset.
* Call resetIfRequired before calling the next effect function. * Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests. * Safe to call from interrupts and network requests.
*/ */
inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true) inline void markForReset() { reset = true; } // setOption(SEG_OPTION_RESET, true)
// transition functions // transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change void startTransition(uint16_t dur); // transition has to start before actual segment values change
void stopTransition(void); // ends transition mode by destroying transition structure (does nothing if not in transition) void stopTransition(); // ends transition mode by destroying transition structure (does nothing if not in transition)
inline void handleTransition(void) { if (progress() == 0xFFFFU) stopTransition(); } inline void handleTransition() { if (progress() == 0xFFFFU) stopTransition(); }
#ifndef WLED_DISABLE_MODE_BLEND #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 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 void restoreSegenv(tmpsegd_t &tmpSegD); // restores segment data from buffer, if buffer is not transition buffer, changed values are copied to transition buffer
#endif #endif
uint16_t progress(void) const; // transition progression between 0-65535 [[gnu::hot]] uint16_t progress() const; // transition progression between 0-65535
uint8_t currentBri(bool useCct = false) const; // current segment brightness/CCT (blended while in transition) [[gnu::hot]] uint8_t currentBri(bool useCct = false) const; // current segment brightness/CCT (blended while in transition)
uint8_t currentMode(void) const; // currently active effect/mode (while in transition) uint8_t currentMode() const; // currently active effect/mode (while in transition)
uint32_t currentColor(uint8_t slot) const; // currently active segment color (blended 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); [[gnu::hot]] CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
void setCurrentPalette(void); void setCurrentPalette();
// 1D strip // 1D strip
uint16_t virtualLength(void) const; [[gnu::hot]] uint16_t virtualLength() const;
void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color [[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(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, 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)); } inline void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); }
@ -587,7 +587,7 @@ typedef struct Segment {
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, 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); } inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
#endif #endif
uint32_t getPixelColor(int i) const; [[gnu::hot]] uint32_t getPixelColor(int i) const;
// 1D support functions (some implement 2D as well) // 1D support functions (some implement 2D as well)
void blur(uint8_t, bool smear = false); void blur(uint8_t, bool smear = false);
void fill(uint32_t c); void fill(uint32_t c);
@ -599,8 +599,8 @@ typedef struct Segment {
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, 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, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); }
inline void fadePixelColor(uint16_t n, uint8_t fade) { setPixelColor(n, color_fade(getPixelColor(n), fade, true)); } 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) const; [[gnu::hot]] uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255) const;
uint32_t color_wheel(uint8_t pos) 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) // 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 inline void blurCols(fract8 blur_amount, bool smear = false) { // blur all columns
@ -613,12 +613,12 @@ typedef struct Segment {
} }
// 2D matrix // 2D matrix
uint16_t virtualWidth(void) const; // segment width in virtual pixels (accounts for groupping and spacing) [[gnu::hot]] uint16_t virtualWidth() 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) [[gnu::hot]] uint16_t virtualHeight() 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]] uint16_t nrOfVStrips() const; // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment [[gnu::hot]] uint16_t XY(int x, int 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]] 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(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, 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(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
@ -628,7 +628,7 @@ typedef struct Segment {
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, 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); } inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
#endif #endif
uint32_t getPixelColorXY(int x, int y) const; [[gnu::hot]] uint32_t getPixelColorXY(int x, int y) const;
// 2D support functions // 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, 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 blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); }
@ -697,8 +697,8 @@ typedef struct Segment {
// main "strip" class // main "strip" class
class WS2812FX { // 96 bytes class WS2812FX { // 96 bytes
typedef uint16_t (*mode_ptr)(void); // pointer to mode function typedef uint16_t (*mode_ptr)(); // pointer to mode function
typedef void (*show_callback)(void); // pre show callback typedef void (*show_callback)(); // pre show callback
typedef struct ModeData { typedef struct ModeData {
uint8_t _id; // mode (effect) id uint8_t _id; // mode (effect) id
mode_ptr _fcn; // mode (effect) function mode_ptr _fcn; // mode (effect) function
@ -764,29 +764,29 @@ class WS2812FX { // 96 bytes
customPalettes.clear(); customPalettes.clear();
} }
static WS2812FX* getInstance(void) { return instance; } static WS2812FX* getInstance() { return instance; }
void void
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
printSize(), // prints memory usage for strip components printSize(), // prints memory usage for strip components
#endif #endif
finalizeInit(), // initialises strip components finalizeInit(), // initialises strip components
service(void), // executes effect functions when due and calls strip.show() service(), // 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) 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) setColor(uint8_t slot, uint32_t c), // sets color (in slot) for given segment (high level API)
setCCT(uint16_t k), // sets global CCT (either in relative 0-255 value or in K) 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 setBrightness(uint8_t b, bool direct = false), // sets strip brightness
setRange(uint16_t i, uint16_t i2, uint32_t col), // used for clock overlay 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) purgeSegments(), // 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), 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), setMainSegmentId(uint8_t n),
resetSegments(), // marks all segments for reset resetSegments(), // marks all segments for reset
makeAutoSegments(bool forceReset = false), // will create segments based on configured outputs makeAutoSegments(bool forceReset = false), // will create segments based on configured outputs
fixInvalidSegments(), // fixes incorrect segment configuration fixInvalidSegments(), // fixes incorrect segment configuration
setPixelColor(unsigned n, uint32_t c), // paints absolute strip pixel with index n and color c setPixelColor(unsigned n, uint32_t c), // paints absolute strip pixel with index n and color c
show(void), // initiates LED output show(), // initiates LED output
setTargetFps(uint8_t fps), setTargetFps(uint8_t fps),
setupEffectData(void); // add default effects to the list; defined in FX.cpp setupEffectData(); // add default effects to the list; defined in FX.cpp
inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); } inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); }
inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); } inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); }
@ -794,74 +794,74 @@ class WS2812FX { // 96 bytes
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, 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 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 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 setShowCallback(show_callback cb) { _callback = cb; }
inline void setTransition(uint16_t t) { _transitionDur = t; } // sets transition time (in ms) 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 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 suspend() { _suspend = true; } // will suspend (and canacel) strip.service() execution
inline void resume(void) { _suspend = false; } // will resume strip.service() execution inline void resume() { _suspend = false; } // will resume strip.service() execution
bool bool
paletteFade, paletteFade,
checkSegmentAlignment(void), checkSegmentAlignment(),
hasRGBWBus(void) const, hasRGBWBus() const,
hasCCTBus(void) const, hasCCTBus() const,
isUpdating(void) const, // return true if the strip is being sent pixel updates isUpdating() const, // return true if the strip is being sent pixel updates
deserializeMap(uint8_t n=0); deserializeMap(uint8_t n=0);
inline bool isServicing(void) const { return _isServicing; } // returns true if strip.service() is executing inline bool isServicing() const { return _isServicing; } // returns true if strip.service() is executing
inline bool hasWhiteChannel(void) const { return _hasWhiteChannel; } // returns true if strip contains separate white chanel inline bool hasWhiteChannel() const { return _hasWhiteChannel; } // returns true if strip contains separate white chanel
inline bool isOffRefreshRequired(void) const { return _isOffRefreshRequired; } // returns true if strip requires regular updates (i.e. TM1814 chipset) inline bool isOffRefreshRequired() const { return _isOffRefreshRequired; } // returns true if strip requires regular updates (i.e. TM1814 chipset)
inline bool isSuspended(void) const { return _suspend; } // returns true if strip.service() execution is suspended inline bool isSuspended() const { return _suspend; } // returns true if strip.service() execution is suspended
inline bool needsUpdate(void) const { return _triggered; } // returns true if strip received a trigger() request inline bool needsUpdate() const { return _triggered; } // returns true if strip received a trigger() request
uint8_t uint8_t
paletteBlend, paletteBlend,
cctBlending, cctBlending,
getActiveSegmentsNum(void) const, getActiveSegmentsNum() const,
getFirstSelectedSegId(void) const, getFirstSelectedSegId() const,
getLastActiveSegmentId(void) const, getLastActiveSegmentId() const,
getActiveSegsLightCapabilities(bool selectedOnly = false) 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; 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) const { return _brightness; } // returns current strip brightness inline uint8_t getBrightness() const { return _brightness; } // returns current strip brightness
inline uint8_t getMaxSegments(void) const { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value) inline uint8_t getMaxSegments() const { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
inline uint8_t getSegmentsNum(void) const { return _segments.size(); } // returns currently present segments inline uint8_t getSegmentsNum() const { return _segments.size(); } // returns currently present segments
inline uint8_t getCurrSegmentId(void) const { return _segment_index; } // returns current segment index (only valid while strip.isServicing()) inline uint8_t getCurrSegmentId() const { return _segment_index; } // returns current segment index (only valid while strip.isServicing())
inline uint8_t getMainSegmentId(void) const { return _mainSegment; } // returns main segment index 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 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 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 inline uint8_t getModeCount() const { return _modeCount; } // returns number of registered modes/effects
uint16_t uint16_t
getLengthPhysical(void) const, getLengthPhysical() const,
getLengthTotal(void) const, // will include virtual/nonexistent pixels in matrix getLengthTotal() const, // will include virtual/nonexistent pixels in matrix
getFps() const, getFps() const,
getMappedPixelIndex(uint16_t index) const; getMappedPixelIndex(uint16_t index) const;
inline uint16_t getFrameTime(void) const { return _frametime; } // returns amount of time a frame should take (in ms) inline uint16_t getFrameTime() const { return _frametime; } // returns amount of time a frame should take (in ms)
inline uint16_t getMinShowDelay(void) const { return MIN_SHOW_DELAY; } // returns minimum amount of time strip.service() can be delayed (constant) inline uint16_t getMinShowDelay() const { return MIN_SHOW_DELAY; } // returns minimum amount of time strip.service() can be delayed (constant)
inline uint16_t getLength(void) const { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H) 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(void) const { return _transitionDur; } // returns currently set transition time (in ms) inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms)
uint32_t uint32_t
now, now,
timebase, timebase,
getPixelColor(uint16_t) const; getPixelColor(uint16_t) const;
inline uint32_t getLastShow(void) const { return _lastShow; } // returns millis() timestamp of last strip.show() call inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call
inline uint32_t segColor(uint8_t i) const { 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 segColor(uint8_t i) const { return _colors_t[i]; } // returns currently valid color (for slot i) AKA SEGCOLOR(); may be blended between two colors while in transition
const char * const char *
getModeData(uint8_t id = 0) const { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); } getModeData(uint8_t id = 0) const { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
const char ** const char **
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data getModeDataSrc() { return &(_modeData[0]); } // vectors use arrays for underlying data
Segment& getSegment(uint8_t id); Segment& getSegment(uint8_t id);
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; } // returns reference to first segment that is "selected" inline Segment& getFirstSelectedSeg() { 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& getMainSegment() { return _segments[getMainSegmentId()]; } // returns reference to main segment
inline Segment* getSegments(void) { return &(_segments[0]); } // returns pointer to segment vector structure (warning: use carefully) inline Segment* getSegments() { return &(_segments[0]); } // returns pointer to segment vector structure (warning: use carefully)
// 2D support (panels) // 2D support (panels)
bool bool
@ -908,7 +908,7 @@ class WS2812FX { // 96 bytes
// end 2D support // end 2D support
void loadCustomPalettes(void); // loads custom palettes from JSON void loadCustomPalettes(); // loads custom palettes from JSON
std::vector<CRGBPalette16> customPalettes; // TODO: move custom palettes out of WS2812FX class std::vector<CRGBPalette16> customPalettes; // TODO: move custom palettes out of WS2812FX class
struct { struct {

View File

@ -161,7 +161,7 @@ void WS2812FX::setUpMatrix() {
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element) // XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
uint16_t IRAM_ATTR_YN Segment::XY(uint16_t x, uint16_t y) uint16_t IRAM_ATTR_YN Segment::XY(int x, int y)
{ {
unsigned width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive) unsigned width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
unsigned height = virtualHeight(); // segment height in logical pixels (is always >= 1) unsigned height = virtualHeight(); // segment height in logical pixels (is always >= 1)

View File

@ -1197,7 +1197,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
//do not call this method from system context (network callback) //do not call this method from system context (network callback)
void WS2812FX::finalizeInit(void) { void WS2812FX::finalizeInit() {
//reset segment runtimes //reset segment runtimes
for (segment &seg : _segments) { for (segment &seg : _segments) {
seg.markForReset(); seg.markForReset();
@ -1366,7 +1366,7 @@ uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) const {
return BusManager::getPixelColor(i); return BusManager::getPixelColor(i);
} }
void WS2812FX::show(void) { void WS2812FX::show() {
// avoid race condition, capture _callback value // avoid race condition, capture _callback value
show_callback callback = _callback; show_callback callback = _callback;
if (callback) callback(); if (callback) callback();
@ -1463,7 +1463,7 @@ uint8_t WS2812FX::getActiveSegsLightCapabilities(bool selectedOnly) const {
return totalLC; return totalLC;
} }
uint8_t WS2812FX::getFirstSelectedSegId(void) const { uint8_t WS2812FX::getFirstSelectedSegId() const {
size_t i = 0; size_t i = 0;
for (const segment &seg : _segments) { for (const segment &seg : _segments) {
if (seg.isActive() && seg.isSelected()) return i; if (seg.isActive() && seg.isSelected()) return i;
@ -1481,14 +1481,14 @@ void WS2812FX::setMainSegmentId(uint8_t n) {
return; return;
} }
uint8_t WS2812FX::getLastActiveSegmentId(void) const { uint8_t WS2812FX::getLastActiveSegmentId() const {
for (size_t i = _segments.size() -1; i > 0; i--) { for (size_t i = _segments.size() -1; i > 0; i--) {
if (_segments[i].isActive()) return i; if (_segments[i].isActive()) return i;
} }
return 0; return 0;
} }
uint8_t WS2812FX::getActiveSegmentsNum(void) const { uint8_t WS2812FX::getActiveSegmentsNum() const {
uint8_t c = 0; uint8_t c = 0;
for (size_t i = 0; i < _segments.size(); i++) { for (size_t i = 0; i < _segments.size(); i++) {
if (_segments[i].isActive()) c++; if (_segments[i].isActive()) c++;
@ -1496,13 +1496,13 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) const {
return c; return c;
} }
uint16_t WS2812FX::getLengthTotal(void) const { uint16_t WS2812FX::getLengthTotal() const {
unsigned len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D unsigned len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
return len; return len;
} }
uint16_t WS2812FX::getLengthPhysical(void) const { uint16_t WS2812FX::getLengthPhysical() const {
unsigned len = 0; unsigned len = 0;
for (size_t b = 0; b < BusManager::getNumBusses(); b++) { for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
Bus *bus = BusManager::getBus(b); Bus *bus = BusManager::getBus(b);
@ -1515,7 +1515,7 @@ uint16_t WS2812FX::getLengthPhysical(void) const {
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw. //used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
//returns if there is an RGBW bus (supports RGB and White, not only white) //returns if there is an RGBW bus (supports RGB and White, not only white)
//not influenced by auto-white mode, also true if white slider does not affect output white channel //not influenced by auto-white mode, also true if white slider does not affect output white channel
bool WS2812FX::hasRGBWBus(void) const { bool WS2812FX::hasRGBWBus() const {
for (size_t b = 0; b < BusManager::getNumBusses(); b++) { for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
Bus *bus = BusManager::getBus(b); Bus *bus = BusManager::getBus(b);
if (bus == nullptr || bus->getLength()==0) break; if (bus == nullptr || bus->getLength()==0) break;
@ -1524,7 +1524,7 @@ bool WS2812FX::hasRGBWBus(void) const {
return false; return false;
} }
bool WS2812FX::hasCCTBus(void) const { bool WS2812FX::hasCCTBus() const {
if (cctFromRgb && !correctWB) return false; if (cctFromRgb && !correctWB) return false;
for (size_t b = 0; b < BusManager::getNumBusses(); b++) { for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
Bus *bus = BusManager::getBus(b); Bus *bus = BusManager::getBus(b);

View File

@ -37,6 +37,8 @@ uint32_t color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16)
*/ */
uint32_t color_add(uint32_t c1, uint32_t c2, bool fast) uint32_t color_add(uint32_t c1, uint32_t c2, bool fast)
{ {
if (c1 == BLACK) return c2;
if (c2 == BLACK) return c1;
if (fast) { if (fast) {
uint8_t r = R(c1); uint8_t r = R(c1);
uint8_t g = G(c1); uint8_t g = G(c1);
@ -68,17 +70,18 @@ uint32_t color_add(uint32_t c1, uint32_t c2, bool fast)
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
{ {
if (c1 == BLACK || amount + video == 0) return BLACK;
uint32_t scaledcolor; // color order is: W R G B from MSB to LSB uint32_t scaledcolor; // color order is: W R G B from MSB to LSB
uint32_t r = R(c1); uint32_t r = R(c1);
uint32_t g = G(c1); uint32_t g = G(c1);
uint32_t b = B(c1); uint32_t b = B(c1);
uint32_t w = W(c1); uint32_t w = W(c1);
uint32_t scale = amount + !video; // 32bit for faster calculation uint32_t scale = amount; // 32bit for faster calculation
if (video) { if (video) {
scaledcolor = (((r * scale) >> 8) << 16) + ((r && scale) ? 1 : 0); scaledcolor = (((r * scale) >> 8) + ((r && scale) ? 1 : 0)) << 16;
scaledcolor |= (((g * scale) >> 8) << 8) + ((g && scale) ? 1 : 0); scaledcolor |= (((g * scale) >> 8) + ((g && scale) ? 1 : 0)) << 8;
scaledcolor |= ((b * scale) >> 8) + ((b && scale) ? 1 : 0); scaledcolor |= ((b * scale) >> 8) + ((b && scale) ? 1 : 0);
scaledcolor |= (((w * scale) >> 8) << 24) + ((w && scale) ? 1 : 0); scaledcolor |= (((w * scale) >> 8) + ((w && scale) ? 1 : 0)) << 24;
} else { } else {
scaledcolor = ((r * scale) >> 8) << 16; scaledcolor = ((r * scale) >> 8) << 16;
scaledcolor |= ((g * scale) >> 8) << 8; scaledcolor |= ((g * scale) >> 8) << 8;
@ -195,7 +198,7 @@ CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette)
RGBpalettecolors[3]); RGBpalettecolors[3]);
} }
CRGBPalette16 generateRandomPalette(void) //generate fully random palette CRGBPalette16 generateRandomPalette() //generate fully random palette
{ {
return CRGBPalette16(CHSV(random8(), random8(160, 255), random8(128, 255)), return CRGBPalette16(CHSV(random8(), random8(160, 255), random8(128, 255)),
CHSV(random8(), random8(160, 255), random8(128, 255)), CHSV(random8(), random8(160, 255), random8(128, 255)),
@ -476,14 +479,14 @@ void NeoGammaWLEDMethod::calcGammaTable(float gamma)
} }
} }
uint8_t NeoGammaWLEDMethod::Correct(uint8_t value) uint8_t IRAM_ATTR NeoGammaWLEDMethod::Correct(uint8_t value)
{ {
if (!gammaCorrectCol) return value; if (!gammaCorrectCol) return value;
return gammaT[value]; return gammaT[value];
} }
// used for color gamma correction // used for color gamma correction
uint32_t NeoGammaWLEDMethod::Correct32(uint32_t color) uint32_t IRAM_ATTR NeoGammaWLEDMethod::Correct32(uint32_t color)
{ {
if (!gammaCorrectCol) return color; if (!gammaCorrectCol) return color;
uint8_t w = W(color); uint8_t w = W(color);

View File

@ -69,20 +69,20 @@ typedef struct WiFiConfig {
// similar to NeoPixelBus NeoGammaTableMethod but allows dynamic changes (superseded by NPB::NeoGammaDynamicTableMethod) // similar to NeoPixelBus NeoGammaTableMethod but allows dynamic changes (superseded by NPB::NeoGammaDynamicTableMethod)
class NeoGammaWLEDMethod { class NeoGammaWLEDMethod {
public: public:
static uint8_t Correct(uint8_t value); // apply Gamma to single channel [[gnu::hot]] static uint8_t Correct(uint8_t value); // apply Gamma to single channel
static uint32_t Correct32(uint32_t color); // apply Gamma to RGBW32 color (WLED specific, not used by NPB) [[gnu::hot]] static uint32_t Correct32(uint32_t color); // apply Gamma to RGBW32 color (WLED specific, not used by NPB)
static void calcGammaTable(float gamma); // re-calculates & fills gamma table static void calcGammaTable(float gamma); // re-calculates & fills gamma table
static inline uint8_t rawGamma8(uint8_t val) { return gammaT[val]; } // get value from Gamma table (WLED specific, not used by NPB) static inline uint8_t rawGamma8(uint8_t val) { return gammaT[val]; } // get value from Gamma table (WLED specific, not used by NPB)
private: private:
static uint8_t gammaT[]; static uint8_t gammaT[];
}; };
#define gamma32(c) NeoGammaWLEDMethod::Correct32(c) #define gamma32(c) NeoGammaWLEDMethod::Correct32(c)
#define gamma8(c) NeoGammaWLEDMethod::rawGamma8(c) #define gamma8(c) NeoGammaWLEDMethod::rawGamma8(c)
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false); [[gnu::hot]] uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
uint32_t color_add(uint32_t,uint32_t, bool fast=false); [[gnu::hot]] uint32_t color_add(uint32_t,uint32_t, bool fast=false);
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false); [[gnu::hot]] uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false);
CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette); CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette);
CRGBPalette16 generateRandomPalette(void); CRGBPalette16 generateRandomPalette();
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); } inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
void colorKtoRGB(uint16_t kelvin, byte* rgb); void colorKtoRGB(uint16_t kelvin, byte* rgb);