Optimisations.
This commit is contained in:
parent
1abf0fc134
commit
f16558c126
@ -75,7 +75,7 @@ int8_t tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec) {
|
||||
*/
|
||||
uint16_t mode_static(void) {
|
||||
SEGMENT.fill(SEGCOLOR(0));
|
||||
return (SEGMENT.getOption(SEG_OPTION_TRANSITIONAL)) ? FRAMETIME : 350; //update faster if in transition
|
||||
return /*(SEGMENT.getOption(SEG_OPTION_TRANSITIONAL)) ? FRAMETIME :*/ 350; //update faster if in transition
|
||||
}
|
||||
static const char *_data_FX_MODE_STATIC PROGMEM = "Solid";
|
||||
|
||||
|
41
wled00/FX.h
41
wled00/FX.h
@ -56,10 +56,6 @@
|
||||
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||
#endif
|
||||
|
||||
//colors.cpp (.h does not like including other .h)
|
||||
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16);
|
||||
uint32_t color_add(uint32_t,uint32_t);
|
||||
|
||||
/* Not used in all effects yet */
|
||||
#define WLED_FPS 42
|
||||
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
||||
@ -71,12 +67,12 @@ uint32_t color_add(uint32_t,uint32_t);
|
||||
#ifdef ESP8266
|
||||
#define MAX_NUM_SEGMENTS 16
|
||||
/* How much data bytes all segments combined may allocate */
|
||||
#define MAX_SEGMENT_DATA 4096
|
||||
#define MAX_SEGMENT_DATA 5120
|
||||
#else
|
||||
#ifndef MAX_NUM_SEGMENTS
|
||||
#define MAX_NUM_SEGMENTS 32
|
||||
#endif
|
||||
#define MAX_SEGMENT_DATA 32768
|
||||
#define MAX_SEGMENT_DATA 32767
|
||||
#endif
|
||||
|
||||
/* How much data bytes each segment should max allocate to leave enough space for other segments,
|
||||
@ -88,7 +84,7 @@ uint32_t color_add(uint32_t,uint32_t);
|
||||
#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[s//trip.getCurrSegmentId()].currentColor(x, strip._segments[strip.getCurrSegmentId()].colors[x])
|
||||
//#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
|
||||
@ -427,6 +423,7 @@ typedef struct Segment {
|
||||
};
|
||||
};
|
||||
uint16_t _dataLen;
|
||||
static uint16_t _usedSegmentData;
|
||||
|
||||
// transition data, valid only if getOption(SEG_OPTION_TRANSITIONAL)==true, holds values during transition
|
||||
//struct Transition {
|
||||
@ -504,23 +501,27 @@ typedef struct Segment {
|
||||
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
|
||||
inline bool isSelected(void) { return getOption(0); }
|
||||
inline bool isActive(void) { return stop > start; }
|
||||
inline bool is2D(void) { return !(startY == 0 && stopY == 1); }
|
||||
inline uint16_t width(void) { return stop - start; }
|
||||
inline uint16_t height(void) { return stopY - startY; }
|
||||
inline uint16_t length(void) { return width(); }
|
||||
inline uint16_t groupLength(void) { return grouping + spacing; }
|
||||
inline uint8_t getLightCapabilities(void) { return _capabilities; }
|
||||
|
||||
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);
|
||||
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
|
||||
static void addUsedSegmentData(int len) { _usedSegmentData += len; }
|
||||
|
||||
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);
|
||||
uint8_t differs(Segment& b);
|
||||
void refreshLightCapabilities(void);
|
||||
void refreshLightCapabilities(void);
|
||||
|
||||
// runtime data functions
|
||||
bool allocateData(uint16_t len);
|
||||
void deallocateData(void);
|
||||
inline uint16_t dataSize(void) { return _dataLen; }
|
||||
bool allocateData(size_t len);
|
||||
void deallocateData(void);
|
||||
void resetIfRequired(void);
|
||||
/**
|
||||
* Flags that before the next effect is calculated,
|
||||
@ -531,11 +532,11 @@ typedef struct Segment {
|
||||
inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true)
|
||||
|
||||
// transition functions
|
||||
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
||||
void handleTransition(void);
|
||||
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
||||
void handleTransition(void);
|
||||
uint16_t progress(void); //transition progression between 0-65535
|
||||
uint8_t currentBri(uint8_t briNew, bool useCct = false);
|
||||
uint32_t currentColor(uint8_t slot, uint32_t colorNew) { return getOption(SEG_OPTION_TRANSITIONAL) /*&& !_t*/ ? color_blend(/*_t->*/_colorT[slot], colorNew, progress(), true) : colorNew; }
|
||||
uint32_t currentColor(uint8_t slot, uint32_t colorNew);
|
||||
CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
|
||||
CRGBPalette16 ¤tPalette(CRGBPalette16 &tgt, uint8_t paletteID);
|
||||
|
||||
@ -633,13 +634,11 @@ class WS2812FX { // 96 bytes
|
||||
#endif
|
||||
// semi-private (just obscured) used in effect functions through macros
|
||||
_currentPalette(CRGBPalette16(CRGB::Black)),
|
||||
_bri_t(0),
|
||||
_colors_t{0,0,0},
|
||||
_virtualSegmentLength(0),
|
||||
// true private variables
|
||||
_length(DEFAULT_LED_COUNT),
|
||||
_brightness(DEFAULT_BRIGHTNESS),
|
||||
_usedSegmentData(0),
|
||||
_transitionDur(750),
|
||||
_targetFps(WLED_FPS),
|
||||
_frametime(FRAMETIME_FIXED),
|
||||
@ -707,7 +706,6 @@ class WS2812FX { // 96 bytes
|
||||
inline void setShowCallback(show_callback cb) { _callback = cb; }
|
||||
inline void setTransition(uint16_t t) { _transitionDur = t; }
|
||||
inline void appendSegment(const Segment &seg = Segment()) { _segments.push_back(seg); }
|
||||
inline void addUsedSegmentData(int16_t size) { _usedSegmentData += size; }
|
||||
|
||||
bool
|
||||
gammaCorrectBri,
|
||||
@ -753,7 +751,6 @@ class WS2812FX { // 96 bytes
|
||||
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; }
|
||||
inline uint16_t getLengthTotal(void) { return _length; }
|
||||
inline uint16_t getTransition(void) { return _transitionDur; }
|
||||
inline uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
|
||||
|
||||
uint32_t
|
||||
now,
|
||||
@ -823,7 +820,6 @@ class WS2812FX { // 96 bytes
|
||||
|
||||
// using public variables to reduce code size increase due to inline function getSegment() (with bounds checking)
|
||||
// and color transitions
|
||||
uint8_t _bri_t; // opacity used for effect (includes transition)
|
||||
uint32_t _colors_t[3]; // color used for effect (includes transition)
|
||||
uint16_t _virtualSegmentLength;
|
||||
|
||||
@ -833,7 +829,6 @@ class WS2812FX { // 96 bytes
|
||||
private:
|
||||
uint16_t _length;
|
||||
uint8_t _brightness;
|
||||
uint16_t _usedSegmentData;
|
||||
uint16_t _transitionDur;
|
||||
|
||||
uint8_t _targetFps;
|
||||
|
@ -152,8 +152,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (!strip.isMatrix) return; // not a matrix set-up
|
||||
|
||||
uint8_t _bri_t = strip._bri_t;
|
||||
//uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
|
||||
uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
|
||||
if (_bri_t < 255) {
|
||||
byte r = scale8(R(col), _bri_t);
|
||||
byte g = scale8(G(col), _bri_t);
|
||||
|
@ -73,6 +73,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Segment class implementation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for their data[]
|
||||
|
||||
Segment::Segment(const Segment &orig) {
|
||||
DEBUG_PRINTLN(F("-- Segment duplicated --"));
|
||||
@ -138,11 +139,10 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Segment::allocateData(uint16_t len) {
|
||||
bool Segment::allocateData(size_t len) {
|
||||
if (data && _dataLen == len) return true; //already allocated
|
||||
deallocateData();
|
||||
// TODO: move out to WS2812FX class: for (seg : _segments) sum += seg.dataSize();
|
||||
if (strip.getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||
// if possible use SPI RAM on ESP32
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound())
|
||||
@ -151,7 +151,7 @@ bool Segment::allocateData(uint16_t len) {
|
||||
#endif
|
||||
data = (byte*) malloc(len);
|
||||
if (!data) return false; //allocation failed
|
||||
strip.addUsedSegmentData(len); // TODO: move out to WS2812FX class: for (seg : _segments) sum += seg.dataSize();
|
||||
Segment::addUsedSegmentData(len);
|
||||
_dataLen = len;
|
||||
memset(data, 0, len);
|
||||
DEBUG_PRINTF("-- Allocated data %p (%d)\n", data, (int)len);
|
||||
@ -159,13 +159,12 @@ bool Segment::allocateData(uint16_t len) {
|
||||
}
|
||||
|
||||
void Segment::deallocateData() {
|
||||
// NOTE: deallocating data sometimes produces corrupt heap.
|
||||
if (!data) return;
|
||||
DEBUG_PRINTF("-- Deallocating data: %p (%d)\n", data, (int)_dataLen);
|
||||
free(data);
|
||||
DEBUG_PRINTLN(F("-- Data freed."));
|
||||
data = nullptr;
|
||||
strip.addUsedSegmentData(-(int16_t)_dataLen); // TODO: move out to WS2812FX class: for (seg : _segments) sum -= seg.dataSize();
|
||||
Segment::addUsedSegmentData(-_dataLen);
|
||||
_dataLen = 0;
|
||||
DEBUG_PRINTLN(F("-- Dealocated data."));
|
||||
}
|
||||
@ -216,16 +215,20 @@ uint16_t Segment::progress() { //transition progression between 0-65535
|
||||
}
|
||||
|
||||
uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
|
||||
//if (!_t) return (useCct) ? cct : opacity;
|
||||
//if (_t) {
|
||||
if (getOption(SEG_OPTION_TRANSITIONAL)) {
|
||||
uint32_t prog = progress() + 1;
|
||||
if (useCct) return ((briNew * prog) + /*_t->*/_cctT * (0x10000 - prog)) >> 16;
|
||||
else return ((briNew * prog) + /*_t->*/_briT * (0x10000 - prog)) >> 16;
|
||||
} else {
|
||||
return (useCct) ? cct : (getOption(SEG_OPTION_ON) ? opacity : 0);
|
||||
return briNew;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) {
|
||||
return getOption(SEG_OPTION_TRANSITIONAL) /*&& _t*/ ? color_blend(/*_t->*/_colorT[slot], colorNew, progress(), true) : colorNew;
|
||||
}
|
||||
|
||||
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment
|
||||
byte tcp[72];
|
||||
@ -375,7 +378,7 @@ uint16_t Segment::virtualHeight() {
|
||||
// 1D strip
|
||||
uint16_t Segment::virtualLength() {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (height() > 1) {
|
||||
if (is2D()) {
|
||||
uint16_t vW = virtualWidth();
|
||||
uint16_t vH = virtualHeight();
|
||||
uint32_t vLen = vW * vH; // use all pixels from segment
|
||||
@ -400,7 +403,7 @@ uint16_t Segment::virtualLength() {
|
||||
void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (height() > 1) { // if this does not work use strip.isMatrix
|
||||
if (is2D()) { // if this does not work use strip.isMatrix
|
||||
uint16_t vH = virtualHeight(); // segment height in logical pixels
|
||||
uint16_t vW = virtualWidth();
|
||||
switch (map1D2D) {
|
||||
@ -431,8 +434,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
#endif
|
||||
|
||||
uint16_t len = length();
|
||||
uint8_t _bri_t = strip._bri_t;
|
||||
//uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
|
||||
uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
|
||||
if (_bri_t < 255) {
|
||||
byte r = scale8(R(col), _bri_t);
|
||||
byte g = scale8(G(col), _bri_t);
|
||||
@ -501,7 +503,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
||||
uint32_t Segment::getPixelColor(uint16_t i)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (height() > 1) { // if this does not work use strip.isMatrix
|
||||
if (is2D()) { // if this does not work use strip.isMatrix
|
||||
uint16_t vH = virtualHeight(); // segment height in logical pixels
|
||||
uint16_t vW = virtualWidth();
|
||||
switch (map1D2D) {
|
||||
@ -589,11 +591,11 @@ void Segment::refreshLightCapabilities() {
|
||||
* Fills segment with color
|
||||
*/
|
||||
void Segment::fill(uint32_t c) {
|
||||
const uint16_t cols = strip.isMatrix ? virtualWidth() : virtualLength();
|
||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||
if (strip.isMatrix) setPixelColorXY(x, y, c);
|
||||
else setPixelColor(x, c);
|
||||
if (is2D()) setPixelColorXY(x, y, c);
|
||||
else setPixelColor(x, c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,7 +613,7 @@ void Segment::addPixelColor(uint16_t n, uint32_t color) {
|
||||
* fade out function, higher rate = quicker fade
|
||||
*/
|
||||
void Segment::fade_out(uint8_t rate) {
|
||||
const uint16_t cols = strip.isMatrix ? virtualWidth() : virtualLength();
|
||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||
|
||||
rate = (255-rate) >> 1;
|
||||
@ -624,7 +626,7 @@ void Segment::fade_out(uint8_t rate) {
|
||||
int b2 = B(color);
|
||||
|
||||
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||
color = strip.isMatrix ? getPixelColorXY(x, y) : getPixelColor(x);
|
||||
color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
|
||||
int w1 = W(color);
|
||||
int r1 = R(color);
|
||||
int g1 = G(color);
|
||||
@ -641,19 +643,19 @@ void Segment::fade_out(uint8_t rate) {
|
||||
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
||||
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
|
||||
|
||||
if (strip.isMatrix) setPixelColorXY(x, y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
else setPixelColor(x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
if (is2D()) setPixelColorXY(x, y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
else setPixelColor(x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
}
|
||||
}
|
||||
|
||||
// fades all pixels to black using nscale8()
|
||||
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||
const uint16_t cols = strip.isMatrix ? virtualWidth() : virtualLength();
|
||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||
|
||||
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||
if (strip.isMatrix) setPixelColorXY(x, y, CRGB(getPixelColorXY(x,y)).nscale8(255-fadeBy));
|
||||
else setPixelColor(x, CRGB(getPixelColor(x)).nscale8(255-fadeBy));
|
||||
if (is2D()) setPixelColorXY(x, y, CRGB(getPixelColorXY(x,y)).nscale8(255-fadeBy));
|
||||
else setPixelColor(x, CRGB(getPixelColor(x)).nscale8(255-fadeBy));
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,7 +664,8 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||
*/
|
||||
void Segment::blur(uint8_t blur_amount)
|
||||
{
|
||||
if (strip.isMatrix) {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (is2D()) {
|
||||
// compatibility with 2D
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
@ -670,6 +673,7 @@ void Segment::blur(uint8_t blur_amount)
|
||||
for (uint16_t k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
@ -844,25 +848,24 @@ void WS2812FX::service() {
|
||||
|
||||
if (!seg.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
|
||||
_virtualSegmentLength = seg.virtualLength();
|
||||
_bri_t = seg.currentBri(seg.getOption(SEG_OPTION_ON) ? seg.opacity : 0);
|
||||
uint8_t _cct_t = seg.currentBri(seg.cct, true);
|
||||
_colors_t[0] = seg.currentColor(0, seg.colors[0]);
|
||||
_colors_t[1] = seg.currentColor(1, seg.colors[1]);
|
||||
_colors_t[2] = seg.currentColor(2, seg.colors[2]);
|
||||
_colors_t[0] = seg.currentColor(0, seg.colors[0]);
|
||||
_colors_t[1] = seg.currentColor(1, seg.colors[1]);
|
||||
_colors_t[2] = seg.currentColor(2, seg.colors[2]);
|
||||
seg.currentPalette(_currentPalette, seg.palette);
|
||||
|
||||
seg.handleTransition();
|
||||
|
||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(_cct_t, correctWB);
|
||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB);
|
||||
for (uint8_t c = 0; c < NUM_COLORS; c++) {
|
||||
_colors_t[c] = gamma32(_colors_t[c]);
|
||||
}
|
||||
|
||||
seg.handleTransition();
|
||||
|
||||
// effect blending (execute previous effect)
|
||||
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
||||
//if (getOption(SEG_OPTION_TRANSITIONAL) && seg._modeP) (*_mode[seg._modeP])(progress());
|
||||
delay = (*_mode[seg.mode])();
|
||||
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
||||
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // foce faster updates during transition
|
||||
}
|
||||
|
||||
seg.next_time = nowUp + delay;
|
||||
|
Loading…
Reference in New Issue
Block a user