some effect optimizations

* getpixelcolor: attribute pure - it reads memory, but does not write
* some optimizations for SEGMENT.blur() and SEGMENT.fadeToBlackBy()

* FX.c:pp remove double calls to blur() and fade_out()
* FX.cpp: SEGMENT.setUpLeds() added to effects, to enable LED buffering (safe some time because getPixelColor does not need to access NeopixelBus)

* a few other optimizations to safe time and avoid "expensive" operations
* set I2C bus speed to 400kHz (default is 100Khz)

* a few other small optimizations and tweaks
* pio: esp32 V4 builds use "patch5" toolchain version, which contains a few bugfixes especially for memory management.
This commit is contained in:
Frank
2023-05-03 20:33:23 +02:00
parent 91d36fa269
commit 7d0e627e14
12 changed files with 66 additions and 31 deletions

View File

@@ -915,7 +915,9 @@ lib_deps = ${esp32_4MB_M_base.lib_deps} ${common_mm.lib_deps_XL}
board = esp32dev
upload_speed = 460800 ; or 921600
platform = ${esp32.platformV4}
platform_packages = ${esp32.platformV4_packages}
platform_packages =
${esp32.platformV4_packages}
toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5 ; align main tools with riscV tools
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32.build_flagsV4} ${common_mm.build_flags_S}
-Wno-misleading-indentation -Wno-format-truncation

View File

@@ -6042,6 +6042,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli
// printUmData();
if (SEGENV.call == 0) {
SEGMENT.setUpLeds();
SEGENV.aux0 = 255;
SEGMENT.custom1 = *binNum;
SEGMENT.custom2 = *maxVol * 2;
@@ -6052,8 +6053,9 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli
*binNum = SEGMENT.custom1; // Select a bin.
*maxVol = SEGMENT.custom2 / 2; // Our volume comparator.
SEGMENT.fade_out(240); // Lower frame rate means less effective fading than FastLED
SEGMENT.fade_out(240);
//SEGMENT.fade_out(240); // Lower frame rate means less effective fading than FastLED
//SEGMENT.fade_out(240);
SEGMENT.fade_out(224); // should be the same as 240 applied twice
for (int i = 0; i < SEGMENT.intensity/16; i++) { // Limit the number of ripples.
if (samplePeak) ripples[i].state = 255;
@@ -6066,7 +6068,8 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli
ripples[i].pos = random16(SEGLEN);
#ifdef ESP32
if (FFT_MajorPeak > 1) // log10(0) is "forbidden" (throws exception)
ripples[i].color = (int)(log10f(FFT_MajorPeak)*128);
//ripples[i].color = (int)(log10f(FFT_MajorPeak)*128); // not to self: buggy !!
ripples[i].color = (int)(logf(FFT_MajorPeak)*32.0f); // works up to 10025 hz
else ripples[i].color = 0;
#else
ripples[i].color = random8();
@@ -6476,8 +6479,12 @@ uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline.
}
float volumeSmth = *(float*) um_data->u_data[0];
SEGMENT.fade_out(SEGMENT.speed);
SEGMENT.fade_out(SEGMENT.speed);
if (SEGENV.call == 0) {
SEGMENT.setUpLeds();
SEGMENT.fill(BLACK);
}
SEGMENT.fadeToBlackBy(SEGMENT.speed/2);
//SEGMENT.fade_out(SEGMENT.speed);
float tmpSound2 = volumeSmth * (float)SEGMENT.intensity / 256.0; // Too sensitive.
tmpSound2 *= (float)SEGMENT.intensity / 128.0; // Reduce sensitity/length.
@@ -6622,8 +6629,13 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline.
}
float volumeSmth = *(float*) um_data->u_data[0];
SEGMENT.fadeToBlackBy(32);
if (SEGENV.call == 0) {
SEGMENT.setUpLeds();
SEGMENT.fill(BLACK);
}
//SEGMENT.fadeToBlackBy(32);
SEGMENT.fadeToBlackBy(48);
plasmoip->thisphase += beatsin8(6,-4,4); // You can change direction and speed individually.
plasmoip->thatphase += beatsin8(7,-4,4); // Two phase values to make a complex pattern. By Andrew Tuline.
@@ -6921,7 +6933,10 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN.
float my_magnitude = *(float*)um_data->u_data[5] / 4.0f;
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
if (SEGENV.call == 0) {
SEGMENT.setUpLeds();
SEGMENT.fill(BLACK);
}
int fadeoutDelay = (256 - SEGMENT.speed) / 32;
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fade_out(SEGMENT.speed);
@@ -7068,7 +7083,7 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
SEGMENT.fill(BLACK);
}
uint8_t secondHand = micros()/(256-SEGMENT.speed)/500 % 16;
uint8_t secondHand = (SEGMENT.speed < 255) ? (micros()/(256-SEGMENT.speed)/500 % 16) : 0;
if((SEGMENT.speed > 254) || (SEGENV.aux0 != secondHand)) { // WLEDMM allow to run at full speed
SEGENV.aux0 = secondHand;

View File

@@ -571,7 +571,7 @@ typedef struct Segment {
void setPixelColor(float i, uint32_t c, bool aa = true);
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); }
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);
uint32_t __attribute__((pure)) getPixelColor(int i); // WLEDMM attribute added
// 1D support functions (some implement 2D as well)
void blur(uint8_t);
void fill(uint32_t c);
@@ -594,14 +594,14 @@ typedef struct Segment {
void createjMap(); //WLEDMM jMap
void deletejMap(); //WLEDMM jMap
#ifndef WLED_DISABLE_2D
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[])
uint16_t __attribute__((pure)) XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[]) // WLEDMM attribute pure
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline
void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } // automatically inline
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true, bool fast = true);
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); }
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);
uint32_t __attribute__((pure)) getPixelColorXY(uint16_t x, uint16_t y); // WLEDMM attribute pure
// 2D support functions
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend);
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); }

View File

@@ -1132,14 +1132,14 @@ void Segment::fade_out(uint8_t rate) {
uint_fast8_t fadeRate = (255-rate) >> 1;
float mappedRate_r = 1.0f / (float(fadeRate) +1.1f); // WLEDMM use reciprocal 1/mappedRate -> faster on non-FPU chips
uint32_t color = colors[1]; // SEGCOLOR(1); // target color
int w2 = W(color);
int r2 = R(color);
int g2 = G(color);
int b2 = B(color);
uint32_t color2 = colors[1]; // SEGCOLOR(1); // target color // WLEDMM minor optimization
int w2 = W(color2);
int r2 = R(color2);
int g2 = G(color2);
int b2 = B(color2);
for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
int w1 = W(color);
int r1 = R(color);
int g1 = G(color);
@@ -1156,6 +1156,7 @@ void Segment::fade_out(uint8_t rate) {
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
//if ((wdelta == 0) && (rdelta == 0) && (gdelta == 0) && (bdelta == 0)) continue; // WLEDMM delta = zero => no change // causes problem with text overlay
if (is2D()) setPixelColorXY((uint16_t)x, (uint16_t)y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
else setPixelColor((uint16_t)x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
}
@@ -1167,9 +1168,15 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
const uint_fast8_t scaledown = 255-fadeBy; // WLEDMM faster to pre-compute this
for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
if (is2D()) setPixelColorXY((uint16_t)x, (uint16_t)y, CRGB(getPixelColorXY(x,y)).nscale8(scaledown));
else setPixelColor((uint16_t)x, CRGB(getPixelColor(x)).nscale8(scaledown));
// WLEDMM minor optimization
if(is2D()) {
for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
setPixelColorXY((uint16_t)x, (uint16_t)y, CRGB(getPixelColorXY(x,y)).nscale8(scaledown));
}
} else {
for (uint_fast16_t x = 0; x < cols; x++) {
setPixelColor((uint16_t)x, CRGB(getPixelColor((uint16_t)x)).nscale8(scaledown));
}
}
}
@@ -1196,6 +1203,7 @@ void Segment::blur(uint8_t blur_amount)
{
CRGB cur = CRGB(getPixelColor(i));
CRGB part = cur;
CRGB before = cur; // WLEDMM
part.nscale8(seep);
cur.nscale8(keep);
cur += carryover;
@@ -1206,7 +1214,8 @@ void Segment::blur(uint8_t blur_amount)
uint8_t b = B(c);
setPixelColor((uint16_t)(i-1), qadd8(r, part.red), qadd8(g, part.green), qadd8(b, part.blue));
}
setPixelColor((uint16_t)i,cur.red, cur.green, cur.blue);
if (before != cur) // WLEDMM optimization: don't write same color again
setPixelColor((uint16_t)i,cur.red, cur.green, cur.blue);
carryover = part;
}
}

View File

@@ -420,7 +420,9 @@ BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
if (!_valid || pix >= _len) return;
if (hasWhite()) c = autoWhiteCalc(c);
#if !defined(WLEDMM_FASTPATH) // WLEDMM expensive operation
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
#endif
uint16_t offset = pix * _UDPchannels;
_data[offset] = R(c);
_data[offset+1] = G(c);

View File

@@ -288,7 +288,7 @@ class BusNetwork : public Bus {
void setPixelColor(uint16_t pix, uint32_t c);
uint32_t getPixelColor(uint16_t pix);
uint32_t __attribute__((pure)) getPixelColor(uint16_t pix); // WLEDMM attribute added
void show();
@@ -341,7 +341,7 @@ class BusManager {
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
uint32_t getPixelColor(uint_fast16_t pix);
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t pix); // WLEDMM attribute added
bool canAllShow();

View File

@@ -11,7 +11,7 @@ IRAM_ATTR_YN uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_
if(blend == 0) return color1;
uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF;
if(blend == blendmax) return color2;
uint_fast8_t shift = b16 ? 16 : 8;
const uint_fast8_t shift = b16 ? 16 : 8;
uint32_t w1 = W(color1);
uint32_t r1 = R(color1);

View File

@@ -88,7 +88,9 @@ void _overlayAnalogCountdown()
}
void handleOverlayDraw() {
#if !defined(WLEDMM_FASTPATH) // WLEDMM expensive operation, and most usermods don't draw overlays
usermods.handleOverlayDraw();
#endif
if (overlayCurrent == 1) _overlayAnalogClock();
}

View File

@@ -588,7 +588,11 @@ bool PinManagerClass::joinWire(int8_t pinSDA, int8_t pinSCL) {
}
#ifdef ARDUINO_ARCH_ESP32
#if defined(WLEDMM_FASTPATH) // wledMM set I2C to 400Khz, to minimize I2C communication delays
wireIsOK = Wire.begin(pinSDA, pinSCL, 400000UL); // this will fail if wire is already running
#else
wireIsOK = Wire.begin(pinSDA, pinSCL); // this will fail if wire is already running
#endif
#else
Wire.begin(pinSDA, pinSCL); // returns void on 8266
#endif

View File

@@ -232,11 +232,12 @@ void handleNotifications()
if (!udpConnected) return;
bool isSupp = false;
size_t packetSize = notifierUdp.parsePacket();
if (!packetSize && udp2Connected) {
int packetSize = notifierUdp.parsePacket(); // WLEDMM function returns int, not size_t
if ((packetSize < 1) && udp2Connected) {
packetSize = notifier2Udp.parsePacket();
isSupp = true;
}
if (packetSize < 1) packetSize = 0; // WLEDMM
//hyperion / raw RGB
if (!packetSize && udpRgbConnected) {

View File

@@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2304300
#define VERSION 2305030
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG

View File

@@ -185,8 +185,8 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static"
#ifndef WLED_DISABLE_2D
if (strip.isMatrix) {
buffer[1] = 2; //version
buffer[2] = Segment::maxWidth;
buffer[3] = Segment::maxHeight;
buffer[2] = min(Segment::maxWidth, (uint16_t) 255); // WLEDMM prevent overflow
buffer[3] = min(Segment::maxHeight, (uint16_t) 255);
//WLEDMM: no skipLines
}
#endif